Live data from Hacker News

How a 20 year old bug in GTA San Andreas surfaced in Windows 11 24H2

cookieplmonster.github.io

181–190 of 315 posts

Re: How a 20 year old bug in GTA San Andreas surfaced in Windows 11 24H2

#182
On Windows 11 24H2, more stack space was modified by a new implementation of Critical Sections.

IMHO this shows the downfall of Microsoft. Why did they do that? Critical sections have been there for many decades and should be basically bug-free by now. My best guess is someone thought they'd "improve" things and rewrote it, then made some microbenchmark that maybe showed the dubious improvement.

The other comment here mentions Raymond Chen, who wrote this article about why backwards-compatibility is very important (and arguably what got Microsoft into the position it's in today):

https://devblogs.microsoft.com/oldnewthing/20031224-00/?p=41...

and also this memorable case: https://news.ycombinator.com/item?id=2281932

Re: How a 20 year old bug in GTA San Andreas surfaced in Windows 11 24H2

#183
post #180
post #144

Earlier quoted context omitted.

> The compiler has no way of knowing that the memory would be undefined Yes it would. -fsanitize=address does a bunch of instrumentation - it allocates shadow memory to keep track of what main memory is defined, and it checks every read and write address against the shadow memory. It is a combination of compile-time instrumentation and run-time checking. And yes, it is expensive, so it should be used for debugging an…

I tried this with clang ASAN. Nothing happens. It won't catch this bug. ASAN detects the presence of incorrect behavior, not the absence of correct behavior. There's no use-after-free, use-after-return, use-after-scope, or OOB access here. It's a case of "an allocated stack variable is dynamically read without being initialized only in a runtime case," which afaik no standard analyzer will catch. The best way to iden…

Thanks for the investigation. Oops, it seems like MSan (memory sanitizer) is the appropriate tool that detects uninitialized reads? https://stackoverflow.com/questions/68576464/clang-sanitizer...

I only use UBSan and ASan on my own programs because I tend not to make mistakes about initialization. So my knowledge is incomplete with respect to auditing other people's code, which can have different classes of errors than mine.

Thank goodness that every language that is newer than C and C++ doesn't repeat these design mistakes, and doesn't require these awkward sanitizer tools that are introduced decades after the fact.

Re: How a 20 year old bug in GTA San Andreas surfaced in Windows 11 24H2

#184

Earlier quoted context omitted.

Raymond knows everything. From microcode bugs on Alpha AXP to template meta programming to UI.

I wonder how many times a Deloitte, PwC, KPMG, Bain, EY, McKinsey, or BCG consultant naively tried putting him on a shortlist for being “impacted” over the years because he was in the Top X of a spreadsheet sorted on Y.

"Look this guy's job seems to be mainly writing blog posts. We could replace that with AI and get it to regularly pitch the new Visual Enshitify 2.0 product launch as a bonus. Win win win!"

Re: How a 20 year old bug in GTA San Andreas surfaced in Windows 11 24H2

#185
post #117

IMHO, if something isn’t part of the contract, it should be randomized. Eg if iteration order of maps isn’t guaranteed in your language, then your language should go out of its way to randomize it. Otherwise, you end up with brittle code: code that works fine until it doesn’t.

Not really the ethos of C(++), though of course this particular bug would be easily caught by running a debug build (even 20 years ago). However, this being a game "true" debug builds were probably too slow to be usable. That was at least my experience doing gamedev in that timeframe. Then again code holding up for 20 years in that line of biz is more than sufficient anyway :)

When I was doing gamedev about 5 years ago, we were still debugging with optimisation on. You get a class of bugs just from running in lower frame rates that don't happen in release.

Re: How a 20 year old bug in GTA San Andreas surfaced in Windows 11 24H2

#186
post #142

Earlier quoted context omitted.

Then you are wasting runtime clock cycles randomizing lists.

