Nota
O acesso a esta página requer autorização. Podes tentar iniciar sessão ou mudar de diretório.
O acesso a esta página requer autorização. Podes tentar mudar de diretório.
A biblioteca de tempo de execução AddressSanitizer interceta funções e operações comuns de alocação de memória para permitir a inspeção de acessos à memória. Existem várias bibliotecas de tempo de execução diferentes que suportam os vários tipos de executáveis que o compilador pode gerar. O compilador e o vinculador vinculam automaticamente as bibliotecas de tempo de execução apropriadas, desde que você passe a opção em tempo de /fsanitize=address compilação. Você pode substituir o comportamento padrão usando a opção no momento do /NODEFAULTLIB link. Para obter mais informações, consulte a seção sobre vinculação na linguagem AddressSanitizer, compilação e referência de depuração.
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 à 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 tempo de execução gere diagnósticos de erros precisos: nomes de funções, linhas e colunas no código-fonte. Combinadas, as verificações do compilador e as bibliotecas de tempo de execução podem diagnosticar com precisão muitos tipos de bugs de segurança de memória se forem encontrados em tempo de execução.
A lista de bibliotecas de tempo de execução para vincular ao tempo de execução AddressSanitizer, a partir do Visual Studio 17.7 Preview 3, segue. Para obter mais informações sobre as /MT opções (vincular estaticamente o tempo de execução) e /MD (vincular dinamicamente o redist no tempo de execução), consulte /MD, /MT, /LD (Usar biblioteca Run-Time).
Note
Na tabela a seguir, {arch} é ou i386x86_64.
Essas bibliotecas usam convenções Clang para nomes de arquitetura. As convenções MSVC são normalmente x86 e x64 não i386 e x86_64, mas referem-se às mesmas arquiteturas.
| Opção CRT | Biblioteca de tempo de execução AddressSanitizer (.lib) |
Endereço binário de tempo de execuçã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 estão vinculadas para as opções , /MT/MTd, /MDe /MDd 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, CRT Universal e C++ vinculados estaticamente. Os cenários mostram /MD no qual my_exe.exe e my_dll.dll compartilham vcruntime140.dll, ucrtbase.dlle 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 tempos de execução: vcruntime140d.dll, ucrtbased.dlle msvcp140d.dll
O diagrama a seguir mostra como a biblioteca ASan está vinculada para várias opções do compilador:
A imagem mostra quatro cenários para vincular a biblioteca de tempo de execução ASan. Os cenários são para /MT (vincular estaticamente o tempo de execução), /MTd (vincular estaticamente o tempo de execução da depuração), /MD (vincular dinamicamente o redist no tempo de execução), /MDd (vincular dinamicamente o redist de depuração no tempo de execução). Em todos os casos, my_exe.exe links e seus associados my_dll.dll link para uma única instância de clang_rt.asan_dynamic-x86_64.dll.
Mesmo ao vincular estaticamente, a DLL de tempo de execução ASan deve estar presente no tempo de execução - ao contrário de outros componentes do C Runtime.
Versões anteriores
Antes do Visual Studio 17.7 Preview 3, compilações vinculadas 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 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 foi configurado para depuração ou versão. Para obter mais informações sobre essas alterações e suas motivações, consulte MSVC AddressSanitizer – One DLL for all Runtime Configurations.
A tabela a seguir descreve o comportamento anterior da vinculação da biblioteca de tempo de execução AddressSanitizer, antes do Visual Studio 17.7 Preview 3:
| Opção CRT | DLL ou EXE | DEBUG? | Biblioteca ASan (.lib) |
ASan binário de tempo de execução (.dll) |
|---|---|---|---|---|
/MT |
EXE | No |
clang_rt.asan-{arch}, clang_rt.asan_cxx-{arch} |
None |
/MT |
DLL | No | clang_rt.asan_dll_thunk-{arch} |
None |
/MD |
Either | No |
clang_rt.asan_dynamic-{arch}, clang_rt.asan_dynamic_runtime_thunk-{arch} |
clang_rt.asan_dynamic-{arch} |
/MT |
EXE | Yes |
clang_rt.asan_dbg-{arch}, clang_rt.asan_dbg_cxx-{arch} |
None |
/MT |
DLL | Yes | clang_rt.asan_dbg_dll_thunk-{arch} |
None |
/MD |
Either | Yes |
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 Preview 3:
A imagem mostra quatro cenários para vincular a biblioteca de tempo de execução ASan. Os cenários são para /MT (vincular estaticamente o tempo de execução), /MTd (vincular estaticamente o tempo de execução da depuração), /MD (vincular dinamicamente o redist no tempo de execução), /MDd (vincular dinamicamente o redist de depuração no tempo de execução). Para /MT, my_exe.exe tem uma cópia vinculada estaticamente do tempo de execução 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 usa o tempo de execução ASan vinculado estaticamente debug. Para /MD, my_exe.exe e my_dll.dll link para o tempo de execução ASan dinamicamente vinculado 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 tempo de execução de depuração ASan chamado clang_rt.asan_dbg_dynamic-x86_64.dll.
Função de interceção
O AddressSanitizer consegue intercetação de funções através de muitas técnicas de hotpatching. Essas técnicas são melhor documentadas dentro do próprio código-fonte.
As bibliotecas de tempo de execução intercetam muitas funções comuns de gerenciamento e manipulação de memória. Para obter uma lista, consulte AddressSanitizer lista de funções intercetadas. Os intercetores de alocação gerenciam metadados e shadow bytes relacionados a cada chamada de alocação. Sempre que uma função CRT como malloc ou delete é chamada, os intercetadores definem valores específicos na região de memória de sombra AddressSanitizer para indicar se esses locais de heap estão atualmente acessíveis 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 armazenamento é válido.
Não é garantido que a interceção tenha êxito. Se um prólogo de função for muito curto para ser jmp escrito, a intercetação pode falhar. Se ocorrer uma falha de interceção, o programa lança um debugbreak e para. Se você anexar um depurador, ele deixará clara a causa do problema de intercetação. Se você tiver esse problema, reporte um bug.
Note
Opcionalmente, os usuários podem tentar continuar após uma intercetação com falha, definindo a variável ASAN_WIN_CONTINUE_ON_INTERCEPTION_FAILURE de ambiente para qualquer valor. Continuar após uma falha de intercetação pode resultar em relatórios de bugs perdidos para essa função.
Alocadores personalizados e o tempo de execução do AddressSanitizer
O tempo de execução do AddressSanitizer fornece intercetores para interfaces comuns de alocadores, malloc/free, new/delete,HeapAlloc/HeapFree(via ).RtlAllocateHeap/RtlFreeHeap Muitos programas fazem uso de alocadores personalizados por uma razão ou outra, um exemplo seria qualquer programa usando dlmalloc ou uma solução usando a std::allocator interface e VirtualAlloc(). O compilador não consegue 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 as convenções existentes de tempo de execução e byte de sombra AddressSanitizer.
Endereço manualInterface de envenenamento do Sanitizer
A interface para 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);
Por conveniência, o arquivo de cabeçalho da interface AddressSanitizer fornece macros de wrapper. Essas macros verificam se a funcionalidade AddressSanitizer está habilitada durante a compilação. Eles permitem que seu código-fonte omita as chamadas de função de envenenamento quando elas não são necessárias. Essas macros devem ser preferidas em vez de chamar as funções acima diretamente:
#define ASAN_POISON_MEMORY_REGION(addr, size)
#define ASAN_UNPOISON_MEMORY_REGION(addr, size)
Note
Se você envenenar manualmente a memória, você deve desenvenená-la antes de reutilizar. Isso é especialmente importante para endereços de pilha, como para uma variável local, que são frequentemente reutilizados durante a execução do programa. Você corre o risco de introduzir use-after-poison falsos positivos em endereços de pilha envenenados manualmente se não os desenvenenar antes que a estrutura da pilha seja removida.
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 estar alinhado a um limite de 8 bytes. Se o requisito de alinhamento não for cumprido, isso pode levar a relatórios de bugs incorretos. A comunicação incorreta pode manifestar-se como notificações em falta (falsos negativos) ou notificações de 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 é um pequeno programa para mostrar o que pode dar errado com o envenenamento manual de memória de sombra. O segundo é um exemplo de implementação de envenenamento manual usando a std::allocator interface.
Opções de tempo de execução
MSVC AddressSanitizer é uma bifurcação sincronizada regularmente do tempo de execução do Clang AddressSanitizer. Como resultado, o MSVC herda implicitamente muitas das opções de tempo de execução ASan do Clang. Uma lista completa de opções que mantemos e testamos ativamente pode ser encontrada aqui. Se você descobrir opções que não funcionam como esperado, reporte um bug.
Configurar opções de tempo de execução
As opções de tempo de execução do ASan são definidas de duas maneiras:
- A variável de ambiente
ASAN_OPTIONS - A
__asan_default_optionsfunção de utilizador
Se a variável de ambiente e a função de usuário especificarem opções conflitantes, as ASAN_OPTIONS opções na variável de ambiente terão precedência.
Várias opções são especificadas separando-as com dois pontos (:).
O exemplo a seguir define alloc_dealloc_mismatch como um e symbolize zero:
set ASAN_OPTIONS=alloc_dealloc_mismatch=1:symbolize=0
Ou adicione a seguinte função ao seu código:
extern "C" const char* __asan_default_options()
{
return "alloc_dealloc_mismatch=1:symbolize=0";
}
Opções de AddressSanitizer não suportadas
detect_container_overflowunmap_shadow_on_exit
Note
A opção halt_on_error de tempo de execução AddressSanitizer não funciona da maneira que você poderia esperar. Nas bibliotecas de tempo de execução Clang e MSVC, muitos tipos de erro são considerados não continuáveis, incluindo a maioria dos erros de corrupção de memória.
Para obter mais informações, consulte a seção Diferenças com o Clang 12.0 .
Opções de tempo de execução do AddressSanitizer específicas do MSVC
continue_on_errorBooleano, definido comofalsepor padrão. Quando definido comotrue, ele permite que o programa continue a ser executado depois que uma violação de memória é relatada, permitindo que você colete vários relatórios de erros.iat_overwriteString, definida como"error"por padrão. Outros valores possíveis são"protect"e"ignore". Alguns módulos podem substituir oimport address tablede outros módulos para personalizar implementações de determinadas funções. Por exemplo, os drivers geralmente fornecem implementações personalizadas para hardware específico. Aiat_overwriteopção gerencia a proteção do tempo de execução do AddressSanitizer contra substituições para funções específicasmemoryapi.h. O tempo de execução atualmente rastreia oVirtualAlloc,VirtualProtecteVirtualQueryfunções para proteção. Esta opção está disponível no Visual Studio 2022 versão 17.5 Preview 1 e versões posteriores. Os valores a seguiriat_overwritecontrolam como o tempo de execução reage quando as funções protegidas são substituídas:- Se definido como
"error"(o padrão), o tempo de execução relata um erro sempre que uma substituição é detetada. - Se definido como
"protect", o tempo de execução tenta evitar o uso da definição substituída e prossegue. Efetivamente, a definição originalmemoryapida função é usada de dentro do tempo de execução para evitar recursão infinita. Outros módulos no processo ainda usam a definição substituída. - Se definido como
"ignore", o tempo de execução não tenta corrigir nenhuma função substituída e prossegue com a execução.
- Se definido como
windows_fast_fail_on_errorBooleano (falsepor padrão), definido paratruepermitir que o processo termine com um após imprimir o relatório de__fastfail(71)erros.Note
Quando
abort_on_errorvalue é definido comotrue, no Windows o programa termina com umexit(3)arquivo . Para não mudar o comportamento atual, decidimos introduzir esta nova opção. Se ambosabort_on_errorewindows_fast_fail_on_errorforemtrue, o programa sairá com o__fastfail.windows_hook_legacy_allocatorsBooleano, definido parafalsedesativar a intercetação eGlobalAllocLocalAllocalocadores.Note
A opção
windows_hook_legacy_allocatorsnão estava disponível no tempo de execução público do llvm-project quando este artigo foi escrito. A opção pode, eventualmente, ser reconduzida para o projeto público; no entanto, depende da revisão do código e da aceitação da comunidade.A opção
windows_hook_rtl_allocators, anteriormente um recurso de aceitação enquanto o AddressSanitizer era experimental, agora está habilitada por padrão. Em versões anteriores ao Visual Studio 2022 versão 17.4.6, o valor de opção padrão éfalse. No Visual Studio 2022 versão 17.4.6 e versões posteriores, a opçãowindows_hook_rtl_allocatorsassume comotruepadrão .
AddressSanitizer lista de funções intercetadas (Windows)
O tempo de execução AddressSanitizer hotpatches muitas funções para permitir verificações de segurança de memória em tempo de execução. Aqui está uma lista não exaustiva das funções que o tempo de execução do AddressSanitizer monitora.
Intercetores padrão
-
__C_specific_handler(apenas x64) _aligned_free_aligned_malloc_aligned_msize_aligned_realloc_calloc_base_calloc_crt-
_calloc_dbg(somente tempo de execução de depuração) -
_except_handler3(apenas x86) -
_except_handler4(apenas x86) (não documentado) _expand-
_expand_base(não documentado) -
_expand_dbg(somente tempo de execução de depuração) -
_free_base(não documentado) -
_free_dbg(somente tempo de execução de depuração) -
_malloc_base(não documentado) -
_malloc_crt(não documentado) -
_malloc_dbg(somente tempo de execução de depuração) _msize-
_msize_base(não documentado) -
_msize_dbg(somente tempo de execução de depuração) -
_realloc_base(não documentado) -
_realloc_crt(não documentado) -
_realloc_dbg(somente tempo de execução de depuração) _recalloc-
_recalloc_base(não documentado) -
_recalloc_crt(não documentado) -
_recalloc_dbg(somente tempo de execução de depuração) _strdupatoiatolcallocCreateThreadfreefrexplongjmpmallocmemchrmemcmpmemcpymemmovememsetRaiseExceptionreallocRtlAllocateHeapRtlCreateHeapRtlDestroyHeapRtlFreeHeapRtlRaiseException-
RtlReAllocateHeap(não documentado) -
RtlSizeHeap(não documentado) SetUnhandledExceptionFilterstrcatstrchrstrcmpstrcpystrcspnstrdupstrlenstrncatstrncmpstrncpystrnlenstrpbrkstrspnstrstrstrtokstrtolwcslenwcsnlen
Intercetores opcionais
Os intercetores listados aqui só são instalados quando uma opção de tempo de execução AddressSanitizer está ativada. Defina windows_hook_legacy_allocators como false para desativar a intercetação do alocador herdado.
set ASAN_OPTIONS=windows_hook_legacy_allocators=false
GlobalAllocGlobalFreeGlobalHandleGlobalLockGlobalReAllocGlobalSizeGlobalUnlockLocalAllocLocalFreeLocalHandleLocalLockLocalReAllocLocalSizeLocalUnlock
Consulte também
Visão geral do AddressSanitizer
AddressSanitizer problemas conhecidos
de compilação e referência de linguagem AddressSanitizer
AddressSanitizer shadow bytes
AddressSanitizer na nuvem ou de testes distribuídos
de integração do depurador AddressSanitizer
Exemplos de erro AddressSanitizer