Compartilhar via


Runtime do AddressSanitizer:

A biblioteca de runtime do AddressSanitizer intercepta funções e operações comuns de alocação de memória para habilitar a inspeção de acessos de memória. Há várias bibliotecas de runtime diferentes que dão suporte aos vários tipos de executáveis que o compilador pode gerar. O compilador e o vinculador associam automaticamente as bibliotecas de runtime apropriadas, desde que você passe a opção /fsanitize=address no tempo de compilação. Você pode substituir o comportamento padrão usando a opção no momento da /NODEFAULTLIB vinculação. Para obter mais informações, consulte a seção sobre vinculação na referência sobre linguagem, compilação e depuração do AddressSanitizer.

Ao compilar com cl /fsanitize=addresso , o compilador gera instruções para gerenciar e verificar bytes de sombra. Seu programa usa essa instrumentação para verificar os acessos de memória na pilha, no heap ou no escopo global. O compilador também produz metadados que descrevem variáveis globais e de pilha. Esses metadados permitem que o runtime gere um diagnóstico de erro preciso: nomes de função, linhas e colunas no código-fonte. Combinadas, as verificações do compilador e as bibliotecas de runtime podem diagnosticar precisamente muitos tipos de bugs de segurança de memória se forem encontrados em tempo de execução.

A lista de bibliotecas de runtime para vincular ao runtime AddressSanitizer, a partir do Visual Studio 17.7 Preview 3, a seguir. Para obter mais informações sobre as /MT opções (vincular estaticamente o tempo de execução) e /MD (vincular dinamicamente o redist em tempo de execução), consulte /MD, /MT, /LD (Usar biblioteca de tempo de execução).

Observação

Na tabela a seguir, {arch} é ou i386 x86_64. Essas bibliotecas usam convenções Clang para nomes de arquitetura. As convenções MSVC são normalmente x86 e x64 em vez de i386 e x86_64, mas se referem às mesmas arquiteturas.

Opção CRT Biblioteca de tempo de execução AddressSanitizer (.lib) Binário de tempo de execução de endereço (.dll)
/MT ou /MTd clang_rt.asan_dynamic-{arch}, clang_rt.asan_static_runtime_thunk-{arch} clang_rt.asan_dynamic-{arch}
/MD ou /MDd clang_rt.asan_dynamic-{arch}, clang_rt.asan_dynamic_runtime_thunk-{arch} clang_rt.asan_dynamic-{arch}

O diagrama a seguir mostra como as bibliotecas de tempo de execução de linguagem são vinculadas para as /MTopções , /MTd, /MD, e /MDd do compilador:

Diagrama de como as bibliotecas de tempo de execução são vinculadas para várias opções do compilador.

A imagem mostra três cenários para vincular a biblioteca de tempo de execução. O primeiro é /MT ou /MTd. My_exe.exe e my_dll.dll são mostrados com suas próprias cópias dos tempos de execução VCRuntime, Universal CRT e C++ vinculados estaticamente. Os cenários mostram /MD em que my_exe.exe e my_dll.dll compartilham vcruntime140.dll, ucrtbase.dll e msvcp140.dll. O último cenário mostra /MDd no qual my_exe.exe e my_dll.dll compartilham as versões de depuração dos runtimes: vcruntime140d.dll, ucrtbased.dll e msvcp140d.dll

O diagrama a seguir mostra como a biblioteca ASan está vinculada a várias opções do compilador:

Diagrama de como a dll de tempo de execução do ASan está vinculada.

A imagem mostra quatro cenários para vincular a biblioteca de tempo de execução do ASan. Os cenários são para /MT (vincular estaticamente o runtime), /MTd (vincular estaticamente o runtime de depuração), /MD (vincular dinamicamente o redist em runtime), /MDd (vincular dinamicamente o redist de depuração em runtime). Em todos os casos, my_exe.exe links e seus associados my_dll.dll vincular a uma única instância de clang-rt.asan-dynamix-x86_64.dll.

