Live data from Hacker News

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

cookieplmonster.github.io

291–300 of 315 posts

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

#291

Earlier quoted context omitted.

You couldn't do random, but with a predictable performance hit to memory, cache and write-line use stack addresses COULD be isolated for a program, for a library, etc. It'd be expensive though; every context switch would require it's own stack and pushing / restoring one more register. There's GOOD reason programs don't work that way and are supposed to not rely on values outside of properly initialized (and not late…

It should be efficient though, that's the point. Specialized hardware or instructions should be able to zero the stack in a single cycle, instead it's much more expensive. Of course the problem with this is it could be used to hide things just as easily, making it impossible to reverse engineer an unknown exploit.

Why would a specialized instruction be necessary? 'the stack' is stored in memory just like everything else.

Expensive is the (very slow for modern CPUs) operation of _writing_ that change in value out to memory at it's distant and slow speed compared to that which the CPU operates at, as well as the overhead of synchronizing that write to any other caches of those memory locations.

Maybe you're thinking of the trick of a band new page of memory mapped memory that is 'zeroed' but is in reality just a special 'all zeros' page in the virtual to physical memory lookup table? Those still need to be zeroed by real writes at some point, if they're ever used.

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

#292

Earlier quoted context omitted.

Rust protects you from external file data you read being incorrect? That's one hell of a language!

The code would have failed because you can't use an uninitialized variable, so you would have had to set it to a default. You don't just get random garbage from the stack.

You can write a genuine uninitialized local variable in Rust, it's just that you wouldn't do it out of laziness because while in C that's the default in Rust it's a lot of extra work to say "No, I really don't want to initialize this variable" and Rust is like "I mean, if you insist, all I can do is warn you that's a terrible idea".

  int k;  // C makes an uninitialized variable named k - probably bad idea

  let k: i32 = unsafe { MaybeUninit::uninit().assume_init() };  // Rust, same bad idea
If we say "I will initialize it - later" that's fine in Rust and you just write the name (and where appropriate type) of the variable and go about your day. The compiler will reject your program if, in fact, it can't see why you're fulfilling that promise, and sometimes that might be because the compiler is dumb (but often it's because you are) but there's no problem technically with this and if the compiler agrees that we do, in fact, initialize it later then it compiles and works and everybody is happy.

But to actually make a variable and not initialize it, as we saw above, is a lot of extra work in Rust because like... that's a bad idea, why would you be setting out to do that?

This is such a bad idea that Rust's unsafe std::mem::uninitialized, which is how they did this before MaybeUninit existed, was de-fanged (giving it poor performance by actually writing a pattern to RAM every time) and deprecated so you get a warning if you try to use it even though it was already marked unsafe. See, people (and I'm sure many C programmers are like this) tend to imagine it's OK for say an integer to be uninitialized because surely any possible value is OK, right ? Nope. Your operating system knows that data was never written, and so it feels entitled to fuck you about if you expect it to stay unchanged, because it never promised that will work - as a result rarely but sometimes you get kicked in the head by the OS and you get a seemingly impossible bug.

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

#293
post #242

Earlier quoted context omitted.

There are fast instructions (e.g., REP STOSx, AVX zero stores, dc zva) and tricks (MTE, zero pages), but no magic CPU instruction exists that transparently and efficiently randomizes or zeros the stack on function calls. You think there would be one and I bet there are on some specialized high-security systems, but I'm not sure even where you would find such a product. Telecom certainly isn't it.

There are proposed cpu architectures that work that way, like the Mill https://millcomputing.com/ >. Where most cpus support multiple calling conventions the Mill enforces a single calling convention in hardware. There is a hardware `call` instruction that does all the work directly, along with a corresponding `ret` instruction for returning from a function call. It also uses its equivalent of the TLB to ensure that…

This is really interesting—how do stack references work in this design?

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

#294
post #260

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)

