Live data from Hacker News

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

cookieplmonster.github.io

191–200 of 315 posts

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

#191
post #88

My takeaway, speaking as someone who leans towards functional programming and immutability, is "this is yet another example of a mutability problem that could never happen in a functional context" (so, for example, this bug would have never been created by Rust unless it was deeply misused)

This is more of a problem of the C/C++ standard that it allows uninitialized variables but doesn't give them defined values, considering it "undefined behavior" to read from an uninitialized variable. Java, for example, doesn't have this particular problem because it does specify default values for variables.

But it's this and many other features of C/C++ that make it faster than Java. C/C++ developers really don't want to "pay" for something for safety.

Though, I really like the _mm_undefined_ps() intrinsics for SSE that make it clear that you're purposefully not initialising a variable. Something like that for ints and floats would be pretty sweet.

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

#192

> Not ignore the compilation warnings – this code most likely threw a warning in the original code that was either ignored or disabled! What compiler error would you expect here? Maybe not checking the return value from scanf to make sure it matches the number of parameters? Otherwise this seems like a data file error that the compiler would have no clue about.

Good point. When reading, I kind of just assumed the "use of initialised memory" warning would pick this up.

But because the whole line is parsed in a single sscanf call, the compiler's static analysis is forced to assume they have now initialised. There doesn't seem to be any generic static analysis approach that can catch this bug.

Though... you could make a specialised warning just for scanf that forced you to either pass in pre-initilized values or check the return result.

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

#193

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.

That's not accurate.

Generally, game console "debug" configurations aren't "true" debug like most people think of -- optimizations are still globally enabled, but the build generally has a number of debug systems enabled that naturally require the use of a devkit. Devkits, especially back then, generally had 2-3x as much memory as retail systems -- so you'd happily sacrifice framerate during feature development to have those systems enabled.

Debugging was (and still is) generally done on optimized builds and, once you know the general area of the problem, you simply disable optimizations for that file or subsystem if you can't pinpoint the issue in an optimized build.

The biggest performance hit, in general, comes from disabling optimizations in the compiler. I say "in general" because there are systems that might be used to find this kind of thing that DO make a game wholly unplayable, such as a stomp allocator. Of course, you wouldn't generally enable a stomp allocator across all your allocations unless you're desperate, so you could still have that enabled to find this kind of bug and end up with a playable game.

The more likely reason here is that no one noticed or cared. GTA:SA is 21 years old and this bug doesn't affect the Xbox or other versions.

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

#194

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.

The article discusses how that turns into an infinite loop and causes a hang.

When you subtract a small float from a very large float, the value doesn't change. This is because the "steps" between float values increase with the size of the value (i.e. floats have coarser resolution for larger magnitudes)

To see this in action, try running the following in a JavaScript interpreter:

console.log(1_000_000_000_000_000_000 - 1);

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

#195

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

I always wonder, why not write these games on top of a virtual machine like Carmack started doing in Quake, a usage he then later extended to quake 2 and 3 [1].

I'm ignorant about game development, virtual machines and system programming but from the little I understand it seems a sensible choice to make.

While there is an initial price to pay modeling 99% of the game to be implemented on a user-implemented stack seems a sensible approach to me.

[1] https://fabiensanglard.net/quake3/qvm.php

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

#196

Earlier quoted context omitted.

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.

That's not accurate. Generally, game console "debug" configurations aren't "true" debug like most people think of -- optimizations are still globally enabled, but the build generally has a number of debug systems enabled that naturally require the use of a devkit. Devkits, especially back then, generally had 2-3x as much memory as retail systems -- so you'd happily sacrifice framerate during feature development to ha…

From GP:

> (with checks for things like this enabled)

You can (and could) easily compile an optimized build with debug symbols to track down sources of issues, but catching a bug like this would likely take a dynamic checker like Valgrind or MSan, which do not allow for any optimizations if you want to avoid false negatives, and add even more overhead on top of that. (Valgrind with its full processor-level virtualization, and MSan with its shadow state on every access. But MSan didn't exist at the time, and Valgrind barely existed.)

At minimum, fine-grained stack randomization might have exposed the issue, but only if it happened to be spotted in playtests on the debug build.

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

#197

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 aroun…

This bug wasn't caused by a read beyond the current bounds of the stack, but a stale value from a prior call to the same function at the exact same location on the stack. Buffer-overflow protections like you describe wouldn't help here.

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

#198
post #2

[flagged]

After finishing the article I immediately did ctrl+f "rust" and was disappointed to not see any of the results I wanted, but actually this comment is more hilarious than anyone saying "why didnt rockstar use rust in 2004!!!1111!!???" it's a bit more of a sophisticated joke since there's an IYKYK factor but it is no less hilarious. Bravo sir, bravo.

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

#199
post #145

My takeaway, speaking as someone who leans towards functional programming and immutability, is "this is yet another example of a mutability problem that could never happen in a functional context" (so, for example, this bug would have never been created by Rust unless it was deeply misused)

The constant rust evangelism on this site is such a turn off from actually wanting to use the language.

While they did mention rust, the actual suggestion was "functional programming and immutability", which to me suggests several other languages first and makes it not really rust evangelism.

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

#200
post #179
post #164

Earlier quoted context omitted.

You both may be right. It could be that ASAN is not instrumenting scanf (or some other random standard lib function). Though since 2015, it certainly has been. https://github.com/google/sanitizers/issues/108 The simpler policy of "don't allow unintialized locals when declared" would also have caught it with the tools available when the game was made (though a bit ham-fisted).

The problem is that after calling scanf(), the number of variables that are defined is a variable number. For example: int x, y, z; int n = scanf("%d %d %d", &x, &y, &z); At compile time, you can make no inferences about which of x, y, and z are defined, because that depends on the returned value n. There are many ways to branch out from this. One is to insist on definite assignment - so if we cannot prove all of the…

The idea is that ASAN would replace scanf with a function that does additional book keeping when writing to whatever arbitrary memory location the inputs dictate at runtime.

It's probably what the PR resolving the issue I linked to does. Though I didn't check

Post reply on HN