为什么 MSVC++ 考虑“std::strcat” “不安全”? (C++)
当我尝试做这样的事情时:
char* prefix = "Sector_Data\\sector";
char* s_num = "0";
std::strcat(prefix, s_num);
std::strcat(prefix, "\\");
等等等等,我收到一条警告
warning C4996: 'strcat': This function or variable may be unsafe. Consider using strcat_s instead.
为什么 strcat 被认为是不安全的,有没有办法在不使用 strcat_s 的情况下消除此警告?
另外,如果消除警告的唯一方法是使用 strcat_s,它是如何工作的(语法方面:显然它不需要两个参数)。
When I try to do things like this:
char* prefix = "Sector_Data\\sector";
char* s_num = "0";
std::strcat(prefix, s_num);
std::strcat(prefix, "\\");
and so on and so forth, I get a warning
warning C4996: 'strcat': This function or variable may be unsafe. Consider using strcat_s instead.
Why is strcat considered unsafe, and is there a way to get rid of this warning without using strcat_s?
Also, if the only way to get rid of the warning is to use strcat_s, how does it work (syntax-wise: apparently it does not take two arguments).
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(7)
如果您使用的是 C++,为什么不避免整个混乱并使用
std::string
。 没有任何错误的相同示例将如下所示:无需担心缓冲区大小和所有其他内容。 如果您有一个采用
const char *
的 API,则可以只使用.c_str()
成员;If you are using c++, why not avoid the whole mess and use
std::string
. The same example without any errors would look like this:no need to worry about buffer sizes and all that stuff. And if you have an API which takes a
const char *
, you can just use the.c_str()
member;因为缓冲区前缀的空间可能小于您复制到其中的空间,从而导致缓冲区溢出。
因此,黑客可以传入一个特制的字符串,该字符串会覆盖返回地址或其他关键内存,并开始在程序上下文中执行代码。
strcat_s 通过强制您传入要将字符串复制到的缓冲区的长度来解决此问题; 如有必要,它将截断字符串以确保缓冲区不会溢出。
google strcat_s 来准确了解如何使用它。
Because the buffer, prefix, could have less space than you are copying into it, causing a buffer overrun.
Therefore, a hacker could pass in a specially crafted string which overwrites the return address or other critical memory and start executing code in the context of your program.
strcat_s solves this by forcing you to pass in the length of the buffer into which you are copying the string; it will truncate the string if necessary to make sure that the buffer is not overrun.
google strcat_s to see precisely how to use it.
消除这些警告。
您可以通过添加:和
到项目的预处理器定义中来
You can get rid of these warning by adding:
and
to your project's preprocessor definitions.
这是 C/C++ 中可能导致缓冲区溢出错误的字符串操作函数之一。
问题是该函数不知道缓冲区的大小是多少。 来自 MSDN 文档:
strcat_s 需要一个额外的参数来告诉它缓冲区的大小。 这允许它在执行连接之前验证大小,并防止溢出。 请参阅 http://msdn.microsoft.com/en-us/library/d45bbxx4 .aspx
That's one of the string-manipulation functions in C/C++ that can lead to buffer overrun errors.
The problem is that the function doesn't know what the size of the buffers are. From the MSDN documentation:
strcat_s takes an extra argument telling it the size of the buffer. This allows it to validate the sizes before doing the concat, and will prevent overruns. See http://msdn.microsoft.com/en-us/library/d45bbxx4.aspx
因为它无法检查您的情况下的目标字符串(前缀)是否会超出其范围。 strcat 本质上是通过循环将源字符串逐字节复制到目标中来工作的。 当它看到值“0”(用“\0”表示)(称为空终端)时,它会停止。 由于 C 没有内置的边界检查,并且 dest str 只是内存中的一个位置,因此 strcat 将继续无穷无尽,即使它超出了源 str 或 dest。 str 没有空终端。
上述解决方案是特定于您的 Windows 环境的平台。 如果你想要独立于平台的东西,你必须与 strncat 争论:
这是明智使用时的另一个选择。 您可以使用 count 来指定要复制的最大字符数。 为此,您必须计算出 dest 中有多少可用空间(您分配了多少空间 - strlen(dest))并将其作为计数传递。
Because it has no means of checking to see if the destination string (prefix) in your case will be written past its bounds. strcat essentially works by looping, copying byte-by-byte the source string into the destination. Its stops when it sees a value "0" (notated by '\0') called a null terminal. Since C has no built in bounds checking, and the dest str is just a place in memory, strcat will continue going ad-infinidium even if it blows past the source str or the dest. str doesn't have a null terminal.
The solutions above are platform-specific to your windows environment. If you want something platform independent, you have to wrangle with strncat:
This is another option when used intelligently. You can use count to specify the max number of characters to copy. To do this, you have to figure out how much space is available in dest (how much you allocated - strlen(dest)) and pass that as count.
要关闭警告,您可以执行以下操作。
顺便说一句,我强烈建议您使用 strcat_s()。
To turn the warning off, you can do this.
btw, I strongly recommend that you use strcat_s().
strcat 有两个问题。 首先,您必须在函数外部进行所有验证,执行与函数几乎相同的工作:
您必须遍历两个字符串的整个长度以确保它适合,然后再次遍历它们的整个长度做副本。 因此,许多程序员会简单地假设它适合并跳过测试。 更糟糕的是,可能在第一次编写代码时保证它适合,但是当有人添加另一个 strcat 或更改程序中其他位置的缓冲区大小或常量时,您现在就会遇到问题。
另一个问题是 pSrc 和 pDst 是否重叠。 根据您的编译器,strcat 很可能是一次检查 pSrc 中的 0 字符的简单循环。 如果 pDst 覆盖该 0,那么您将进入一个循环,该循环将一直运行直到程序崩溃。
There are two problems with strcat. First, you have to do all your validation outside the function, doing work that is almost the same as the function:
You have to walk down the entire length of both strings just to make sure it will fit, before walking down their entire length AGAIN to do the copy. Because of this, many programmers will simply assume that it will fit and skip the test. Even worse, it may be that when the code is first written it is GUARANTEED to fit, but when someone adds another strcat, or changes a buffer size or constant somewhere else in the program, you now have issues.
The other problem is if pSrc and pDst overlap. Depending on your compiler, strcat may very well be simple loop that checks a character at a time for a 0 in pSrc. If pDst overwrites that 0, then you will get into a loop that will run until your program crashes.