Erro: global-buffer-overflow
Erro do Sanitizador de Endereço: estouro de buffer global
O compilador gera metadados para qualquer variável nas seções .data
ou .bss
. Essas variáveis têm escopo de linguagem de estático global ou de arquivo. Eles são alocados na memória antes main()
de começar. As variáveis globais em C são tratadas de forma muito diferente da do C++. Essa diferença ocorre devido às regras complexas para vincular C.
Em C, uma variável global pode ser declarada em vários arquivos de origem e cada definição pode ter tipos diferentes. O compilador não pode ver todas as definições possíveis de uma só vez, mas o vinculador pode. Para C, o vinculador usa como padrão selecionar a variável de maior tamanho de todas as diferentes declarações.
No C++, um global é alocado pelo compilador. Só pode haver uma definição, portanto, o tamanho de cada definição é conhecido no tempo de compilação.
Exemplo: globais em 'C' com várias definições de 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;
}
Para compilar e testar esse exemplo, execute estes comandos em um prompt de comando do desenvolvedor do Visual Studio 2019 versão 16.9 ou posterior:
cl a.c b.c c.c example1-main.c /fsanitize=address /Zi
devenv /debugexe example1-main.exe
Erro resultante
Exemplo: estático no nível de função simples
// 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;
}
Para compilar e testar esse exemplo, execute estes comandos em um prompt de comando do desenvolvedor do Visual Studio 2019 versão 16.9 ou posterior:
cl example2.cpp /fsanitize=address /Zi
devenv /debugexe example2.exe
Erro resultante: estático no nível de função simples
Exemplo: todos os escopos globais no 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;
}
Para compilar e testar esse exemplo, execute estes comandos em um prompt de comando do desenvolvedor do Visual Studio 2019 versão 16.9 ou posterior:
cl example3.cpp /fsanitize=address /Zi
devenv /debugexe example3.exe -l
Erro resultante: todos os escopos globais no C++
Confira também
Visão geral do AddressSanitizer
Problemas conhecidos do AddressSanitizer
Referência de linguagem e build do AddressSanitizer
Referência de runtime do AddressSanitizer
Bytes de sombra de AddressSanitizer
Nuvem do AddressSanitizer ou teste distribuído
Integração do depurador do AddressSanitizer
Exemplos de erro do AddressSanitizer