Mesmo ao vincular estaticamente, a DLL de runtime do ASan deve estar presente no runtime, ao contrário de outros componentes do C Runtime.

Versões anteriores

Antes do Visual Studio 17.7 Versão Prévia 3, os builds vinculados estaticamente (/MT ou /MTd) não usavam uma dependência de DLL. Em vez disso, o tempo de execução do AddressSanitizer foi vinculado estaticamente ao EXE do usuário. Os projetos DLL carregariam as exportações do EXE do usuário para acessar a funcionalidade ASan.

Projetos vinculados dinamicamente (/MD ou /MDd) usavam bibliotecas e DLLs diferentes, dependendo se o projeto estava configurado para depuração ou versão. Para obter mais informações sobre essas alterações e suas motivações, consulte MSVC Address Sanitizer – Uma DLL para todas as configurações de runtime.

A tabela a seguir descreve o comportamento anterior da vinculação da biblioteca de runtime AddressSanitizer, antes do Visual Studio 17.7 Preview 3:

Opção CRT DLL ou EXE DEBUG? Uma biblioteca (.lib) Binário de tempo de execução do ASan (.dll)
/MT EXE Não clang_rt.asan-{arch}, clang_rt.asan_cxx-{arch} Nenhum
/MT DLL Não clang_rt.asan_dll_thunk-{arch} Nenhum
/MD Ou Não clang_rt.asan_dynamic-{arch}, clang_rt.asan_dynamic_runtime_thunk-{arch} clang_rt.asan_dynamic-{arch}
/MT EXE Sim clang_rt.asan_dbg-{arch}, clang_rt.asan_dbg_cxx-{arch} Nenhum
/MT DLL Sim clang_rt.asan_dbg_dll_thunk-{arch} Nenhum
/MD Você pode usar o Sim clang_rt.asan_dbg_dynamic-{arch}, clang_rt.asan_dbg_dynamic_runtime_thunk-{arch} clang_rt.asan_dbg_dynamic-{arch}

O diagrama a seguir mostra como a biblioteca ASan foi vinculada para várias opções do compilador antes do Visual Studio 2022 17.7 Versão Prévia 3:

Diagrama de como a dll de runtime do ASan foi vinculada antes do Visual Studio 2022 Preview 3.

A imagem mostra quatro cenários para vincular a biblioteca de tempo de execução do ASan. Os cenários são para /MT (vincular estaticamente o runtime), /MTd (vincular estaticamente o runtime de depuração), /MD (vincular dinamicamente o redist em runtime), /MDd (vincular dinamicamente o redist de depuração em runtime). Para /MT, my_exe.exe tem uma cópia vinculada estaticamente do tempo de execução do ASan. my_dll.dll links para o tempo de execução do ASan no my_exe.exe. Para /MTd, o diagrama é o mesmo, exceto que ele usa o runtime de depuração vinculado estaticamente do ASan. Para /MD, my_exe.exe e my_dll.dll vinculam ao runtime do ASan vinculado dinamicamente chamado clang_rt.asan_dynamic-x86_64.dll. Para /MDd, o diagrama é o mesmo, exceto my_exe.exe e my_dll.dll link para o runtime de depuração do ASan chamado clang_rt.asan_dbg_dynamic-x86_64.dll.

Interceptação de função

O AddressSanitizer obtém interceptação de função por meio de muitas técnicas de hotpatching. Essas técnicas são mais bem-documentadas dentro do próprio código-fonte.

As bibliotecas de runtime interceptam muitas funções comuns de gerenciamento de memória e manipulação de memória. Para obter uma lista, consulte a lista AddressSanitizer de funções interceptadas. Os interceptadores de alocação gerenciam metadados e bytes de sombra relacionados a cada chamada de alocação. Sempre que uma função CRT, como malloc ou delete é chamada, os interceptadores definem valores específicos na região de memória sombra do AddressSanitizer para indicar se esses locais de heap estão acessíveis no momento e quais são os limites da alocação. Esses bytes de sombra permitem que as verificações geradas pelo compilador dos bytes de sombra determinem se uma carga ou repositório é válida.

