1 points par GN⁺ 2025-04-24 | 1 commentaires | Partager sur WhatsApp
  • Un bug vieux de 20 ans dans GTA San Andreas refait surface sur Windows 11 24H2
    • Un bug a été signalé dans GTA San Andreas où l’avion Skimmer disparaît sous Windows 11 24H2
    • Le problème n’est pas résolu même avec SilentPatch
    • Le problème ne se produit pas sous Windows 11 23H2
    • Tous les utilisateurs ayant mis à jour vers Windows 11 24H2 rencontrent ce bug

Analyse du bug

Qu’est-ce qui ne va pas ?

  • Lors de l’installation de SilentPatch, le jeu se fige
  • Il a été constaté que CPlane::PreRender se retrouve coincé dans une petite boucle
  • La vitesse des hélices de l’avion est définie à une valeur anormalement élevée
  • La vitesse des hélices est calculée proportionnellement à l’altitude de l’avion

Pourquoi et comment ?

  • Un paramètre requis manque dans la définition de Skimmer dans vehicles.ide
  • Dans Vice City, Skimmer était défini comme un bateau
  • Dans San Andreas, il a été transformé en avion, mais le paramètre nécessaire n’a pas été ajouté

La véritable cause racine

  • Le problème est dû à un changement dans la manière dont la pile est utilisée sous Windows 11 24H2
  • LeaveCriticalSection utilise désormais davantage d’espace sur la pile
  • Auparavant, fgets et LeaveCriticalSection n’écrasaient pas cet espace sur la pile, mais c’est désormais le cas

Pourquoi ce problème apparaît-il seulement maintenant ?

  • Les changements de Windows 11 24H2 ont modifié l’espace de pile
  • Le jeu utilisait une variable locale non initialisée, ce qui a provoqué le problème
  • Le bug avait déjà été corrigé sur d’autres plateformes

Vous voulez corriger ce problème dans le jeu ?

  • Le prochain hotfix de SilentPatch inclura une correction dans le code
  • Il est aussi possible de corriger le problème en modifiant manuellement le fichier vehicles.ide

Mot de la fin

  • Ce bug est intéressant parce qu’il est directement lié à une version précise de l’OS
  • Il montre qu’un changement dans la disposition de la pile peut affecter la compatibilité
  • Il ne faut pas négliger la validation des données d’entrée ni ignorer les avertissements du compilateur

1 commentaires

 
GN⁺ 2025-04-24
Avis Hacker News
  • Un sujet digne du travail de Raymond Chen. C’est un très grand compliment
  • Ravi que la cause du problème ait été analysée plus en profondeur
  • À mon avis, tout ce qui ne fait pas partie du contrat devrait être traité de manière aléatoire. Par exemple, si l’ordre d’itération d’une map n’est pas garanti par le langage, alors le langage devrait le rendre aléatoire. Sinon, le code devient fragile
  • Il ne faut pas ignorer les avertissements du compilateur. Ce code a probablement déclenché un avertissement dans le code d’origine
  • Quelle erreur du compilateur pouvait-on attendre ici ? Probablement quelque chose comme ne pas vérifier la valeur de retour de scanf pour confirmer qu’elle correspond au nombre de paramètres. Sinon, cela ressemble à une erreur dans un fichier de données que le compilateur ne peut pas connaître
  • J’aime toujours lire des articles techniques. Je me demande à quel point ce genre de texte deviendra encore plus rare à l’ère de l’IA
  • Je me demande ce qui a changé dans l’implémentation du verrouillage/déverrouillage des sections critiques de Windows
  • Merci d’avoir fourni un lien pour les personnes qui ont des problèmes d’accès
  • Il a toujours été bien trop facile de lire et d’écrire au-delà de la pile. Cela devrait simplement échouer
  • Il existe des mesures d’atténuation : ASLR, pages NX, protection contre le stack smashing, etc. Mais elles n’empêchent pas complètement la lecture d’anciennes données au-delà de la pile
  • Expérience de pensée : que se passerait-il si le matériel empêchait de lire ou d’écrire dans les portions inutilisées de la zone de pile ?
  • Proposition d’une manière de suivre l’adresse de début A de la pile, sa taille S et sa profondeur actuelle D
    • Ajouter une instruction pour indiquer au CPU que la pile se trouve à l’adresse A avec la taille S
    • Ajouter une instruction de saut qui réserve N octets sur la pile
    • Ajouter à l’instruction de retour existante une prise en compte de la pile
    • Faire échouer toute lecture ou écriture dans une zone de la pile au-delà de la profondeur actuelle
    • Sur les architectures où la pile croît vers le bas, l’arithmétique s’applique en sens inverse
  • Inconvénients : cela fige une convention d’appel unique et impose au gestionnaire mémoire du CPU de conserver beaucoup d’état
  • La pile est partout. Une prise en compte matérielle de la pile ouvrirait la voie à de nouvelles mesures d’atténuation
  • Pourquoi cette idée n’est-elle pas plus répandue ? A-t-elle déjà été essayée ?
  • Toutes ces découvertes prouvent que ce n’est pas un problème de Windows 11 24H2. Le jeu dépend d’un comportement indéfini
  • Le comportement indéfini est très sournois et vous pousse à croire que vous avez raison alors que vous avez déjà fait une erreur
  • Si un programme en C ou C++ déclenche un comportement indéfini, absolument n’importe quoi peut se produire pendant son exécution
  • Avec un peu de chance, le programme affichera un message d’erreur approprié ou plantera, ce qui vous signalera immédiatement qu’il y a un problème
  • Avec moins de chance, le programme corrompra silencieusement des données, et au moment où vous vous en rendrez compte, la cause sera enfouie dans l’historique d’exécution passé
  • Avec vraiment très peu de chance, le programme fonctionnera comme vous le souhaitez, puis un nouveau bug apparaîtra quand vous modifierez du code sans rapport, ou changerez de version de compilateur, de système d’exploitation, etc.
  • Suggestions pour trouver de meilleures pratiques en tant que développeur
    • Lire, comprendre et mémoriser les comportements indéfinis en C ou C++, et les éviter
    • Compiler l’application en mode debug et la comparer au mode release ; s’il y a une différence, il existe un problème sérieux
    • Utiliser des outils comme -fsanitize=undefined,address pour détecter les comportements indéfinis à l’exécution
    • Recommandation d’utiliser des langages managés comme Java, C# ou Python. Ou bien des langages bas niveau sûrs comme Rust
  • Recommandation d’utiliser un débogueur. J’ai entendu des histoires sur les problèmes causés par le fait de ne pas en utiliser
  • Beaucoup d’amour pour Silent. Il améliore un de mes jeux préférés depuis plus de 10 ans