为了安全起见,一些静态代码分析工具建议所有strcat用法都应该替换为strncat?
在一个程序中,如果我们清楚地知道目标缓冲区和源缓冲区的大小,是否仍然建议使用strncat?
另外,根据静态工具的建议,是否应该使用strcat?
答案 0 :(得分:13)
将两个字符串连接成一个字符串。
<强> 原型 强>
#include <string.h>
char * strcat(char *restrict s1, const char *restrict s2);
char * strncat(char *restrict s1, const char *restrict s2, size_t n);
<强> 说明 强>
strcat()
和strncat()
函数附加一个以null结尾的副本
字符串s2到以null结尾的字符串s1的末尾,然后添加一个终止\ 0'。字符串s1必须有足够的空间来容纳
结果
strncat()函数从s2追加不超过n个字符,和 然后添加一个终止\ 0'。
源行为和目标字符串不应重叠,因为行为是 未定义。
返回值
The `strcat()` and `strncat()` functions return the pointer s1.
安全注意事项
strcat()
函数很容易被滥用,使恶意用户可以随意更改正在运行的程序的功能
通过缓冲区溢出攻击。
避免使用strcat()
。相反,请使用strncat()
或strlcat()
并确保
没有更多的字符被复制到目标缓冲区
持。
请注意,strncat()
也可能存在问题。根本要截断字符串可能是一个安全问题。由于截断的字符串
将不会与原始资源一样长,它可能指的是完全不同的资源,并且截断资源的使用可能导致非常
行为不正确。例如:
void
foo(const char *arbitrary_string)
{
char onstack[8] = "";
#if defined(BAD)
/*
* This first strcat is bad behavior. Do not use strcat!
*/
(void)strcat(onstack, arbitrary_string); /* BAD! */
#elif defined(BETTER)
/*
* The following two lines demonstrate better use of
* strncat().
*/
(void)strncat(onstack, arbitrary_string,
sizeof(onstack) - strlen(onstack) - 1);
#elif defined(BEST)
/*
* These lines are even more robust due to testing for
* truncation.
*/
if (strlen(arbitrary_string) + 1 >
sizeof(onstack) - strlen(onstack))
err(1, "onstack would be truncated");
(void)strncat(onstack, arbitrary_string,
sizeof(onstack) - strlen(onstack) - 1);
#endif
}
<强> 实施例 强>
char dest[20] = "Hello";
char *src = ", World!";
char numbers[] = "12345678";
printf("dest before strcat: \"%s\"\n", dest); // "Hello"
strcat(dest, src);
printf("dest after strcat: \"%s\"\n", dest); // "Hello, World!"
strncat(dest, numbers, 3); // strcat first 3 chars of numbers
printf("dest after strncat: \"%s\"\n", dest); // "Hello, World!123"
答案 1 :(得分:10)
如果您完全确定源缓冲区的大小并且源缓冲区包含终止字符串的NULL字符,那么当目标缓冲区足够大时,您可以安全地使用strcat。
我仍然建议使用strncat并为其指定目标缓冲区的大小 - 目标字符串的长度 - 1
注意:我对此进行了编辑,因为评论指出我之前的回答非常错误。
答案 2 :(得分:1)
他们没有做同样的事情,所以他们不能互相替代。两者都有不同的数据模型。
strcat
的字符串为空
已终止的字符串,您(作为程序员)保证它有足够的空间。strncat
的字符串是一个序列
char
的任何一个被终止
在您指示或的长度
如果是,则通过空终止
应该比那短
长度。因此,这些功能的使用仅取决于您可能(或想要)对您的数据做出的假设。
答案 3 :(得分:0)
静态工具通常很难理解使用函数的情况。我打赌他们中的大多数只是警告每个遇到的strcat而不是实际查看传递给函数的数据是否是确定性的。如前所述,如果您可以控制输入数据,则功能都不安全。
虽然注意strncat()稍慢,因为它必须检查'\ 0'终止和计数器,并且还明确地将它添加到结尾。另一方面,strcat()只检查'\ 0',并通过从第二个字符串复制终结符以及所有数据,将尾部'\ 0'添加到新字符串。
答案 4 :(得分:-1)
非常简单的strcat用于连接两个字符串,例如
String a= data
String b = structures
如果使用,请执行strcat
Strcat(a, b)
然后
a= data structures
但是,如果要连接单词r元素的特定数目,则可以使用strncat 例如,如果您只想将b的前两个字母lt连接到a中,则必须编写 Strncat(a,b,2) (这意味着您只需将拳头b的两个字母关联到a中,a就会变成 a =数据st