A interceptação não tem garantia de sucesso. Se um prólogo de função for muito curto para um jmp ser gravado, a interceptação poderá falhar. Se ocorrer uma falha de interceptação, o programa lançará um debugbreak e interromperá. Se você anexar um depurador, isso torna clara a causa do problema de interceptação. Se você tiver esse problema, relate um bug.

Observação

Opcionalmente, os usuários podem tentar continuar após uma interceptação com falha definindo a variável de ambiente ASAN_WIN_CONTINUE_ON_INTERCEPTION_FAILURE como qualquer valor. Continuar após uma falha de interceptação pode resultar em relatórios de bugs perdidos para essa função.

Alocadores personalizados e o runtime addressSanitizer

O runtime do AddressSanitizer fornece interceptadores para interfaces comuns do alocador, malloc/free, new/delete, HeapAlloc/HeapFree (via RtlAllocateHeap/RtlFreeHeap). Muitos programas usam alocadores personalizados por um motivo ou outro, um exemplo seria qualquer programa usando dlmalloc ou uma solução usando a interface std::allocator e VirtualAlloc(). O compilador não pode adicionar automaticamente chamadas de gerenciamento de memória de sombra a um alocador personalizado. É responsabilidade do usuário usar a interface de envenenamento manual fornecida. Essa API permite que esses alocadores funcionem corretamente com o runtime do AddressSanitizer existente e as convenções de bytes de sombra .

Interface de envenenamento do AddressSanitizer manual

A interface de esclarecimento é simples, mas impõe restrições de alinhamento ao usuário. Os usuários podem importar esses protótipos importando sanitizer/asan_interface.h. Aqui estão os protótipos da função de interface:

void __asan_poison_memory_region(void const volatile *addr, size_t size);
void __asan_unpoison_memory_region(void const volatile *addr, size_t size);

Para conveniência, o arquivo de cabeçalho da interface AddressSanitizer fornece macros de encapsulamento. Essas macros verificam se a funcionalidade AddressSanitizer está habilitada durante a compilação. Eles permitem que o código-fonte omita as chamadas de função de envenenamento quando não são necessárias. Essas macros devem ser preferenciais ao chamar diretamente as funções acima:

#define ASAN_POISON_MEMORY_REGION(addr, size)
#define ASAN_UNPOISON_MEMORY_REGION(addr, size)

Requisitos de alinhamento para envenenamento por AddressSanitizer

Qualquer envenenamento manual de bytes de sombra deve considerar os requisitos de alinhamento. O usuário deve adicionar preenchimento, se necessário, para que os bytes de sombra terminem em um limite de bytes na memória de sombra. Cada bit na memória de sombra addressSanitizer codifica o estado de um único byte na memória do aplicativo. Essa codificação significa que o tamanho total de cada alocação, incluindo qualquer preenchimento, deve se alinhar a um limite de 8 bytes. Se o requisito de alinhamento não for atendido, ele poderá levar a relatórios de bug incorretos. O relatório incorreto pode se manifestar como relatórios ausentes (falsos negativos) ou relatórios sobre não erros (falsos positivos).

Para obter uma ilustração do requisito de alinhamento e possíveis problemas, consulte os exemplos de alinhamento ASan fornecidos. Um deles é um pequeno programa para mostrar o que pode dar errado com envenenamento manual de memória de sombra. A segunda é uma implementação de exemplo de envenenamento manual usando a interface std::allocator.

Opções de tempo

O Microsoft C/C++ (MSVC) usa um runtime baseado no runtime do Clang AddressSanitizer do repositório llvm-project. Por isso, a maioria das opções de runtime é compartilhada entre as duas versões. Uma lista completa das opções de runtime do Clang público está disponível aqui. Documentamos algumas diferenças nas seções a seguir. Se você descobrir opções que não funcionam conforme o esperado, relate um bug.

