什么C / C ++函数最常使用不正确,可能导致缓冲区溢出?

时间:2008-10-03 14:33:57

标签: c++ c buffer-overflow buffer-overrun

我被要求维护一个充满内存泄漏的大型C ++代码库。在探索时,我发现我们有很多缓冲区溢出导致泄漏(它如何变坏,我不想知道)。

我决定首先删除缓冲区溢出,从危险函数开始。哪些C / C ++函数最常使用不正确并且可能导致缓冲区溢出?

对于用于帮助查找缓冲区溢出的编译器和/或工具,我created another question that deals with this

11 个答案:

答案 0 :(得分:11)

通常,任何不检查参数中的边界的函数。列表将是

  • 得到()
  • scanf()的
  • 的strcpy()
  • 的strcat()

你应该使用尺寸有限的版本,如stncpy,strncat,fgets等。然后在给出尺寸限制时要小心;考虑'\ 0'终止字符串。

此外,数组未在C或C ++中进行检查。以下示例将导致错误。见off by one error

int foo[3];
foo[3] = WALKED_OFF_END_OF_ARRAY;

编辑:@MrValdez,@ Denton Gentry的复制答案

答案 1 :(得分:5)

Valgrind是你最好的朋友。

valgrind --tool = memcheck --leak-check = full ./a.out

答案 2 :(得分:3)

问题是从错误的一端开始,我害怕。它假设缓冲区溢出发生在其他函数中。根据我的经验,最常见的原因是operator ++,或者缺少运算符!=。

在Visual Studio 2005/8中查找批量的最佳解决方案是/ GS。它不会找到所有这些,但它是减少所需手工工作量的廉价方法。

答案 3 :(得分:2)

以下是我发现的一些危险的功能:

  • gets() - 它不检查变量的长度,如果输入大于变量的缓冲区,则可以覆盖内存。
  • scanf() - 我很高兴Visual Studio告诉我这个功能已被弃用。这很容易解决。
  • strcpy() - 如果源的内存空间大于目标,则覆盖目标后的数据。

答案 4 :(得分:2)

以下链接应该让您全面了解C ++中的安全功能(使用'_s'进行后置修复以解决溢出等问题):http://msdn.microsoft.com/en-us/library/8ef0s5kh(VS.80).aspx

编辑:此链接包含已替换的特定功能:http://msdn.microsoft.com/en-us/library/wd3wzwts(VS.80).aspx

编辑:我应该提到这些是Microsoft方法,但该链接仍然可用于识别被视为红旗的功能。

答案 5 :(得分:2)

不幸的是,任何数组都可能导致缓冲区溢出:

uint32_t foo[3];
foo[3] = WALKED_OFF_END_OF_ARRAY;

在功能方面,sprintf很乐意走出缓冲区的末尾。它可以被snprintf替换。

答案 6 :(得分:2)

Memcpy()是另一个危险的。

任何访问数组的循环都是一个危险点,因为没有超出数组末尾的停止。

内存泄漏是由分配内存引起的,而不是释放它。构造函数和析构函数应该是另一个强有力的评论点,后者是为了确保任何已分配的内存都是自由的。

答案 7 :(得分:2)

您使用的是哪个版本的visual studio?在2008年启用所有警告后,您提及的所有功能(以及更多)都会警告您已弃用它们。

也许您可以检查是否已打开所有警告并让编译器为您完成了艰苦的工作?

作为旁注,优秀的writing secure code可以很好地解释一些旧功能的不同之处。

答案 8 :(得分:2)

我在处理的代码库上遇到了同样的问题。我的建议:警惕任何看起来像str *()和mem *()的C函数。还要注意任何指向缓冲区的指针,没有长度。由于您似乎有机会使用C ++,我会在最恶劣的情况下尝试使用C ++容器来处理事物:矢量,字符串,地图等。这些会让您的生活更轻松。

此外,自动化问题检测工具非常棒。如果你可以使用valgrind我会推荐它。 Rational Purify也非常强大,但并不便宜。

答案 9 :(得分:1)

C中的另一个问题是“strncpy()”函数。许多人没有意识到可以自由地返回一个非空终止的字符串。

答案 10 :(得分:0)

基本上,任何接受指针并写入指针而不检查长度的东西。所以像strcpy(),sprintf()等。