为什么电栅栏/ Valgrind无法捕获这个缓冲区溢出问题?

我创建了一个错误的程序 – buggy.c – 这是缓冲区t的缓冲区溢出方案。 您可以看到我正在编写超过5个索引。 它工作正常。 它永远不会给我一个错误。 我在想,为什么会那样? 我甚至试过Valgrind,这也找不到这个问题。 你能告诉我这里有什么问题吗?

void buffer_overflow(void) { int t[5]; int i = 0; for(i = 0; i<=7; i++) { t[i] = i; } /** this will cause buffer overflow **/ printf("Memory_overflow_completed\r\n"); } int main(int argc, char **argv) { buffer_overflow(); return 0; } $gcc -g buggy.c -o buggy.out -lefence $./buggy.out 

但是,我没有遇到任何崩溃。 这里没有电围栏的效果。 我错过了什么? 我看到这里发布的类似问题gcc用电栅栏库没有生效 ,但似乎还没有答案。 我在FC19上运行这个例子。 有人有答案吗? 甚至valgrind也未能发现问题? 还有其他工具可以检测这些问题吗?

根据进一步的评论,我修改了缓冲区溢出函数,以便被Electric Fence检测到。 但是,电围栏无法检测到这个问题。 这是修改后的function。

 void buffer_overflow(void) { #if 0 int t[5]; int i = 0; for(i = 0; i<=7; i++) { t[i] = i; } #endif char *t = malloc(sizeof(char)*7); strcpy(t,"SHREYAS_JOSHI"); /** this will cause buffer overflow **/ printf("Memory_overflow_completed\r\n"); free(t); } [joshis1@localhost blogs-tune2wizard]$ gcc -g buggy.c -o buggy.out -lefence [joshis1@localhost blogs-tune2wizard]$ ./buggy.out Electric Fence 2.2.2 Copyright (C) 1987-1999 Bruce Perens  Memory_overflow_completed 

Electric Fence没有检测到任何错误,但Valgrind至少表现出来了。

Valgrind仅限于二元可用。 如果您不介意在代码中插入一些检测(通过编译器),您可以尝试使用地址清理程序 。 它会限制分配区域(甚至堆栈)的内存,然后检查每次读/写,因此它有更高的机会来捕获这些问题。

它集成在当前的gcc(4.8+)和clang(3.2+)中。只需编译你的代码,如:

 gcc -g buggy.c -o buggy.out -fsanitize=address 

在执行时,它打印如下:

 ==26247== ERROR: AddressSanitizer: stack-buffer-overflow on address 0x7fff9fa0be54 at pc 0x4008df bp 0x7fff9fa0be00 sp 0x7fff9fa0bdf8 WRITE of size 4 at 0x7fff9fa0be54 thread T0 

和堆栈跟踪。

Chandler Carruth 在GN13的这次演讲中谈到了这一点

注意:即使在clang 3.1中也支持它,但是该开关被称为-faddress-sanitizer而不是-fsanitize=address

运行valgrind --tool=exp-sgcheck ./buggy.out ,它应该能够检测到你在局部变量t[5]有缓冲区溢出

Valgrind和EF检测动态分配的内存中的错误。 您的数组未动态分配。

引用valgrind 快速入门指南 :“例如,它无法检测超出范围的读取或写入静态分配或堆栈的数组。”

要检测静态分配的内存(即堆栈中)的越界访问,可以使用静态代码分析工具。

我们刚刚开始在工作中使用的是Klocwork

正如Valgrind wiki页面上所提到的(在memcheck的限制下),它无法检测静态分配的内存上的超出访问。 引用维基:

已经编写了实验性的valgrind工具exp-sgcheck来解决Memcheck中的这个限制。 如果第一次访问数组在数组范围内,它将检测数组溢出错误。