[英]strcat Vs strncat - When should which function be used?
一些靜態代碼分析器工具建議為了安全起見,所有strcat用法應該替換為strncat?
在程序中,如果我們清楚地知道目標緩沖區和源緩沖區的大小,是否仍然建議使用strncat?
另外,根據靜態工具的建議,是否應該使用strcat?
將兩個字符串連接成一個字符串。
原型
#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()
函數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"
如果您完全確定源緩沖區的大小並且源緩沖區包含終止字符串的NULL字符,那么當目標緩沖區足夠大時,您可以安全地使用strcat。
我仍然建議使用strncat並給它目標緩沖區的大小 - 目標字符串的長度 - 1
注意:我編輯了這個,因為評論指出我之前的回答是非常錯誤的。
他們不做同樣的事情,所以他們不能互相替代。 兩者都有不同的數據模型。
strcat
的字符串是一個以空字符結尾的字符串,您(作為程序員)保證它有足夠的空間。 strncat
的字符串是一個char
序列,它以您指示的長度終止, 或者如果它應該短於該長度則由null終止終止。 因此,這些函數的使用僅取決於您可能(或想要)對數據做出的假設。
靜態工具通常很難理解使用函數的情況。 我打賭他們中的大多數只是警告每個遇到的strcat而不是實際查看傳遞給函數的數據是否是確定性的。 如前所述,如果您可以控制輸入數據,則功能都不安全。
雖然注意strncat()稍慢,因為它必須檢查'\\ 0'終止和計數器,並且還明確地將它添加到結尾。 另一方面,strcat()只檢查'\\ 0',並通過從第二個字符串復制終結符以及所有數據,將尾部'\\ 0'添加到新字符串。
例如,strcat用於連接兩個字符串非常簡單
String a= data
String b = structures
如果使用執行strcat
Strcat(a, b)
然后
a= data structures
但是如果你想連接單詞r元素的特定數字,那么你可以使用strncat示例如果你想只連接b的前兩個字母lts然后你必須編寫Strncat(a,b,2)(這意味着你只需將b的兩個字母組合成a,然后變成a = data st
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.