什么C/ c++函数最常被错误地使用,并可能导致缓冲区溢出?

时间:2022-09-06 18:33:53

I've been asked to maintain a large C++ codebase full of memory leaks. While poking around, I found out that we have a lot of buffer overflows that lead to the leaks (how it got this bad, I don't ever want to know).

我被要求维护一个包含大量内存泄漏的大型c++代码库。当我四处查看时,我发现我们有很多缓冲区溢出导致了泄漏(我从来不想知道它是如何变得如此糟糕的)。

I've decided to removing the buffer overflows first, starting with the dangerous functions. What C/C++ functions that are most often used incorrectly and can lead to buffer overflow?

我决定首先删除缓冲区溢出,从危险的函数开始。什么C/ c++函数最常被错误使用,并可能导致缓冲区溢出?

For compiler and/or tools used to help look for buffer overrun, I've created another question that deals with this

对于用于查找缓冲区溢出的编译器和/或工具,我创建了另一个问题来处理这个问题

11 个解决方案

#1


11  

In general, any function that does not check bounds in the arguments. A list would be

一般来说,任何不检查参数边界的函数。将列表

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

You should use size limited versions like stncpy, strncat, fgets, etc. Then be careful while giving the size limit; take into consideration the '\0' terminating the string.

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

Also, arrays are NOT bound checked in C or C++. The following example would cause errors. See off by one error

此外,在C或c++中不检查数组绑定。下面的示例将导致错误。以一个错误结束

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

edit: Copied answers of @MrValdez , @Denton Gentry

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

#2


5  

Valgrind is your new best friend.

Valgrind是你最好的朋友。

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

valgrind——工具= memcheck检查漏气=饱了。/ a.o ut

#3


3  

The question is starting at the wrong end, I'm afraid. It's presuming that buffer overruns happen in other functions. The most common cause is operator++, in my experience, or alternatively a lack of operator!=.

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

The best solution to find a batch of those is /GS in Visual Studio 2005/8. It won't find all of them, but it's a cheap way to reduce the amount of manual work needed.

最好的解决办法是在Visual Studio 2005/8中找到一批。它不会找到所有的,但它是减少手工工作量的廉价方法。

#4


2  

Here's some functions that I found that are dangerous:

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

  • gets() - It doesn't check the length of the variable and can overwrite memory if the input is bigger than the variable's buffer.
  • gets()——它不检查变量的长度,如果输入大于变量的缓冲区,则可以覆盖内存。
  • scanf() - I'm so glad that Visual Studio told me this function is deprecated. This was an easy fix.
  • scanf() -我很高兴Visual Studio告诉我不赞成使用这个函数。这是一个简单的解决办法。
  • strcpy() - If the source's memory space is bigger than the destination's, the data after the destination is overwritten.
  • strcpy()——如果源的内存空间大于目标空间,则覆盖目标后的数据。

#5


2  

Unfortunately any array can result in a buffer overflow:

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

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

In terms of functions, sprintf will happily walk off the end of the buffer. It can be replaced by snprintf.

在函数方面,sprintf会很高兴地从缓冲区的末尾走出来。它可以被snprintf代替。

#6


2  

Memcpy() is another dangerous one.

Memcpy()是另一个危险的问题。

Any loop accessing an array is a danger point, because there's no stopping going beyond the end of array.

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

Memory Leaks are caused by allocating memory, and not freeing it. Constructor and destructors should be another strong review point, the latter to make sure any allocated memory is freeded.

内存泄漏是由分配内存引起的,而不是释放内存。构造函数和析构函数应该是另一个强的检查点,后者可以确保任何分配的内存都是空闲的。

#7


2  

Which version of visual studio are you using? In 2008 with all warnings enabled, all the functions you mention (and more) warn you that they are deprecated.

您使用的是哪个版本的visual studio ?在2008年启用了所有警告后,您提到(以及更多)的所有函数都警告您不赞成使用它们。

Perhaps you could check that all warnings are turned on and let the compiler do the hard work for you?

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