I think the response to that would be: yes but the game would simply not have been made if it wasn't written in C++. That's not to say you couldn't or that you can't make something like GTA:SA in Rust in 2025 or in a safer different language in the early 2000s. It just would take a great deal more time and expense as you'd have needed to construct a lot of tooling and do a lot of training to ensure all of the employe…

We don't have enough information to claim it's the "right decision" only that this choice did work, not that other choices couldn't have been better.

In video games you can go back and try another option but life isn't like that and so we can only suppose what might have happened.

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

#295
post #88

Earlier quoted context omitted.

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.

It is definitely not the case that magically safer is slower. IMO too often the attitude from WG21 (the c++ language committee) has been "Some fast things are unsafe, therefore if we make our language more unsafe it will go faster" which... that's not how implication works.

As a very high level example, take sorting. Rust's standard library provides you both a stable and unstable sort, as does your C++ standard library.

The C++ standard promises these sorts have O(n log n) performance, it's unclear in modern C++ if having a nonsensical ordering† is Undefined Behaviour (as it was in older versions) or outright IFNDR (much worse than UB) but the real world effect will be similar anyway

Rust promises that these sorts work as expected, if you provide nonsensical ordering, obviously it can't very well "sort" things the way you asked, but we don't need to kill your neighbour's cats and wipe the hard disk either, so, it will either give you back the same things in... some order or it will report the fatal error in your software.

The Rust option here is clearly much safer right? So, how much performance is this costing? Actually, it's faster. So C++ is choosing slower and worse. What's the upside?

† For example what about if I insist that Red < Green, but also Green < Red, and furthermore Red == Green is true, but so is Red != Green, however neither Green == Red nor Green != Red are true!

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

#296

Earlier quoted context omitted.

Most binary save game files are human editable, too; unless they go through a separate encoding stage.

Editting simcity saves was my introduction to hex editing...

For me, iirc, it was Bard's Tale

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

#297
post #149

Earlier quoted context omitted.

Valgrind was released in 2002 to immediate celebration. It was available and surely known to the team. All they needed to do was write a unit test that loaded and instantiated those vehicle files and run it with "valgrind" in front of the command line.

I don't know whether Valgrind ever gained support for any of the GTA target platforms. It wasn't available on Windows for a very, very long time.

Still isn't available for windows from what I gather.

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

#298
post #250

> all these findings prove that the bug is NOT an issue with Windows 11 24H2, as things like the way the stack is used by internal WinAPI functions are not contractual and they may change at any time, with no prior notice. This reminds me of an excellent article I read a while back, the gist of it was that, given sufficient success, there's no such thing as a private API.

Could you please find this article and link it here. I'm curious about the arguments.

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

#299

Earlier quoted context omitted.

it probably shouldn’t be a “release” thing. actually, certainly. i do wonder how many bugs would never have seen the light of day, if someone’s “set” actually turned out to be a sequence (i.e. allowed duplicate values) resulting in a debug build raising an assert.

Debug builds are worthless for catching issues. How many people actually run them? Perhaps developers run debug builds of individual binaries they're working on when they're trying to repro a bug, but my experience at every company of every size and position in the stack (including the Windows team) is that no one does their general purpose use on a debug build.

Yeah, even their integration tests will probably run in opt mode.

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

#300

Earlier quoted context omitted.

I don't think they will get more rare; there will always be a top % of engineers that do deep dives. I hope anyway. But AI won't replace them, nor did the past 50+ years of software development innovation. There's millions (tens of millions?) of higher programming language developers that don't know the difference between stack or heap besides maybe some theory they half remember from school but they don't care becau…

If your whole career will be using higher order languages with very little data stored on stack (vs heap), why should those programmers care? It seems like normal progression of more abstraction in the tools that we use. Similarly, I have programmed a lot of C and C++ in my career and I never once need assembly language. (I am expecting someone to pop in the convo here and tell me about how I am a terrible C/C++ prog…

Why should I care is a awful catchohrase.
Post reply on HN