什么工具可以捕获C中的缓冲区溢出?

时间:2009-11-15 07:39:26

标签: c debugging stack

所以我有这段简单的代码来演示一个简单的缓冲区溢出:

#include <stdio.h>

int main(void)
{
    char c[4] = { 'A', 'B', 'C', 'D' };
    char d[4] = { 'W', 'X', 'Y', 'Z' };

    printf("c[0] is '%c'\n", c[0]);

    d[4] = 'Z'; /* Overflow that overwrites c[0] */

    printf("c[0] is '%c'\n", c[0]);

    return 0;
}

输出:

$ ./a.out
c[0] is 'A'
c[0] is 'Z'

我尝试使用以下gcc选项编译此代码,并以常亮颜色传递:

gcc -Wall -Wextra -Wformat=2 -Wswitch-default -Wcast-align -Wpointer-arith \
    -Wbad-function-cast -Wstrict-prototypes -Winline -Wundef -Wnested-externs \
    -Wcast-qual -Wshadow -Wwrite-strings -Wconversion -Wunreachable-code \
    -Wstrict-aliasing=2 -ffloat-store -fno-common -fstrict-aliasing \
    -Wstack-protector -fstack-protector-all -std=c99 -pedantic -O0 -ggdb3

我也试过libefence和valgrind 。我希望libefence能够通过,因为它可以捕获堆上的读/写区域,但是我很惊讶valgrind通过了。

此代码不会产生Segfault,因为c [4]和d [0]碰巧重叠,我认为这导致工具错过它。

那么, CAN 会抓住这个?在Linux上运行的免费软件会很好。

11 个答案:

答案 0 :(得分:5)

试试cppcheck。它对我有用。

答案 1 :(得分:2)

由于valgrind在二进制文件上工作,所以它没有看到这个代码有什么问题。检查这些(http://www.thefreecountry.com/programming/debuggers.shtml)静态源代码分析器,他们应该找到。如果它们不起作用,PC-lint(http://www.gimpel.com/html/pcl.htm)将处理这个....

答案 2 :(得分:2)

尝试使用Bugfighter C / C ++。

我每天都使用它,它工作正常,即使是像array[5][5][5]这样的多维数组。

Bugfighter网页是www.bugfighter-soft.com。

答案 3 :(得分:2)

valgrind的memcheck正在检测堆内存

对于堆栈,您可以尝试valgrind的SGCheck

答案 4 :(得分:1)

Rational Purify在检测缓冲区溢出,内存泄漏,损坏等方面非常有效。但它非常昂贵。

提到的mem包in this SO answer可能是另一种选择。

答案 5 :(得分:1)

Coverity(静态分析工具)会抓住这个。

答案 6 :(得分:0)

如果是在linux上,我会首先尝试valgrind,我认为它会处理它。

编辑:如果它像SiegeX说我猜valgrind没有(这是有道理的,因为它无法在堆栈上插入防护,因为它只涉及进程运行时)。无论如何,这是一个很好的工具,值得在你的工具箱中使用,所以我会保留帖子。

答案 7 :(得分:0)

缓冲区溢出很难在C中捕获,因为它们直到运行时才会发生。为了最大限度地减少创建一个边界的机会,你应该使用更安全的标准库函数进行一些边界检查 - 例如fgets()而不是gets()。

如果您手动操作大量数组,您应该编写单元测试来检查算法中的边缘情况。 Cmockery是C的单元测试框架的一个例子。

答案 8 :(得分:0)

Valgrind在自动和静态存储中没有捕获溢出。至少不是默认情况下。 IIRC要使其工作,你应该打开一些选项或运行随附的“开发中”工具,而不是默认的“memcheck”。

答案 9 :(得分:0)

visual studio(我认为-Zi,但我可能错了)用它的运行时堆栈检查器捕获这种赋值。它不是您喜欢的免费Linux解决方案,但确实可以很好地工作。

答案 10 :(得分:-1)

我认为在这种情况下有一个隐含的空字符,因为你引用了一个文字字符串。因此,d [4]仍然在界限内(想象为const char *)....虽然我可能不正确。