1 pontos por GN⁺ 2025-04-24 | 1 comentários | Compartilhar no WhatsApp
  • Bug de 20 anos em GTA San Andreas aparece no Windows 11 24H2
    • Foi relatado um bug em GTA San Andreas no qual o avião Skimmer desaparece no Windows 11 24H2
    • O problema não é resolvido nem com o uso do SilentPatch
    • No Windows 11 23H2, o problema não ocorre
    • Todos os usuários que atualizaram para o Windows 11 24H2 tiveram esse bug

Investigação do bug

O que deu errado?

  • Ao instalar o SilentPatch, ocorre um problema em que o jogo trava
  • Foi descoberto que o jogo fica preso em um pequeno loop dentro de CPlane::PreRender
  • A velocidade das hélices do avião estava configurada de forma anormalmente alta
  • A velocidade das hélices é calculada proporcionalmente à altitude do avião

Por quê e como?

  • Faltam parâmetros necessários na definição do Skimmer em vehicles.ide
  • Em Vice City, o Skimmer era definido como barco
  • Em San Andreas, ele foi alterado para avião, mas os parâmetros necessários não foram adicionados

A verdadeira causa raiz

  • O problema ocorre porque a forma de uso da pilha mudou no Windows 11 24H2
  • LeaveCriticalSection passou a usar mais espaço de pilha
  • Antes, fgets e LeaveCriticalSection não sobrescreviam o espaço da pilha, mas agora sobrescrevem

Por que isso só aconteceu agora?

  • As mudanças do Windows 11 24H2 alteraram o espaço da pilha
  • O problema ocorreu porque o jogo usava variáveis locais não inicializadas
  • Em outras plataformas, esse problema já havia sido corrigido

Se você quiser corrigir esse problema no jogo

  • A próxima correção emergencial do SilentPatch incluirá uma mudança no código
  • Também é possível resolver o problema editando manualmente o arquivo vehicles.ide

Considerações finais

  • Esse bug é interessante por estar diretamente ligado a uma versão específica do sistema operacional
  • Ele mostra que mudanças no layout da pilha podem afetar a compatibilidade
  • É importante validar os dados de entrada e não ignorar avisos do compilador

1 comentários

 
GN⁺ 2025-04-24
Opiniões no Hacker News
  • Parece o tipo de coisa em que vale esperar o trabalho do Raymond Chen. Isso é um elogio e tanto
  • Fico feliz que tenham ido mais fundo na investigação da causa do problema
  • Na minha opinião, tudo o que não fizer parte do contrato deveria ser tratado de forma aleatória. Por exemplo, se uma linguagem não garante a ordem de iteração de um mapa, então a linguagem deveria aleatorizá-la. Caso contrário, o código fica frágil
  • Avisos do compilador não devem ser ignorados. Esse código provavelmente teria gerado um aviso no código original
  • Que erro do compilador seria esperado aqui? Talvez algo sobre não verificar o valor de retorno de scanf, para confirmar se corresponde ao número de parâmetros. Fora isso, parece um erro em arquivo de dados que o compilador não teria como conhecer
  • Sempre gosto de ler textos técnicos. Fico pensando o quão mais raros eles vão se tornar na era da IA
  • Fico curioso sobre o que mudou na implementação de bloqueio/desbloqueio de seções críticas do Windows
  • Obrigado por fornecer um link para quem está tendo problemas de acesso
  • Sempre foi fácil demais ler e escrever além da pilha. Isso simplesmente deveria falhar
  • Existem medidas de mitigação — ASLR, páginas NX, proteção contra stack smashing etc. Mas isso não impede completamente a leitura de dados antigos além da pilha
  • Um experimento mental: e se o hardware impedisse ler ou escrever na parte não utilizada da área da pilha?
  • Proposta de uma forma de rastrear o endereço inicial A da pilha, seu tamanho S e a profundidade atual D
    • Adicionar uma instrução para informar à CPU que existe uma pilha no endereço A com tamanho S
    • Adicionar uma instrução de salto para reservar N bytes na pilha
    • Adicionar consciência de pilha à instrução de retorno existente
    • Falhar em leituras ou escritas na região da pilha além da profundidade atual
    • Em arquiteturas em que a pilha cresce para baixo, a aritmética se aplica ao contrário
  • As desvantagens seriam fixar uma única convenção de chamada e exigir muito estado do gerenciador de memória da CPU
  • A pilha está em toda parte. A consciência de pilha no hardware abriria novas possibilidades de mitigação
  • Por que essa ideia não é comum? Será que já tentaram?
  • Tudo isso prova que não é um problema do Windows 11 24H2. O jogo depende de comportamento indefinido
  • Comportamento indefinido é traiçoeiro demais, porque faz você acreditar que está certo mesmo quando já cometeu um erro
  • Se um programa em C ou C++ provoca comportamento indefinido, qualquer coisa pode acontecer durante a execução do programa
  • Com sorte, o programa mostra uma mensagem de erro apropriada ou trava, e assim você percebe na hora que há um problema
  • Sem sorte, o programa corrompe dados silenciosamente e, quando você percebe o problema, a causa já ficou enterrada em execuções passadas
  • Com muito azar, o programa funciona exatamente como você quer, até que você muda um código sem relação, ou troca a versão do compilador, do sistema operacional etc., e então um novo bug aparece
  • Sugestões para encontrar abordagens melhores como desenvolvedor
    • Ler, entender e memorizar o que é comportamento indefinido em C ou C++, e evitá-lo
    • Compilar a aplicação em modo de depuração e comparar com o modo de lançamento; se houver diferença, existe um problema sério
    • Usar ferramentas como -fsanitize=undefined,address para capturar comportamento indefinido em tempo de execução
    • Recomenda-se usar linguagens gerenciadas como Java, C#, Python. Ou usar uma linguagem segura de baixo nível como Rust
  • Recomenda-se usar um depurador. Já ouvi histórias sobre os problemas de não usar um depurador
  • Muito amor para o Silent. Há mais de 10 anos ele melhora um jogo de que eu gosto