Errore: global-buffer-overflow
Errore di purificazione dell'indirizzo: overflow del buffer globale
Il compilatore genera metadati per qualsiasi variabile nelle .data
sezioni o .bss
. Queste variabili hanno l'ambito del linguaggio globale o statico del file. Vengono allocati in memoria prima dell'avvio main()
. Le variabili globali in C vengono trattate in modo molto diverso rispetto a in C++. Questa differenza è dovuta alle regole complesse per il collegamento di C.
In C una variabile globale può essere dichiarata in diversi file di origine e ogni definizione può avere tipi diversi. Il compilatore non può visualizzare tutte le definizioni possibili contemporaneamente, ma il linker può. Per C, per impostazione predefinita il linker seleziona la variabile di dimensioni maggiori in tutte le diverse dichiarazioni.
In C++, un oggetto globale viene allocato dal compilatore. Può esistere una sola definizione, quindi le dimensioni di ogni definizione sono note in fase di compilazione.
Esempio: global in 'C' con più definizioni di tipo
// file: a.c
int x;
// file: b.c
char* x;
// file: c.c
float* x[3];
// file: example1-main.c
// global-buffer-overflow error
// AddressSanitizer reports a buffer overflow at the first line
// in function main() in all cases, REGARDLESS of the order in
// which the object files: a.obj, b.obj, and c.obj are linked.
double x[5];
int main() {
int rc = (int) x[5]; // Boom!
return rc;
}
Per compilare e testare questo esempio, eseguire questi comandi in un prompt dei comandi per sviluppatori di Visual Studio 2019 versione 16.9 o successiva:
cl a.c b.c c.c example1-main.c /fsanitize=address /Zi
devenv /debugexe example1-main.exe
Errore risultante
Esempio: statico a livello di funzione semplice
// example2.cpp
// global-buffer-overflow error
#include <string.h>
int
main(int argc, char **argv) {
static char XXX[10];
static char YYY[10];
static char ZZZ[10];
memset(XXX, 0, 10); memset(YYY, 0, 10); memset(ZZZ, 0, 10);
int res = YYY[argc * 10]; // Boom!
res += XXX[argc] + ZZZ[argc];
return res;
}
Per compilare e testare questo esempio, eseguire questi comandi in un prompt dei comandi per sviluppatori di Visual Studio 2019 versione 16.9 o successiva:
cl example2.cpp /fsanitize=address /Zi
devenv /debugexe example2.exe
Errore risultante - livello di funzione semplice statico
Esempio: tutti gli ambiti globali in C++
// example3.cpp
// global-buffer-overflow error
// Run 4 different ways with the choice of one of these options:
//
// -g : Global
// -c : File static
// -f : Function static
// -l : String literal
#include <string.h>
struct C {
static int array[10];
};
// normal global
int global[10];
// class static
int C::array[10];
int main(int argc, char **argv) {
int one = argc - 1;
switch (argv[1][1]) {
case 'g': return global[one * 11]; //Boom! simple global
case 'c': return C::array[one * 11]; //Boom! class static
case 'f':
{
static int array[10] = {};
return array[one * 11]; //Boom! function static
}
case 'l':
// literal global ptr created by compiler
const char *str = "0123456789";
return str[one * 11]; //Boom! .rdata string literal allocated by compiler
}
return 0;
}
Per compilare e testare questo esempio, eseguire questi comandi in un prompt dei comandi per sviluppatori di Visual Studio 2019 versione 16.9 o successiva:
cl example3.cpp /fsanitize=address /Zi
devenv /debugexe example3.exe -l
Errore risultante: tutti gli ambiti globali in C++
Vedi anche
Panoramica di AddressSanitizer
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