所以我有这段简单的代码来演示一个简单的缓冲区溢出:
#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上运行的免费软件会很好。
答案 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 *)....虽然我可能不正确。