识别和预防静态缓冲区溢出的工具和方法

3

有没有工具或方法可以识别静态定义数组(即char [1234]而不是malloc(1234))中的缓冲区溢出?

昨天我大部分时间都在追踪崩溃和奇怪的行为,最终发现是以下代码行引起的:

// ensure string is nul terminated due to stupid snprintf
error_msg[error_msg_len] = '\0';

这个索引显然导致了数组越界写入。这导致指针变量被破坏,从而导致后来该指针的意外行为。
我想到了三件事可以帮助缓解这些问题:
1. 代码审查 这没有做,但我正在努力做到这一点。
2. valgrind 我经常在开发过程中使用valgrind来检测内存问题,但它不能处理静态数组。在上面的例子中,它只向我显示了症状,比如被破坏的指针的无效free()。
3. -fstack-protector-all 在过去,我使用-fstack-protector-all来检测像上面那样的溢出,但由于某种奇怪的原因,在这种情况下它没有标记任何东西。
那么有人能提供任何关于如何识别这样的溢出的想法吗?无论是通过改进上述列表还是通过完全新的方法。
编辑:到目前为止,一些答案已经提到了相当昂贵的商业产品。在这个阶段,我不认为我能说服权力机构购买这样的工具,所以我想将工具限制在便宜/免费的范围内。是的,你得到你所付出的,但一些改进总比没有好。

1
我知道这与所问的问题无关,但是 snprintf 会添加空字符终止符。 - Steve Jessop
我使用了Coverity来捕获这些错误,它是一个非常优秀的静态分析工具。然而它并不免费(或便宜)。 - TJD
@Steve Jessop 很好的观点。如果你以某种方式编写了超过可用缓冲区大小的内容(这本身就是一个问题),那么就需要对sprintf进行保护。所以事实证明,那行代码不仅存在缓冲区溢出的问题,而且也是无意义的。唉。 - Burhan Ali
@Burhan:代码的作者可能将其与strncpy混淆了,除非在达到目标大小限制之前在源中找到它,否则它不会向目标写入nul字节。 - Steve Jessop
3个回答

3

静态分析工具能够检测到一些缓冲区溢出。

例如,对于以下代码:

char bla[1024];
int i;

for (i = 0; i <= 1024; i++)
    bla[i] = 0;

以下是PC-Lint / flexelint报告的内容:

tst.c 9 警告 661: 可能由于运算符'['而访问越界指针(数据末尾之后的1) [参考:文件tst.c:第8行,第9行]


+1,但请确保您在手册开头阅读了“与 Lint 一起生活”的章节,否则可能会收到大量消息。 - SmacL
是的,@ShaneMacLaughlin,这就是静态分析器的问题,它们可能非常冗长,读取它们的输出报告可能需要很多时间。 - ouah
flexelint 似乎需要付费。我不确定我能否说服管理层现在这样做,那么您有没有尝试过其他静态分析工具并可以推荐的? - Burhan Ali

1

你尝试过实验性的Valgrind工具"SGCheck:一种实验性的堆栈和全局数组溢出检测器",而不是默认的“memcheck”工具吗?

http://valgrind.org/docs/manual/sg-manual.html

我自己没有尝试过,但它似乎涵盖了你感兴趣的某些类型的错误。

显然,Valgrind执行的是动态分析而不是静态分析,这是一个完全不同的讨论。


0

我们的CheckPointer工具是一种动态分析工具,可以捕捉数组越界错误,无论它们在哪里。

CheckPointer可以捕获Valgrind无法捕获的很多问题,例如超出任何结构或结构字段引用,包括静态数组,如OP所示的问题。Valgrind无法检测此类溢出,因为它对正在操作的数据的实际形状一无所知; 这需要了解编程语言,例如C。Valgrind只能检测分配内存外的引用。Checkpointer之所以能够做到这一点,是因为它深入了解C;它使用完整的类似编译器的C前端来收集类型和关键大小信息。

目前它可用于C,但还不适用于C++。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接