AddressSanitizer
Panoramica
I linguaggi C & C++ sono potenti, ma possono risentire di una classe di bug che influiscono sulla correttezza del programma e sulla sicurezza del programma. A partire da Visual Studio 2019 versione 16.9, il compilatore Microsoft C/C++ (MSVC) e l'IDE supportano il servizio di purificazione AddressSanitizer . AddressSanitizer (ASan) è una tecnologia del compilatore e del runtime che espone molti bug difficili da trovare con zero falsi positivi:
- Mancata corrispondenza tra alloc/dealloc e
new
/delete
mancata corrispondenza del tipo - Allocazioni troppo grandi per l'heap
calloc
overflow ealloca
overflow- Double free and use after free
- Overflow variabile globale
- Overflow del buffer heap
- Allineamento non valido dei valori allineati
memcpy
sovrapposizione di parametri estrncat
- Overflow e underflow del buffer dello stack
- Uso dello stack dopo
return
e uso dopo l'ambito - Uso della memoria dopo che è avvelenato
Usare AddressSanitizer per ridurre il tempo impiegato per:
- Correttezza di base
- Portabilità multipiattaforma
- Sicurezza
- Test di stress
- Integrazione di nuovo codice
AddressSanitizer, originariamente introdotto da Google, fornisce tecnologie di ricerca di bug di runtime che usano direttamente i sistemi di compilazione esistenti e gli asset di test esistenti.
AddressSanitizer è integrato con il sistema di progetto di Visual Studio, il sistema di compilazione CMake e l'IDE. I progetti possono abilitare AddressSanitizer impostando una proprietà del progetto o usando un'opzione del compilatore aggiuntiva: /fsanitize=address
. La nuova opzione è compatibile con tutti i livelli di ottimizzazione e configurazioni di x86 e x64. Tuttavia, non è compatibile con la modifica e continuazione, il collegamento incrementale e /RTC
.
A partire da Visual Studio 2019 versione 16.9, la tecnologia AddressSanitizer di Microsoft abilita l'integrazione con l'IDE di Visual Studio. La funzionalità può facoltativamente creare un file di dump di arresto anomalo del sistema quando il servizio di purificazione rileva un bug in fase di esecuzione. Se si imposta la ASAN_SAVE_DUMPS=MyFileName.dmp
variabile di ambiente prima di eseguire il programma, viene creato un file dump di arresto anomalo del sistema con metadati aggiuntivi per un debug post-mortem efficiente dei bug diagnosticati con precisione. Questi file di dump semplificano l'uso esteso di AddressSanitizer per:
- Test del computer locale
- Test distribuiti locali
- Flussi di lavoro basati sul cloud per i test
Installare AddressSanitizer
Per impostazione predefinita, i carichi di lavoro C++ nella Programma di installazione di Visual Studio installano le librerie AddressSanitizer e l'integrazione dell'IDE. Tuttavia, se si esegue l'aggiornamento da una versione precedente di Visual Studio 2019, usare il programma di installazione per abilitare il supporto di ASan dopo l'aggiornamento. È possibile aprire il programma di installazione dal menu principale di Visual Studio tramite Strumenti Ottieni strumenti>e funzionalità... Scegliere Modifica nell'installazione esistente di Visual Studio dalla Programma di installazione di Visual Studio per passare alla schermata seguente.
Nota
Se si esegue Visual Studio nel nuovo aggiornamento ma non è stato installato ASan, viene visualizzato un errore quando si esegue il codice:
LNK1356: impossibile trovare la libreria 'clang_rt.asan_dynamic-i386.lib'
Usare AddressSanitizer
Iniziare a compilare i file eseguibili con l'opzione del /fsanitize=address
compilatore usando uno di questi metodi di sviluppo comuni:
- Compilazioni della riga di comando
- Sistema del progetto di Visual Studio
- Integrazione di Visual Studio CMake
Ricompilare, quindi eseguire il programma normalmente. Questa generazione di codice espone molti tipi di bug diagnosticati con precisione. Questi errori vengono segnalati in tre modi: nell'IDE del debugger, nella riga di comando o archiviati in un nuovo tipo di file di dump per un'elaborazione off-line precisa.
Microsoft consiglia di usare AddressSanitizer in questi tre flussi di lavoro standard:
Ciclo interno dello sviluppatore
- Visual Studio - Riga di comando
- Visual Studio - Sistema di progetti
- Visual Studio - CMake
CI/CD - Integrazione continua/Sviluppo continuo
- Segnalazione errori - Nuovi file di dump AddressSanitizer
Fuzzing : compilazione con il wrapper libFuzzer
- Azure OneFuzz
- Computer locale
Questo articolo illustra le informazioni necessarie per abilitare i tre flussi di lavoro elencati in precedenza. Le informazioni sono specifiche dell'implementazione di Windows 10 (e versioni successive) dipendente dalla piattaforma di AddressSanitizer. Questa documentazione integra la documentazione eccellente di Google, Apple e GCC già pubblicata.
Nota
Il supporto è limitato a x86 e x64 in Windows 10 e versioni successive. Inviare commenti e suggerimenti su ciò che si vuole visualizzare nelle versioni future. I commenti e suggerimenti ci aiutano a classificare in ordine di priorità altri sanificatori per il futuro, ad esempio /fsanitize=thread
, /fsanitize=leak
/fsanitize=memory
, /fsanitize=undefined
, o /fsanitize=hwaddress
. Se si verificano problemi, è possibile segnalare bug qui .
Usare AddressSanitizer da un prompt dei comandi per sviluppatori
Usare l'opzione /fsanitize=address
del compilatore in un prompt dei comandi per sviluppatori per abilitare la compilazione per il runtime AddressSanitizer. L'opzione /fsanitize=address
è compatibile con tutti i livelli di ottimizzazione C++ o C esistenti (ad esempio, /Od
, /O1
/O2
, /O2 /GL
, e PGO
). L'opzione funziona con CRT statici e dinamici , ad esempio , /MD
/MDd
, /MT
e /MTd
. Funziona se si crea un file EXE o una DLL. Le informazioni di debug sono necessarie per una formattazione ottimale degli stack di chiamate. Nell'esempio seguente viene cl /fsanitize=address /Zi
passato alla riga di comando.
Le librerie AddressSanitizer (file con estensione lib) vengono collegate automaticamente. Per altre informazioni, vedere Riferimento al linguaggio AddressSanitizer, alla compilazione e al debug.
Esempio: overflow del buffer globale di base
// basic-global-overflow.cpp
#include <stdio.h>
int x[100];
int main() {
printf("Hello!\n");
x[100] = 5; // Boom!
return 0;
}
Uso di un prompt dei comandi per gli sviluppatori per Visual Studio 2019, compilare main.cpp
con /fsanitize=address /Zi
Quando si esegue il risultato main.exe
nella riga di comando, viene creato il report degli errori formattato che segue.
Si considerino le caselle rosse sovrapposte che evidenziano sette informazioni chiave:
Sono presenti sette evidenziazioni rosse che identificano le informazioni chiave nel report degli errori. Eseguono il mapping all'elenco numerato che segue questo screenshot. Le caselle numerate evidenziano il testo seguente: 1) global-buffer-overflow 2) WRITE di dimensione 4 3) basic-global-overflow.cpp 7 4) a destra della variabile globale 'x' definita in 'basic-global-overflow.cpp:3:8' 5) di dimensioni 400 6) 00 00[f9]f9 f9 7) Box si trova nell'area della legenda dei byte shadow e contiene la zona rossa globale: f9
Evidenziazioni rosse, dall'alto verso il basso
- Il bug di sicurezza della memoria è un overflow globale del buffer.
- Sono stati archiviati 4 byte (32 bit) all'esterno di qualsiasi variabile definita dall'utente.
- L'archivio ha avuto luogo nella funzione
main()
definita nel filebasic-global-overflow.cpp
alla riga 7. - La variabile denominata
x
viene definita in basic-global-overflow.cpp alla riga 3, a partire dalla colonna 8 - Questa variabile
x
globale è di dimensioni pari a 400 byte - Il byte di ombreggiatura esatto che descrive l'indirizzo di destinazione dell'archivio ha un valore
0xf9
- La legenda dei byte ombreggiatura dice
0xf9
che è un'area di riempimento a destra diint x[100]
Nota
I nomi delle funzioni nello stack di chiamate vengono generati tramite il simbolizzatore LLVM richiamato dal runtime in caso di errore.
Usare AddressSanitizer in Visual Studio
AddressSanitizer è integrato con l'IDE di Visual Studio. Per attivare AddressSanitizer per un progetto MSBuild, fare clic con il pulsante destro del mouse sul progetto in Esplora soluzioni e scegliere Proprietà. Nella finestra di dialogo Pagine delle proprietà selezionare Proprietà>di configurazione C/C++>Generale, quindi modificare la proprietà Enable AddressSanitizer. Scegli OK per salvare le modifiche.
Per eseguire la compilazione dall'IDE, rifiutare esplicitamente eventuali opzioni incompatibili. Per un progetto esistente compilato tramite /Od
(o modalità debug), potrebbe essere necessario disattivare queste opzioni:
- Disattivare la modifica e continuare
- Disattiva
/RTC1
(controlli di runtime) - Disattiva
/INCREMENTAL
(collegamento incrementale)
Per compilare ed eseguire il debugger, premere F5. In Visual Studio viene visualizzata una finestra Eccezione generata :
Usare AddressSanitizer da Visual Studio: CMake
Per abilitare AddressSanitizer per un progetto CMake creato in Windows di destinazione, seguire questa procedura:
Aprire l'elenco a discesa Configurazioni nella barra degli strumenti nella parte superiore dell'IDE e selezionare Gestisci configurazioni.
Verrà aperto l'editor impostazioni progetto CMake, che riflette il contenuto del file del
CMakeSettings.json
progetto.Scegliere il collegamento Modifica JSON nell'editor. Questa selezione consente di passare alla visualizzazione json non elaborato.
Aggiungere il frammento di codice seguente al
"windows-base"
set di impostazioni, all'interno"configurePresets":
per attivare Address Sanitizer:"environment": { "CFLAGS": "/fsanitize=address", "CXXFLAGS": "/fsanitize=address" }
"configurePresets"
ha un aspetto simile al seguente:"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" } },
Il servizio di purificazione degli indirizzi non funziona se è specificato edit-and-continue (
/ZI
), che è abilitato per impostazione predefinita per i nuovi progetti CMake. InCMakeLists.txt
impostare come commento (prefisso con#
) la riga che inizia conset(CMAKE_MSVC_DEBUG_INFORMATION_FORMAT"
. La riga è simile alla seguente:# set(CMAKE_MSVC_DEBUG_INFORMATION_FORMAT "$<IF:$<AND:$<C_COMPILER_ID:MSVC>,$<CXX_COMPILER_ID:MSVC>>,$<$<CONFIG:Debug,RelWithDebInfo>:EditAndContinue>,$<$<CONFIG:Debug,RelWithDebInfo>:ProgramDatabase>>")
Premere CTRL+S per salvare il file JSON
Cancellare la directory della cache CMake e riconfigurarsi scegliendo dal menu di Visual Studio: Project Delete cache and Reconfigure (Elimina>cache e riconfigura). Scegliere Sì quando viene visualizzata la richiesta di cancellare la directory della cache e riconfigurarla.
Sostituire il contenuto del file di origine (ad esempio,
CMakeProject1.cpp
) con quanto segue:// 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; }
Scegliere F5 per ricompilare ed eseguire nel debugger.
Questo screenshot acquisisce l'errore dalla compilazione CMake.
Dump di arresto anomalo di AddressSanitizer
Sono state introdotte nuove funzionalità in AddressSanitizer per l'uso con flussi di lavoro cloud e distribuiti. Questa funzionalità consente la visualizzazione offline di un errore AddressSanitizer nell'IDE. L'errore viene sovrapposto all'origine, proprio come si farebbe in una sessione di debug in tempo reale.
Questi nuovi file di dump possono causare efficienza durante l'analisi di un bug. Non è necessario rieseguire o trovare dati remoti o cercare un computer che è andato fuori linea.
Per produrre un nuovo tipo di file di dump che può essere visualizzato in Visual Studio in un altro computer in un secondo momento:
set ASAN_SAVE_DUMPS=MyFileName.dmp
A partire da Visual Studio 16.9 è possibile visualizzare un errore diagnosticato con precisione, archiviato nel *.dmp
file, sopra il codice sorgente.
Questa nuova funzionalità di dump di arresto anomalo del sistema consente flussi di lavoro basati sul cloud o test distribuiti. Può anche essere usato per archiviare un bug dettagliato e praticabile in qualsiasi scenario.
Esempi di errori
AddressSanitizer può rilevare diversi tipi di errori di uso improprio della memoria. Di seguito sono riportati molti degli errori di runtime segnalati quando si eseguono i file binari compilati usando l'opzione del compilatore AddressSanitizer (/fsanitize=address
):
alloc-dealloc-mismatch
allocation-size-too-big
calloc-overflow
double-free
dynamic-stack-buffer-overflow
global-buffer-overflow
heap-buffer-overflow
heap-use-after-free
invalid-allocation-alignment
memcpy-param-overlap
new-delete-type-mismatch
stack-buffer-overflow
stack-buffer-underflow
stack-use-after-return
stack-use-after-scope
strncat-param-overlap
use-after-poison
Per altre informazioni sugli esempi, vedere Esempi di errore AddressSanitizer.
Differenze con Clang 12.0
MSVC è attualmente diverso da Clang 12.0 in due aree funzionali:
- stack-use-after-scope : questa impostazione è attivata per impostazione predefinita e non può essere disattivata.
- stack-use-after-return : questa funzionalità richiede un'opzione aggiuntiva del compilatore e non è disponibile solo impostando
ASAN_OPTIONS
.
Queste decisioni sono state prese per ridurre la matrice di test necessaria per distribuire questa prima versione.
Le funzionalità che potrebbero causare falsi positivi in Visual Studio 2019 16.9 non sono state incluse. Tale disciplina imponeva l'integrità dei test efficace necessaria quando si considera l'interoperabilità con decenni di codice esistente. Altre funzionalità possono essere considerate nelle versioni successive:
- Ordine di inizializzazione Fiasco
- Overflow all'interno dell'oggetto
- Overflow del contenitore
- Sottrazione/confronto puntatore
Per altre informazioni, vedere Compilazione per AddressSanitizer con MSVC.
Documentazione del settore esistente
Documentazione completa già esistente per queste implementazioni di linguaggio e dipendenti dalla piattaforma della tecnologia AddressSanitizer.
Questo documento fondamentale su AddressSanitizer (esterno) descrive l'implementazione.
Vedi anche
Problemi noti di AddressSanitizer
Riferimento alla compilazione e al linguaggio AddressSanitizer
Informazioni di riferimento sul runtime AddressSanitizer
Byte ombreggiatura AddressSanitizer
AddressSanitizer cloud o test distribuiti
Integrazione del debugger AddressSanitizer
Esempi di errore addressSanitizer