C中的字符串溢出检测

时间:2010-02-24 01:15:13

标签: c string memory buffer-overflow memory-corruption

我们正在使用DevPartners boundchecker来检测内存泄漏问题。它做得很棒,虽然它没有发现字符串溢出,如下所示

char szTest [1] = "";

for (i = 0; i < 100; i ++) {

    strcat (szTest, "hi");
}

问题1:无论如何,我可以让BoundsChecker检测到这个吗?

问题2:他们的任何其他工具是否可以检测到此类问题?

8 个答案:

答案 0 :(得分:2)

一种选择是简单地禁止使用没有目标缓冲区信息的字符串函数。普遍包含的标题中的以下一组宏可能会有所帮助:

#define strcpy  strcpy_is_banned_use_strlcpy
#define strcat  strcat_is_banned_use_strlcat
#define strncpy strncpy_is_banned_use_strlcpy
#define strncat strncat_is_banned_use_strlcat
#define sprintf sprintf_is_banned_use_snprintf

因此,任何尝试使用“禁止”例程都会导致链接器错误,该错误也会告诉您应该使用什么。 MSVC做了类似的事情,可以使用像_CRT_SECURE_NO_DEPRECATE这样的宏来控制。

这种技术的缺点是,如果你拥有大量现有代码,那么将事情转移到使用新的更安全的例程可能是一项繁重的工作。它可以让你发疯,直到你摆脱了被认为危险的功能。

答案 1 :(得分:2)

valgrind将检测写入过去动态分配的数据,但我不认为它可以为您的示例中的自动数组执行此操作。如果您使用strcatstrcpy等,则必须确保目的地足够大。

编辑:我是right about valgrind,但有一些希望:

  

不幸的是,Memcheck没有对静态或堆栈数组进行边界检查。我们想,但是不可能以合理的方式做到与Memcheck的工作方式相符。遗憾。

     

然而,实验工具Ptrcheck可以检测到这样的错误。使用--tool=exp-ptrcheck选项运行Valgrind进行尝试,但要注意它不如Memcheck强大。

我没有使用过Ptrcheck。

答案 2 :(得分:2)

我在我的devpartner中尝试过(msvc6.6)(devpartner 7.2.0.372)

我确认你观察到的行为。 大约63次循环后我收到了访问冲突。

compuware对这个问题有什么看法?

CppCheck会检测到此问题。

答案 3 :(得分:1)

您可能会发现编译器可以提供帮助。例如,在Visual Studio 2008中,检查项目属性 - C / C ++ - 代码生成页面。这是一个“缓冲区安全检查”选项。

我的猜测是它会保留一些额外的内存并在那里写一个已知的序列。如果该序列被修改,则假定缓冲区溢出。不过我不确定 - 我记得在某个地方读过这个,但我不记得是否确定它是关于VC ++的。

答案 4 :(得分:1)

鉴于你已经标记了这个C ++,为什么要使用指向char的指针?

std::stringstream test;
std::fill_n(std::ostream_iterator<std::string>(test), 100, "hi");

答案 5 :(得分:1)

如果启用/RTCs compiler switch,可能会有助于解决此类问题。启用此选项后,仅在运行strcat一次时,测试会导致访问冲突。

另一个有用的实用程序可以帮助解决这类问题(比堆栈更面向堆但非常有用)application verifier。它是免费的,可以捕获许多与堆溢出有关的问题。

答案 6 :(得分:0)

另一种选择:我们的Memory Safety Checker。 我认为它会处理这种情况。

答案 7 :(得分:0)

问题是默认情况下,API验证子系统未启用,您感兴趣的邮件来自那里。

我不能代表旧版本的BoundsChecker,但10.5版本对此测试没有特别的问题。它报告正确的结果,BoundsChecker本身不会崩溃。但是,测试应用程序会这样做,因为这个特定的测试用例会完全破坏导致测试代码所在的函数的调用堆栈,并且一旦该函数终止,应用程序也会这样做。

结果:1​​00条关于写入超出本地变量的消息,以及99条关于目标字符串未被空终止的消息。从技术上讲,第二条消息不正确,但BoundsChecker只在目标字符串本身的范围内搜索空终止,并且在第一次strcat调用之后,它的边界内不再包含零字节。

免责声明:我作为开发BoundsChecker的开发人员为MicroFocus工作。