Opções do AddressSanitizer sem suporte

  • detect_container_overflow
  • unmap_shadow_on_exit

Observação

A opção halt_on_error de runtime addressSanitizer não funciona conforme esperado. Nas bibliotecas de runtime do Clang e do MSVC, muitos tipos de erro são considerados incompletos, incluindo a maioria dos erros de corrupção de memória.

Para obter mais informações, consulte a seção Diferenças com Clang 12.0.

Opções de runtime do AddressSanitizer específicas do MSVC

  • windows_hook_legacy_allocators Booleano, definido como false para desabilitar a interceptação de GlobalAlloc e LocalAlloc alocadores.

    Observação

    A opção windows_hook_legacy_allocators não estava disponível no runtime público do projeto llvm quando este artigo foi redigido. A opção pode eventualmente ser contribuída de volta para o projeto público; no entanto, depende da revisão de código e da aceitação da comunidade.

    A opção windows_hook_rtl_allocators, anteriormente um recurso de aceitação enquanto AddressSanitizer era experimental, agora está habilitada por padrão. Em versões anteriores ao Visual Studio 2022 versão 17.4.6, o valor da opção padrão é false. No Visual Studio 2022 versão 17.4.6 e versões posteriores, o padrão da opção windows_hook_rtl_allocators é true.

  • iat_overwrite String, definida como "error" por padrão. Outros valores possíveis são "protect" e "ignore". Alguns módulos podem substituir o import address table de outros módulos para personalizar implementações de determinadas funções. Por exemplo, os drivers geralmente fornecem implementações personalizadas para hardware específico. A iat_overwrite opção gerencia a proteção do runtime do AddressSanitizer contra substituições para funções específicas memoryapi.h . Atualmente, o runtime rastreia as VirtualAllocfunções , VirtualProtect, e VirtualQuery para proteção. Essa opção está disponível no Visual Studio 2022 versão 17.5 Versão Prévia 1 e versões posteriores. Os valores a seguir iat_overwrite controlam como o runtime reage quando as funções protegidas são substituídas:

    • Se definido como "error" (o padrão), o runtime relata um erro sempre que uma substituição é detectada.
    • Se definido como "protect", o runtime tentará evitar o uso da definição substituída e continuará. Efetivamente, a definição original memoryapi da função é usada de dentro do runtime para evitar recursão infinita. Outros módulos no processo ainda usam a definição substituída.
    • Se definido como "ignore", o runtime não tentará corrigir nenhuma função substituída e continuará com a execução.
  • windows_fast_fail_on_error Booleano (falso por padrão), definido como true para permitir que o processo seja encerrado com um __fastfail(71) após a impressão do relatório de erros.

Observação

Quando abort_on_error valor é definido como true, no Windows o programa termina com um exit(3). Para não alterar o comportamento atual, decidimos introduzir essa nova opção. Se abort_on_error e windows_fast_fail_on_error forem verdadeiros, o programa será encerrado com o __fastfail.

Lista do AddressSanitizer de funções interceptadas (Windows)

O tempo de execução do AddressSanitizer corrige muitas funções para habilitar verificações de segurança de memória no tempo de execução. Aqui está uma lista, que não é definitiva, das funções que o runtime do AddressSanitizer monitora.

Interceptadores padrão

Interceptadores opcionais

Os interceptadores listados aqui só são instalados quando uma opção de runtime do AddressSanitizer está habilitada. Defina windows_hook_legacy_allocators como false para desabilitar a interceptação do alocador herdado. set ASAN_OPTIONS=windows_hook_legacy_allocators=false

Confira também

Visão geral do AddressSanitizer
Problemas conhecidos do AddressSanitizer
Referência de linguagem e build do AddressSanitizer
Bytes de sombra de AddressSanitizer
Nuvem do AddressSanitizer ou teste distribuído
Integração do depurador do AddressSanitizer
Exemplos de erro do AddressSanitizer