As a side note, the excellent writing secure code does a great job explaining the different the pitfalls of some of the older functions.

作为补充说明,优秀的编写安全代码很好地解释了一些旧函数的不同缺陷。

#8


2  

I have somewhat the same problem on the code base I work on. My advice: be wary of any C functions that look like str*() and mem*(). Also be wary of anything that takes a pointer to a buffer, without a length. Since it seems like you have the chance to use C++ I would in the most egregious cases try to use C++ containers for things: vector, string, map, etc. These make your life a lot easier.

在我处理的代码库上,我有一些相同的问题。我的建议是:警惕任何看起来像str*()和mem*()的C函数。也要注意任何不带长度的指向缓冲区的指针。因为看起来您有机会使用c++,我将在最恶劣的情况下尝试使用c++容器来做一些事情:向量、字符串、映射等等,这些使您的生活变得更加轻松。

Also, automated problem detection tools are wonderful to have. If you can use valgrind I would recommend it. Also Rational Purify is extremely powerful, though not cheap.

同样,自动化的问题检测工具也是很好的选择。如果你能使用valgrind,我将推荐它。Rational Purify也非常强大,虽然不便宜。

#9


2  

The following link should give you a comprehensive look at security functions in C++ (ones that are post-fixed with '_s' to fix problems like overflows): http://msdn.microsoft.com/en-us/library/8ef0s5kh(VS.80).aspx

下面的链接应该让您全面了解c++中的安全函数(用'_s'后缀的函数,以修复诸如溢出之类的问题):http://msdn.microsoft.com/en-us/library/8ef0s5kh(VS.80).aspx

EDIT: This link contains the specific functions that have been replaced: http://msdn.microsoft.com/en-us/library/wd3wzwts(VS.80).aspx

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

EDIT: I should mention these are Microsoft methods, but the link is still useful for identifying functions that were deemed a red flag.

编辑:我应该提到这些是微软的方法,但是这个链接对于识别那些被认为是危险信号的函数仍然很有用。

#10


1  

An additional gotcha in C is the "strncpy()" function. Many people do not realize that it is free to return a string that is not null terminated.

C中的另一个陷阱是“strncpy()”函数。许多人没有意识到返回一个非空终止的字符串是*的。

#11


0  

Basically, anything which accept a pointer and writes to it, without checking the length. So thing like strcpy(), sprintf() etc.

基本上,任何接受指针并对其进行写入的操作,都不需要检查长度。比如strcpy()和sprintf()等等。

#1


11  

In general, any function that does not check bounds in the arguments. A list would be

一般来说,任何不检查参数边界的函数。将列表

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

You should use size limited versions like stncpy, strncat, fgets, etc. Then be careful while giving the size limit; take into consideration the '\0' terminating the string.

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

Also, arrays are NOT bound checked in C or C++. The following example would cause errors. See off by one error

此外,在C或c++中不检查数组绑定。下面的示例将导致错误。以一个错误结束

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

edit: Copied answers of @MrValdez , @Denton Gentry

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

#2


5  

Valgrind is your new best friend.

Valgrind是你最好的朋友。

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

valgrind——工具= memcheck检查漏气=饱了。/ a.o ut

#3


3  

The question is starting at the wrong end, I'm afraid. It's presuming that buffer overruns happen in other functions. The most common cause is operator++, in my experience, or alternatively a lack of operator!=.

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

The best solution to find a batch of those is /GS in Visual Studio 2005/8. It won't find all of them, but it's a cheap way to reduce the amount of manual work needed.

最好的解决办法是在Visual Studio 2005/8中找到一批。它不会找到所有的,但它是减少手工工作量的廉价方法。

#4


2  

