Aracılığıyla paylaş


Hata: global-buffer-overflow

Adres Temizleme Hatası: Genel arabellek taşması

Derleyici, veya .bss bölümlerindeki .data herhangi bir değişken için meta veriler oluşturur. Bu değişkenlerin dil kapsamı genel veya dosya statiktir. Bunlar başlamadan önce main() bellekte ayrılır. C'deki genel değişkenler C++ dilinden çok farklı şekilde değerlendirilir. Bu farkın nedeni C'yi bağlamaya yönelik karmaşık kurallardır.

C'de, genel değişken birkaç kaynak dosyada bildirilebilir ve her tanımın farklı türleri olabilir. Derleyici tüm olası tanımları aynı anda göremez, ancak bağlayıcı görebilir. C için bağlayıcı varsayılan olarak tüm farklı bildirimler arasından en büyük boyutlu değişkeni seçer.

C++ dilinde, derleyici tarafından bir genel ayrılır. Yalnızca bir tanım olabileceğinden, her tanımın boyutu derleme zamanında bilinir.

Örnek - 'C' dilinde birden çok tür tanımına sahip geneller

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

Bu örneği derlemek ve test etmek için visual studio 2019 sürüm 16.9 veya sonraki bir geliştirici komut isteminde şu komutları çalıştırın:

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

Sonuçta oluşan hata

Örnek 1'de genel arabellek taşması hatasını görüntüleyen hata ayıklayıcının ekran görüntüsü.

Örnek - basit işlev düzeyi statik

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

Bu örneği derlemek ve test etmek için visual studio 2019 sürüm 16.9 veya sonraki bir geliştirici komut isteminde şu komutları çalıştırın:

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

Sonuç hatası - basit işlev düzeyi statik

Örnek 2'de genel arabellek taşması hatasını görüntüleyen hata ayıklayıcının ekran görüntüsü.

Örnek - C++ içindeki tüm genel kapsamlar

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

Bu örneği derlemek ve test etmek için visual studio 2019 sürüm 16.9 veya sonraki bir geliştirici komut isteminde şu komutları çalıştırın:

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

Sonuç hatası - C++ içindeki tüm genel kapsamlar

Örnek 3'te genel arabellek taşması hatasını görüntüleyen hata ayıklayıcının ekran görüntüsü.

Ayrıca bkz.

AddressSanitizer'a genel bakış
AddressSanitizer bilinen sorunları
AddressSanitizer derlemesi ve dil başvurusu
AddressSanitizer çalışma zamanı başvurusu
AddressSanitizer gölge baytları
AddressSanitizer bulut veya dağıtılmış test
AddressSanitizer hata ayıklayıcısı tümleştirmesi
AddressSanitizer hata örnekleri