Nota
O acesso a esta página requer autorização. Pode tentar iniciar sessão ou alterar os diretórios.
O acesso a esta página requer autorização. Pode tentar alterar os diretórios.
Visão geral
As linguagens C & C++ são poderosas, mas podem sofrer de uma classe de bugs que afetam a correção e a segurança do programa. A partir do Visual Studio 2019 versão 16.9, o compilador Microsoft C/C++ (MSVC) e o IDE oferecem suporte ao AddressSanitizer sanitizer. AddressSanitizer (ASan) é um compilador e tecnologia de tempo de execução que expõe muitos bugs difíceis de encontrar com zero falsos positivos:
-
Incompatibilidades Alloc/dealloc e
new/deletetipo incompatibilidades - Alocações muito grandes no heap
-
calloctransbordo eallocatransbordo - Duplo gratuito e uso após grátis
- Estouro de variável global
- Estouro de buffer de pilha
- Alinhamento inválido de valores alinhados
-
memcpyestrncatparâmetros se sobrepõem - estouro de buffer de pilha e subfluxo
-
Uso da pilha após
returne uso após o escopo - Uso de memória depois de envenenado
Use o AddressSanitizer para reduzir o tempo gasto em:
- Correção básica
- Portabilidade entre plataformas
- Segurança
- Testes de esforço
- Integração de novo código
O AddressSanitizer, originalmente introduzido pelo Google, fornece tecnologias de deteção de bugs em tempo de execução que usam seus sistemas de compilação existentes e ativos de teste existentes diretamente.
AddressSanitizer é integrado com o sistema de projeto Visual Studio, o sistema de compilação CMake e o IDE. Os projetos podem habilitar o AddressSanitizer definindo uma propriedade de projeto ou usando uma opção de compilador extra: /fsanitize=address. A nova opção é compatível com todos os níveis de otimização e configurações de x86 e x64. No entanto, ele não é compatível com edição e continuação, vinculação incremental e /RTC.
A partir da versão 16.9 do Visual Studio 2019, a tecnologia AddressSanitizer da Microsoft permite a integração com o IDE do Visual Studio. A funcionalidade pode, opcionalmente, criar um arquivo de despejo de memória quando o sanitizer encontrar um bug no tempo de execução. Se definires a variável de ambiente ASAN_SAVE_DUMPS=MyFileName.dmp antes de executares o teu programa, será criado um ficheiro de despejo com metadados extra para uma depuração post-mortem eficiente de bugs diagnosticados com precisão. Esses arquivos de despejo tornam o uso estendido de AddressSanitizer mais fácil para:
- Testes de máquinas locais
- Testes distribuídos no local
- Fluxos de trabalho baseados na nuvem para testes
Instalar AddressSanitizer
As cargas de trabalho C++ no Visual Studio Installer instalam as bibliotecas AddressSanitizer e a integração IDE por padrão. No entanto, se você estiver atualizando de uma versão mais antiga do Visual Studio 2019, use o instalador para habilitar o suporte a ASan após a atualização. Você pode abrir o instalador no menu principal do Visual Studio por meio do Ferramentas>Obter Ferramentas e Recursos... Escolha Modificar em sua instalação existente do Visual Studio no Instalador do Visual Studio para chegar à tela a seguir.
Observação
Se você executar o Visual Studio na nova atualização, mas não tiver instalado o ASan, receberá um erro ao executar o código:
LNK1356: não é possível encontrar a biblioteca 'clang_rt.asan_dynamic-i386.lib'
Utilize o AddressSanitizer
Comece a construir seus executáveis com a opção de compilador /fsanitize=address usando qualquer um destes métodos de desenvolvimento comuns:
- Compilações de linha de comando
- Sistema de projeto do Visual Studio
- Integração com o Visual Studio CMake
Recompile e, em seguida, execute o programa normalmente. Esta geração de código expõe muitos tipos de bugs diagnosticados com precisão. Esses erros são relatados de três maneiras: no IDE do depurador, na linha de comando ou armazenados em um novo tipo de arquivo de despejo para processamento off-line preciso.
A Microsoft recomenda que você use AddressSanitizer nestes três fluxos de trabalho padrão:
Loop interno do desenvolvedor
- Visual Studio - Linha de Comando
- Visual Studio - Sistema de Projeto
- Visual Studio - CMake
CI/CD - integração contínua / desenvolvimento contínuo
- Relatório de erros - Novos ficheiros de despejo AddressSanitizer
Fuzzing - edifício com o invólucro libFuzzer
- Azure OneFuzz
- Máquina local
Este artigo aborda as informações necessárias para habilitar os três fluxos de trabalho listados anteriormente. As informações são específicas para a implementação dependente da plataforma Windows 10 (e posterior) do AddressSanitizer. Esta documentação complementa a excelente documentação de Google, Apple e GCC já publicada.
Observação
O suporte é limitado a x86 e x64 no Windows 10 e posterior.
Envie-nos feedback sobre o que você gostaria de ver em versões futuras. Seu feedback nos ajuda a priorizar outros sanitizantes para o futuro, como /fsanitize=thread, /fsanitize=leak, /fsanitize=memory, /fsanitize=undefinedou /fsanitize=hwaddress. Você pode relatar bugs aqui se tiver problemas.
Use AddressSanitizer em um prompt de comando do desenvolvedor
Use a opção do /fsanitize=address compilador num prompt de comando do desenvolvedor para habilitar a compilação para o tempo de execução do AddressSanitizer. A opção /fsanitize=address é compatível com os níveis de otimização C++ ou C existentes (por exemplo, /Od, /O1, /O2e /O2 /GL). A opção funciona com CRTs estáticos e dinâmicos (por exemplo, /MD, /MDd, /MTe /MTd). Ele funciona se você criar um EXE ou uma DLL. As informações de depuração são necessárias para a formatação ótima das pilhas de chamadas. No exemplo a seguir, cl /fsanitize=address /Zi é passado na linha de comando.
Observação
O AddressSanitizer não suporta otimização guiada por perfil (PGO). AddressSanitizer não deve ser usado na produção.
As bibliotecas AddressSanitizer (arquivos .lib) são vinculadas automaticamente. Para mais informações, consulte a referência de linguagem, compilação e depuração do AddressSanitizer.
Exemplo - estouro de buffer global básico
// basic-global-overflow.cpp
#include <stdio.h>
int x[100];
int main() {
printf("Hello!\n");
x[100] = 5; // Boom!
return 0;
}
Usando um prompt de comando do desenvolvedor para o Visual Studio 2019, compile main.cpp usando /fsanitize=address /Zi
Quando você executa o main.exe resultante na linha de comando, ele cria o relatório de erro formatado a seguir.
Considere as caixas vermelhas sobrepostas que destacam sete informações-chave:
Há sete destaques vermelhos que identificam as principais informações no relatório de erros. Eles correspondem à lista numerada que se segue a esta imagem. As caixas numeradas destacam o seguinte texto: 1) global-buffer-overflow 2) WRITE com tamanho 4 3) basic-global-overflow.cpp 7 4) à direita da variável global 'x' definida em 'basic-global-overflow.cpp:3:8' 5) com tamanho 400 6) 00 00[f9]f9 f9 7) A caixa encontra-se na área de legenda de byte sombra e contém Global redzone: f9
Destaques vermelhos, de cima para baixo
- O bug de segurança de memória é um estouro de buffer global.
- Havia 4 bytes (32 bits) armazenados fora de qualquer variável definida pelo usuário.
- O armazenamento ocorreu na função
main()definida no ficheirobasic-global-overflow.cppna linha 7. - A variável denominada
xé definida em basic-global-overflow.cpp na linha 3, começando na coluna 8 - Esta variável global
xé de tamanho 400 bytes - O byte de sombra exato que descreve o endereço visado pelo armazenamento tinha um valor de
0xf9 - A legenda do byte de sombra diz que
0xf9é uma área de preenchimento à direita deint x[100]
Observação
Os nomes de função na pilha de chamadas são produzidos por meio do symbolizer LLVM que é invocado pelo tempo de execução após um erro.
Utilizar AddressSanitizer no Visual Studio
AddressSanitizer é integrado com o IDE do Visual Studio. Para ativar o AddressSanitizer para um projeto MSBuild, clique com o botão direito do mouse no projeto no Gerenciador de Soluções e escolha Propriedades. Na caixa de diálogo Property Pages, selecione Configuration Properties>C/C++>Generale, em seguida, modifique a propriedade Enable AddressSanitizer. Escolha OK para salvar as alterações.
Para criar a partir do IDE, desative todas as opções incompatíveis. Para um projeto existente compilado usando /Od (ou modo de depuração), talvez seja necessário desativar estas opções:
- Desativar
/ZI(Formato de Informações de Depuração) - Desativar
/RTC1(verificações de tempo de execução) - Desativar
/INCREMENTAL(vinculação incremental)
Para criar e executar o depurador, pressione F5. Uma janela Exceção lançada aparece no Visual Studio:
Use AddressSanitizer do Visual Studio: CMake
Para habilitar o AddressSanitizer para um projeto CMake criado para o Windowsde destino, siga estas etapas:
Abra o menu suspenso Configurações na barra de ferramentas na parte superior do IDE e selecione Gerir Configurações.
Isso abre o editor de configurações do projeto CMake, que reflete o conteúdo do arquivo de
CMakeSettings.jsondo seu projeto.Escolha o link Editar JSON no editor. Esta seleção muda a exibição para JSON bruto.
Adicione o seguinte trecho à
"windows-base"predefinição, dentro"configurePresets":para ativar o AddressSanitizer:"environment": { "CFLAGS": "/fsanitize=address", "CXXFLAGS": "/fsanitize=address" }"configurePresets"fica mais ou menos assim, depois:"configurePresets": [ { "name": "windows-base", "hidden": true, "generator": "Ninja", "binaryDir": "${sourceDir}/out/build/${presetName}", "installDir": "${sourceDir}/out/install/${presetName}", "cacheVariables": { "CMAKE_C_COMPILER": "cl.exe", "CMAKE_CXX_COMPILER": "cl.exe" }, "condition": { "type": "equals", "lhs": "${hostSystemName}", "rhs": "Windows" }, "environment": { "CFLAGS": "/fsanitize=address", "CXXFLAGS": "/fsanitize=address" } },AddressSanitizer não funciona caso "edit-and-continue" seja especificado (
/ZI), o qual é ativado por omissão para novos projetos CMake. EmCMakeLists.txt, comente (prefixo com#) a linha que começa comset(CMAKE_MSVC_DEBUG_INFORMATION_FORMAT". Essa linha é mais ou menos assim, depois:# set(CMAKE_MSVC_DEBUG_INFORMATION_FORMAT "$<IF:$<AND:$<C_COMPILER_ID:MSVC>,$<CXX_COMPILER_ID:MSVC>>,$<$<CONFIG:Debug,RelWithDebInfo>:EditAndContinue>,$<$<CONFIG:Debug,RelWithDebInfo>:ProgramDatabase>>")Digite Ctrl+S para salvar este arquivo JSON
Limpe o diretório de cache do CMake e reconfigure escolhendo no menu do Visual Studio: Project>Delete cache e Reconfigure. Escolha Sim quando o prompt aparecer para limpar o diretório de cache e reconfigurar.
Substitua o conteúdo do arquivo de origem (por exemplo,
CMakeProject1.cpp) pelo seguinte:// CMakeProject1.cpp : Defines the entry point for the application #include <stdio.h> int x[100]; int main() { printf("Hello!\n"); x[100] = 5; // Boom! return 0; }Escolha F5 para recompilar e executar no ambiente de depuração.
Esta captura de tela captura o erro da compilação CMake.
AddressSanitizer relatórios de falhas
Introduzimos uma nova funcionalidade no AddressSanitizer para uso com fluxos de trabalho distribuídos e na nuvem. Essa funcionalidade permite a visualização offline de um erro AddressSanitizer no IDE. O erro é sobreposto sobre sua fonte, assim como você experimentaria em uma sessão de depuração ao vivo.
Esses novos arquivos de despejo podem levar a uma maior eficiência na análise de um bug. Você não precisa executar novamente, encontrar dados remotos ou procurar uma máquina que ficou off-line.
Para produzir um novo tipo de arquivo de despejo que pode ser exibido no Visual Studio em outra máquina em uma data posterior:
set ASAN_SAVE_DUMPS=MyFileName.dmp
A partir do Visual Studio 16.9, pode exibir um erro diagnosticado com precisão, armazenado no seu ficheiro de *.dmp, acima do seu código-fonte.
Esta nova funcionalidade de despejo de falhas permite fluxos de trabalho baseados na nuvem ou testes distribuídos. Ele também pode ser usado para arquivar um bug detalhado e acionável em qualquer cenário.
Exemplos de erros
AddressSanitizer pode detetar vários tipos de erros de uso indevido de memória. Aqui estão muitos dos erros de tempo de execução relatados quando você executa seus binários compilados usando a opção de compilador AddressSanitizer (/fsanitize=address):
alloc-dealloc-mismatchallocation-size-too-bigcalloc-overflowdouble-freedynamic-stack-buffer-overflowglobal-buffer-overflowheap-buffer-overflowheap-use-after-freeinvalid-allocation-alignmentmemcpy-param-overlapnew-delete-type-mismatchstack-buffer-overflowstack-buffer-underflowstack-use-after-returnstack-use-after-scopestrncat-param-overlapuse-after-poison
Para obter mais informações sobre os exemplos, consulte Exemplos de erro AddressSanitizer.
Diferenças com Clang 12.0
MSVC atualmente difere do Clang 12.0 em duas áreas funcionais:
- stack-use-after-scope - essa configuração está ativada por padrão e não pode ser desativada.
-
stack-use-after-return - esta funcionalidade requer uma opção de compilador extra e não está disponível apenas definindo
ASAN_OPTIONS.
Essas decisões foram tomadas para reduzir a matriz de teste necessária para entregar esta primeira versão.
Recursos que poderiam levar a falsos positivos no Visual Studio 2019 16.9 não foram incluídos. Essa disciplina impôs a integridade de testes eficazes necessária para assegurar a interoperabilidade com décadas de código existente. Mais recursos podem ser considerados em versões posteriores:
- Fiasco da Ordem de Inicialização
- Estouro Intra-Objeto
- Contentor Overflow
- Subtração/Comparação de Ponteiros
Para obter mais informações, consulte Building for AddressSanitizer with MSVC.
Documentação existente da indústria
Já existe uma extensa documentação para essas implementações dependentes de linguagem e plataforma da tecnologia AddressSanitizer.
Este artigo seminal sobre o AddressSanitizer (externo) descreve a implementação.
Ver também
Problemas conhecidos do AddressSanitizer
AddressSanitizer: guia de compilação e referência de linguagem
Referência do tempo de execução do AddressSanitizer
Bytes de sombra do AddressSanitizer
Testes de AddressSanitizer na nuvem ou distribuídos
Integração do depurador AddressSanitizer
Exemplos de erro AddressSanitizer