Here's some functions that I found that are dangerous:

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

  • gets() - It doesn't check the length of the variable and can overwrite memory if the input is bigger than the variable's buffer.
  • gets()——它不检查变量的长度,如果输入大于变量的缓冲区,则可以覆盖内存。
  • scanf() - I'm so glad that Visual Studio told me this function is deprecated. This was an easy fix.
  • scanf() -我很高兴Visual Studio告诉我不赞成使用这个函数。这是一个简单的解决办法。
  • strcpy() - If the source's memory space is bigger than the destination's, the data after the destination is overwritten.
  • strcpy()——如果源的内存空间大于目标空间,则覆盖目标后的数据。

#5


2  

Unfortunately any array can result in a buffer overflow:

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

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

In terms of functions, sprintf will happily walk off the end of the buffer. It can be replaced by snprintf.

在函数方面,sprintf会很高兴地从缓冲区的末尾走出来。它可以被snprintf代替。

#6


2  

Memcpy() is another dangerous one.

Memcpy()是另一个危险的问题。

Any loop accessing an array is a danger point, because there's no stopping going beyond the end of array.

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

Memory Leaks are caused by allocating memory, and not freeing it. Constructor and destructors should be another strong review point, the latter to make sure any allocated memory is freeded.

内存泄漏是由分配内存引起的,而不是释放内存。构造函数和析构函数应该是另一个强的检查点,后者可以确保任何分配的内存都是空闲的。

#7


2  

Which version of visual studio are you using? In 2008 with all warnings enabled, all the functions you mention (and more) warn you that they are deprecated.

您使用的是哪个版本的visual studio ?在2008年启用了所有警告后,您提到(以及更多)的所有函数都警告您不赞成使用它们。

Perhaps you could check that all warnings are turned on and let the compiler do the hard work for you?

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

As a side note, the excellent writing secure code does a great job explaining the different the pitfalls of some of the older functions.

作为补充说明,优秀的编写安全代码很好地解释了一些旧函数的不同缺陷。

#8


2  

I have somewhat the same problem on the code base I work on. My advice: be wary of any C functions that look like str*() and mem*(). Also be wary of anything that takes a pointer to a buffer, without a length. Since it seems like you have the chance to use C++ I would in the most egregious cases try to use C++ containers for things: vector, string, map, etc. These make your life a lot easier.

在我处理的代码库上,我有一些相同的问题。我的建议是:警惕任何看起来像str*()和mem*()的C函数。也要注意任何不带长度的指向缓冲区的指针。因为看起来您有机会使用c++,我将在最恶劣的情况下尝试使用c++容器来做一些事情:向量、字符串、映射等等,这些使您的生活变得更加轻松。

Also, automated problem detection tools are wonderful to have. If you can use valgrind I would recommend it. Also Rational Purify is extremely powerful, though not cheap.

同样,自动化的问题检测工具也是很好的选择。如果你能使用valgrind,我将推荐它。Rational Purify也非常强大,虽然不便宜。

#9


2  

The following link should give you a comprehensive look at security functions in C++ (ones that are post-fixed with '_s' to fix problems like overflows): http://msdn.microsoft.com/en-us/library/8ef0s5kh(VS.80).aspx

下面的链接应该让您全面了解c++中的安全函数(用'_s'后缀的函数,以修复诸如溢出之类的问题):http://msdn.microsoft.com/en-us/library/8ef0s5kh(VS.80).aspx

EDIT: This link contains the specific functions that have been replaced: http://msdn.microsoft.com/en-us/library/wd3wzwts(VS.80).aspx

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

EDIT: I should mention these are Microsoft methods, but the link is still useful for identifying functions that were deemed a red flag.

编辑:我应该提到这些是微软的方法,但是这个链接对于识别那些被认为是危险信号的函数仍然很有用。

#10


1  

An additional gotcha in C is the "strncpy()" function. Many people do not realize that it is free to return a string that is not null terminated.

C中的另一个陷阱是“strncpy()”函数。许多人没有意识到返回一个非空终止的字符串是*的。

#11


0  

Basically, anything which accept a pointer and writes to it, without checking the length. So thing like strcpy(), sprintf() etc.

基本上,任何接受指针并对其进行写入的操作,都不需要检查长度。比如strcpy()和sprintf()等等。