AddressSanitizer

Panoramica

I linguaggi C e C++ sono potenti, ma possono risentire di una classe di bug che influiscono sulla correttezza del programma e sulla sicurezza del programma. A partire dalla versione 16.9 di Visual Studio 2019, il compilatore Microsoft C/C++ (MSVC) e l'IDE supportano AddressSanitizer. AddressSanitizer (ASan) è una tecnologia del compilatore e del runtime che espone molti bug difficili da trovare con zero falsi positivi:

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 modifica e continua, 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 crash dump quando il sanitizzatore rileva un bug durante l'esecuzione. Se si imposta la ASAN_SAVE_DUMPS=MyFileName.dmp variabile di ambiente prima di eseguire il proprio programma, viene creato un file dump di arresto anomalo del sistema con metadati aggiuntivi per un debugging 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 in sede
  • 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 Visual Studio selezionando Tools>Strumenti e funzionalità. Scegliere Modify nell'installazione Visual Studio esistente dal programma di installazione di Visual Studio per passare alla schermata seguente.

Schermata che mostra Visual Studio Installer con il componente AddressSanitizer per C++, nella sezione Facoltativo, evidenziato.

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:

Questo articolo illustra le informazioni necessarie per abilitare i tre flussi di lavoro elencati in precedenza. Le informazioni sono specifiche dell'implementazione di AddressSanitizer per Windows 10 (e versioni successive) dipendente dalla piattaforma. 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 dello sviluppatore per abilitare la compilazione per il runtime AddressSanitizer. L'opzione /fsanitize=address è compatibile con i livelli di ottimizzazione C++ o C esistenti, ad esempio , /Od/O1, /O2e /O2 /GL. L'opzione funziona con CRT statici e dinamici , ad esempio , /MD/MDd, /MTe /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.

Nota

AddressSanitizer non supporta l'ottimizzazione guidata dal profilo (PGO). AddressSanitizer non deve essere usato nell'ambiente di produzione.

Le librerie AddressSanitizer (file con estensione lib) vengono collegate automaticamente. Per ulteriori informazioni, vedere riferimento al linguaggio, alla compilazione e al debug di AddressSanitizer.

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;
}

Usando un prompt dei comandi per gli sviluppatori per Visual Studio 2019, compilare basic-global-overflow.cpp usando /fsanitize=address /Zi.

Schermata che mostra un prompt dei comandi con il comando `cl basic-global-overflow.cpp /fsanitize=address /Zi`.

Quando si esegue il comando risultante basic-global-overflow.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:

Schermata del debugger che mostra un semplice errore di overflow globale.

Evidenziazioni rosse, dall'alto verso il basso

  1. Il bug di sicurezza della memoria è un buffer overflow globale.
  2. Sono stati archiviati 4 byte (32 bit) all'esterno di qualsiasi variabile definita dall'utente.
  3. La memorizzazione è avvenuta nella funzione main() definita nel file basic-global-overflow.cpp a riga 7.
  4. La variabile denominata x viene definita in basic-global-overflow.cpp alla riga 3, a partire dalla colonna 8.
  5. Questa variabile x globale è di dimensioni pari a 400 byte.
  6. L'esatto byte ombra che descriveva l'indirizzo a cui era destinata la scrittura aveva un valore di 0xf9.
  7. La legenda dei byte shadow dice che 0xf9 è un'area di padding a destra di int x[100].

Nota

Quando AddressSanitizer segnala un errore, il runtime ASan richiama il simbolizzatore LLVM per produrre i nomi di funzione nello stack di chiamate.

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.

Screenshot della finestra di dialogo delle Pagine delle Proprietà che mostra la proprietà

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:

Per compilare ed eseguire il debugger, premere F5. In Visual Studio viene visualizzata una finestra Eccezione generata :

Screenshot del debugger che mostra un errore di overflow del buffer globale.

Usare AddressSanitizer da Visual Studio: CMake

Per abilitare AddressSanitizer per un progetto CMake creato per Windows, seguire questa procedura:

  1. Aprire il menu a discesa Configurazioni nella barra degli strumenti nella parte superiore dell'IDE e selezionare Gestisci configurazioni.

    Schermata che mostra il menu a discesa di configurazione di CMake, che visualizza opzioni come x64 Debug, x64 Release e, nella parte inferiore dell'elenco, Gestisci configurazioni..., evidenziato.

    Questa azione apre l'editor delle impostazioni del progetto CMake, che rispecchia il contenuto del file CMakeSettings.json del progetto.

  2. Scegliere il collegamento Modifica JSON . Questa selezione consente di passare alla visualizzazione json non elaborato.

  3. Per attivare AddressSanitizer, aggiungi il frammento seguente al preset "windows-base", all'interno di "configurePresets":.

    "environment": {
      "CFLAGS": "/fsanitize=address",
      "CXXFLAGS": "/fsanitize=address"
    }
    

    "configurePresets" apparirà simile a questo, successivamente:

        "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"
            }
          },
    
  4. AddressSanitizer non funziona se è specificato "edit-and-continue" (/ZI), che è abilitato per impostazione predefinita per i nuovi progetti CMake. In CMakeLists.txtimpostare come commento (prefisso con #) la riga che inizia con set(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>>")
    
  5. Usare CTRL+S per salvare il file JSON.

  6. Svuota la directory della cache di CMake e riconfigura selezionando dal menu di Visual Studio: Progetto>Elimina cache e Riconfigura. Scegliere quando viene visualizzata la richiesta di cancellare la directory della cache e riconfigurarla.

  7. Sostituire il contenuto del file di origine, ad esempio , CMakeProject1.cppcon il codice seguente:

    // 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;
    }
    
  8. Scegliere F5 per ricompilare ed eseguire nel debugger.

    Questa schermata mostra l'errore durante la compilazione con CMake.

    Schermata che mostra un'eccezione che indica: Address Sanitizer Error: Global buffer overflow.

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 rendere più efficiente 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 a errore con diagnosi precisa, archiviato nel file *.dmp, sopra il codice sorgente.

Questa nuova funzionalità di dump di crash del sistema abilita 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):

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 del compilatore aggiuntiva 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:

Per altre informazioni, vedere Compilazione per AddressSanitizer con MSVC.

Documentazione del settore esistente

Documentazione ampia già esistente per queste implementazioni dipendenti dal linguaggio e dalla piattaforma della tecnologia AddressSanitizer.

Questo documento fondamentale su AddressSanitizer (esterno) descrive l'implementazione.

Vedi anche