Any sane language would design a list iterator to follow the order of the list. No, the difference is when you're iterating over orderless hash-based sets or maps/dictionaries. Many languages choose to leave the iteration order undefined. I think Python did that up to a point, but afterward they defined dictionaries (but not sets) to be iterated over in the order that keys were added. Also, some languages intentional…

Best change ever, that. Now it would also be nice if sets were ordered too.

Re: How a 20 year old bug in GTA San Andreas surfaced in Windows 11 24H2

#187

Use a debugger folks. A 10x dev cited this story to me about the ills of not using one.

This is a game; I don't think a debug configuration (with checks for things like this enabled) would run fast enough to be playable on contemporary hardware.

Re: How a 20 year old bug in GTA San Andreas surfaced in Windows 11 24H2

#188
post #167

Earlier quoted context omitted.

When I worked at Microsoft and I had downtime I would sometimes read the code for app compatibility shims out of pure curiosity. Win9x video games that made bad assumptions about the stack were a theme I saw. One of the differences between win9x and NT based windows is that kernel32 (later kernelbase) is a now user mode wrapper atop ntdll, whereas in the olden days kernel32 would trap directly into the kernel. This m…

What was the testing like for such bugs? Is it somehow automated, or is there a lengthy doc describing the manual testing steps, or are there no tests at all?

I don't know. I wasn't on the team doing this. I was just looking at the source tree.

Re: How a 20 year old bug in GTA San Andreas surfaced in Windows 11 24H2

#189

Am I the only one to be annoyed by this...? while (this->m_fBladeAngle > 6.2831855) { this->m_fBladeAngle = this->m_fBladeAngle - 6.2831855; } Like, "let's just write a while loop that could turn into an infinite loop coz I'm too lazy to do a division"

I'm willing to bet it was was done for performance reasons, subtraction is cheaper than float point division. Probably the compiler also has some tricks to optimize this further. There is absolutely no way this could turn into an infinite loop. It could underflow, but for that to happen angle would have to be less than the 2*pi, therefore exiting the loop.

If m_fBladeAngle is really large (>2.2e8 back of the envelope), the subtraction will have no effect, and that would be an infinite loop.

Re: How a 20 year old bug in GTA San Andreas surfaced in Windows 11 24H2

#190
It has always been too easy to read & write beyond the stack. This should fail, plain and simple.

Mitigations exist - ASLR, NX pages, stack-smashing protection etc. but nothing comprehensively stops reads of stale data beyond the stack.

Thought experiment for a moment. What if the hardware ensures the unused part of a stack region cannot be read or written.

There are many ways to skin this cat, here’s one based around tracking each stack’s start address A, size S, and current depth D

1. Add an instruction to inform the CPU there is a stack at address A of size S. Its depth D is initially 0.

2. Add a jump instruction which reserves N bytes on the stack at address A, growing depth D to (D+N). Maybe this can be its own “reserve” instruction so as not to need a new jump instruction.

3. Give existing return instructions stack awareness. If returning to an address inside a stack, un-reserve the bytes reserved by the most recent jump, making the new depth (D-N).

4. Fail reads or writes to the stack region beyond its current depth. In other words fail all reads and writes between A+S-D and A+S.

5. The arithmetic is reversed on architectures whose stacks grow downwards.

Downsides I can see:

It cements one calling convention. The CPU memory manager will need a lot of state per stack, of which there are many per process: address A, size S, current depth D, plus a reservation stack - ie. sizes of each frame’s stack memory. That’s a lot of bookkeeping! It’s far from zero cost. The limits of how much bookkeeping the CPU can do impose limits on how deep a stack can go and how many stacks are supported - so when there are too many stacks or one goes too deep, either the CPU needs to signal failure or engage a fallback mode and revert to behaving as CPUs do today. And of course fallback puts things back to the start. It’d therefore only mitigate situations in which an attacker cannot control the depth of the stack / a bug always happens inside the max depth the CPU can bookkeep for.

That said, stacks are ubiquitous! Hardware stack awareness opens up all kinds of new mitigations.

Why isn’t this a common idea? Has it been tried?

Post reply on HN