Byte ombreggiatura AddressSanitizer

Riepilogiamo brevemente il concetto di byte shadow e il modo in cui possono essere usati dall'implementazione di runtime di /fsanitize=address. Per altri dettagli, ti riferiamo alla ricerca iniziale AddressSanitizer - Serebryany, et al e alla documentazione corrente dell'algoritmo AddressSanitizer.

Concetto di base

Ogni 8 byte nello spazio indirizzi virtuale dell'applicazione può essere descritto usando un byte shadow.

Un byte shadow descrive il numero di byte attualmente accessibili come indicato di seguito:

  • 0 indica tutti i 8 byte
  • 1-7 significa da uno a sette byte
  • Il contesto di codifica dei numeri negativi per il runtime da usare per la diagnostica dei report.

Legenda dei byte ombreggiatura

Si consideri questa legenda dei byte shadow in cui sono definiti tutti i numeri negativi:

Screenshot della legenda shadow-byte addressSanitizer.

Mapping: descrizione dello spazio indirizzi

Ogni 8 byte nello spazio indirizzi virtuale dell'applicazione allineato "0-mod-8" può essere mappato al byte ombreggiato che descrive lo slot nello spazio indirizzi virtuale. Questo mapping può essere eseguito con un semplice spostamento e aggiunta.

In x86:

char shadow_byte_value = *((Your_Address >> 3) + 0x30000000)

In x64:

char shadow_byte_value = *((Your_Address >> 3) + _asan_runtime_assigned_offset)

Generazione di codice : test

Si consideri il modo in cui possono essere scritti byte shadow specifici, dal codice generato dal compilatore, dai dati statici o dal runtime. Questo pseudo-codice mostra come è possibile generare un controllo che precede qualsiasi caricamento o archivio:

ShadowAddr = (Addr >> 3) + Offset;
if (*ShadowAddr != 0) {
    ReportAndCrash(Addr);
}

Quando si instrumenta un riferimento di memoria inferiore a 8 byte, la strumentazione è leggermente più complessa. Se il valore dell'ombreggiatura è positivo (ovvero è possibile accedere solo ai primi k byte nella parola a 8 byte), è necessario confrontare gli ultimi 3 bit dell'indirizzo con k.

ShadowAddr = (Addr >> 3) + Offset;
k = *ShadowAddr;
if (k != 0 && ((Addr & 7) + AccessSize > k)) {
    ReportAndCrash(Addr);
}

Il runtime e il codice generato dal compilatore scrivono entrambi i byte shadow. Questi byte shadow consentono o revocano l'accesso quando gli ambiti terminano o lo spazio di archiviazione vengono liberati. I controlli precedenti leggono i byte shadow che descrivono "slot" a 8 byte nello spazio indirizzi dell'applicazione, in un determinato momento nell'esecuzione del programma. Oltre a questi controlli generati in modo esplicito, il runtime controlla anche i byte shadow dopo che intercetta (o "hook") molte funzioni in CRT.

Per altre informazioni, vedere l'elenco delle funzioni intercettate.

Impostazione dei byte ombreggiatura

Sia il codice generato dal compilatore che il runtime AddressSanitizer può scrivere byte shadow. Ad esempio, il compilatore può impostare byte shadow per consentire l'accesso a dimensioni fisse alle variabili locali dello stack definite in un ambito interno. Il runtime può racchiudere le variabili globali nella sezione dei dati con byte shadow.

Vedi anche

Panoramica di AddressSanitizer
Problemi noti di AddressSanitizer
Riferimento alla compilazione e al linguaggio AddressSanitizer
Informazioni di riferimento sul runtime AddressSanitizer
AddressSanitizer cloud o test distribuiti
Integrazione del debugger AddressSanitizer
Esempi di errore addressSanitizer