Freigeben über


Fehler: global-buffer-overflow

Adressbereinigungsfehler: Globaler Pufferüberlauf

Der Compiler generiert Metadaten für jede Variable in den .data Abschnitten oder .bss Abschnitten. Diese Variablen haben den Sprachumfang globaler oder datei statischer Dateien. Sie werden vor dem main() Start im Arbeitsspeicher zugewiesen. Globale Variablen in C werden viel anders behandelt als in C++. Dieser Unterschied liegt an den komplexen Regeln für die Verknüpfung von C.

In C kann eine globale Variable in mehreren Quelldateien deklariert werden, und jede Definition kann unterschiedliche Typen aufweisen. Der Compiler kann nicht alle möglichen Definitionen gleichzeitig sehen, aber der Linker kann. Bei C wählt der Linker standardmäßig die Variable der größten Größe aus allen verschiedenen Deklarationen aus.

In C++ wird vom Compiler eine globale Zuordnung zugewiesen. Es kann nur eine Definition geben, sodass die Größe jeder Definition zur Kompilierungszeit bekannt ist.

Beispiel : Globalen in "C" mit mehreren Typdefinitionen

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

Führen Sie zum Erstellen und Testen dieses Beispiels die folgenden Befehle in einer Visual Studio 2019,16.9- oder höher-Entwickler-Eingabeaufforderung aus:

cl a.c b.c c.c example1-main.c /fsanitize=address /Zi
devenv /debugexe example1-main.exe

Resultierender Fehler

Screenshot des Debuggers, der den Global-Buffer-Overflow-Fehler in Beispiel 1 anzeigt.

Beispiel : Einfache Funktionsebene statisch

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

Führen Sie zum Erstellen und Testen dieses Beispiels die folgenden Befehle in einer Visual Studio 2019,16.9- oder höher-Entwickler-Eingabeaufforderung aus:

cl example2.cpp /fsanitize=address /Zi
devenv /debugexe example2.exe

Resultierender Fehler – statische Einfache Funktionsebene

Screenshot des Debuggers, der den Fehler

Beispiel : alle globalen Bereiche 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;
}

Führen Sie zum Erstellen und Testen dieses Beispiels die folgenden Befehle in einer Visual Studio 2019,16.9- oder höher-Entwickler-Eingabeaufforderung aus:

cl example3.cpp /fsanitize=address /Zi
devenv /debugexe example3.exe -l

Resultierender Fehler – alle globalen Bereiche in C++

Screenshot des Debuggers, der den Fehler

Siehe auch

AddressSanitizer -Übersicht
Beheben bekannter Probleme mit demSanitizer
AddressSanitizer Build- und Sprachreferenz
AddressSanitizer-Laufzeitreferenz
AddressSanitizer-Schattenbytes
AddressSanitizer-Cloud oder verteilte Tests
AddressSanitizer Debugger-Integration
Beispiele für AddressSanitizer-Fehler