Live data from Hacker News

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

cookieplmonster.github.io

261–270 of 315 posts

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

#261

Earlier quoted context omitted.

I would add: code defensively. Initialize your variables (either to a sensible value, or an outrageously wrong value) before passing pointers to them, even when you "know" that the value will be overwritten. Check for errors. Always consider what happens when things go wrong, not just when things go right. Any time you find yourself thinking, "condition X is guaranteed to hold, so I don't need to check for it" consid…

My only issue with defensive codding is that often it doesn't play nice with code coverage requirements. I've been in situations where I would like to add defensive coding just in case, but then the PR doesn't pass the coverage checks. The best is when you can ensure via th compiler (e.g. via the type system) that a case is impossible, but C++ (in my case) isn't perfect for this.

Code coverage tools allow to pragma the defensive code which will appear reasonable to most reviewers ?

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

#262
post #210

Earlier quoted context omitted.

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.

And yet, there is a good chance that C++ will start doing exactly this [1]. Because [2]: > The performance impact is negligible (less that 0.5% regression) to slightly positive (that is, some code gets faster by up to 1%). The code size impact is negligible (smaller than 0.5%). Compile-time regressions are negligible. Were overheads to matter for particular coding patterns, compilers would be able to obviate most of…

Thanks for the references - that was interesting reading, particularly that initialisation can be good for instruction pipelining.

A trick we were using with SSE was something like

__m128 zero = _mm_undefined_ps(); zero = _mm_xor_ps(zero, zero);

Now we were really careful with viewing our ops as data dependencies to reason about pipelining efficiency. But our profiling tools were not measuring this.

We did avoid _mm_set_ps(0.0f) which was actually showing up as cache misses.

I wonder if we were actually slower because cache misses are something we can measure?!

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

#263
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…

> Also, some languages intentionally randomize the order per program run, to avoid things like users intentionally stuffing hash tables with colliding keys.

Most modern langages do that as part of hashdos mitigation, Python did that until it switched to a naturally ordered hashmap, then made insertion order part of the spec. Importantly iteration order remains consistent with a process (possibly on a per-hashmap basis).

Notably, Go will randomise the starting point of hashmap iteration on each iteration.

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

#264
post #94

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)

Could you elaborate? I cannot see how a functional programming language would have protected you from reading a non existing value while not providing a default

It's more that functional languages just happen to be stricter in various ways that would've mitigated against this. You could quite happily design a functional language that has an unsafe equivalent to sscanf in its stdlib, or has big parts of the spec which are "undefined behaviour" that may differ depending on the underlying OS/compiler/runtime/stdlib in use. But the more popular functional languages have gained traction in part because they tend to have a "if you model the types correctly, the program basically works" philosophy around them. I don't think things like Haskell, Ocaml or F# would allow this if you wrote idiomatic code, you'd probably need to do something a little hacky or sketchy.

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

#265

Earlier quoted context omitted.

What happened to him?

https://randomascii.wordpress.com/2024/10/01/life-death-and-... https://randomascii.wordpress.com/2016/10/17/vestibular-dysf...

I remember reading this and having a mini-midlife-crisis after every read

I documented it this time :sigh: https://github.com/MatthewJohn/terrareg/commit/2231ba733a7f5...

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

#266

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.

Nope. You have to remember https://www.hyrumslaw.com/ With a sufficient number of users of an API, it does not matter what you promise in the contract: all observable behaviors of your system will be depended on by somebody. If you promise randomization, then somebody will depend on that :) And then you can never remove it!

Semi-related: this type of thing is actually covered in the Site Reliability Engineering book by Google. They highlighted a case of a system that outperformed its SLO, so people depended on it having 100% uptime. They "fixed" this by injecting errors to go closer to their SLA, forcing downstream engineers to deal with the fact that the dependent services would sometimes fail for no reason.

I know it's easier said than done everywhere, just found it to be an interesting parallel.

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

#267
post #249
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 tried to use Valgrind to catch pretty much this exact bug 20 years ago, and it was nigh impossible. If you call any 3rd party code it'll have flag tens of thousands of false positives that you have to sift through. And that was on a small game engine, I can't imagine running it on millions of lines of code.

Again, you don't valgrind a whole game. You valgrind your unit tests. Even in 2004 when this game was released, and even in the game industry, unit testing was a routine thing. And this particular bug was in code very amenable to lightweight unit testing.

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

#268

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.

Regarding contracts, there's an additional lesson here, quoting from the source: > This is an interesting lesson in compatibility: even changes to the stack layout of the internal implementations can have compatibility implications if an application is bugged and unintentionally relies on a specific behavior. I suppose this is why Linux kernel maintainers insist on never breaking user space.

But the linux equivalent here would be glibc, not the kernel

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

#270
The core problem is some compilers initialising memory to zero in Debug mode, masking behaviour of unitialised data, since in most cases zero is a legit value. In Release mode, this zeroing doesn’t happen.

Devs need to be aware that the following C++ initisliser exists which zeros data structures for you:

MyStruct s = { };

Post reply on HN