一些静态代码分析器工具建议为了安全起见,所有strcat用法应该替换为strncat?
在程序中,如果我们清楚地知道目标缓冲区和源缓冲区的大小,是否仍然建议使用strncat?
另外,根据静态工具的建议,是否应该使用strcat?
Pan*_*mar 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);
Run Code Online (Sandbox Code Playgroud)
描述
的strcat()
和strncat()
功能追加空终止字符串的副本S2至空终止字符串S1的结尾,然后添加终止\ 0' .字符串s1必须有足够的空间来保存结果.
strncat()函数从s2追加不超过n个字符,然后添加一个终止\ 0'.
源字符串和目标字符串不应重叠,因为行为未定义.
返回值
The `strcat()` and `strncat()` functions return the pointer s1.
Run Code Online (Sandbox Code Playgroud)
安全考虑
该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
}
Run Code Online (Sandbox Code Playgroud)
例
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"
Run Code Online (Sandbox Code Playgroud)
Juh*_*uho 11
如果您完全确定源缓冲区的大小并且源缓冲区包含终止字符串的NULL字符,那么当目标缓冲区足够大时,您可以安全地使用strcat.
我仍然建议使用strncat并给它目标缓冲区的大小 - 目标字符串的长度 - 1
注意:我编辑了这个,因为评论指出我之前的回答是非常错误的.