简体   繁体   English

strcat vs strncat - 什么时候应该使用哪个函数?

[英]strcat Vs strncat - When should which function be used?

Some static code analyzer tools are suggesting that all strcat usage should be replaced with strncat for safety purpose? 一些静态代码分析器工具建议为了安全起见,所有strcat用法应该替换为strncat?

In a program, if we know clearly the size of the target buffer and source buffers, is it still recommended to go for strncat? 在程序中,如果我们清楚地知道目标缓冲区和源缓冲区的大小,是否仍然建议使用strncat?

Also, given the suggestions by static tools, should strcat be used ever? 另外,根据静态工具的建议,是否应该使用strcat?

Concatenate two strings into a single string. 将两个字符串连接成一个字符串。

Prototypes 原型

#include <string.h>

char * strcat(char *restrict s1, const char *restrict s2);

char * strncat(char *restrict s1, const char *restrict s2, size_t n);

DESCRIPTION 描述

The strcat() and strncat() functions append a copy of the null-terminated string s2 to the end of the null-terminated string s1, then add a terminating \\0'. strcat()strncat()函数strncat() null结尾的字符串s2的副本附加到以null结尾的字符串s1的末尾,然后添加一个终止的\\ 0'。 The string s1 must have sufficient space to hold the result. 字符串s1必须有足够的空间来保存结果。

The strncat() function appends not more than n characters from s2, and then adds a terminating \\0'. strncat()函数从s2追加不超过n个字符,然后添加一个终止\\ 0'。

The source and destination strings should not overlap, as the behavior is undefined. 源字符串和目标字符串不应重叠,因为行为未定义。

RETURN VALUES 返回值

 The `strcat()` and `strncat()` functions return the pointer s1.

SECURITY CONSIDERATIONS 安全考虑

The strcat() function is easily misused in a manner which enables malicious users to arbitrarily change a running program's functionality through a buffer overflow attack. strcat()函数很容易被滥用,使恶意用户能够通过缓冲区溢出攻击任意改变正在运行的程序的功能。

Avoid using strcat() . 避免使用strcat() Instead, use strncat() or strlcat() and ensure that no more characters are copied to the destination buffer than it can hold. 相反,使用strncat()strlcat()并确保不再将任何字符复制到目标缓冲区而不是它可以容纳。

Note that strncat() can also be problematic. 请注意, strncat()也可能存在问题。 It may be a security concern for a string to be truncated at all. 根本要截断字符串可能是一个安全问题。 Since the truncated string will not be as long as the original, it may refer to a completely different resource and usage of the truncated resource could result in very incorrect behavior. 由于截断的字符串不会与原始字符串一样长,因此它可能指的是完全不同的资源,截断资源的使用可能导致非常不正确的行为。 Example: 例:

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
 }

Example

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"

If you are absolutely sure about source buffer's size and that the source buffer contains a NULL-character terminating the string, then you can safely use strcat when the destination buffer is large enough. 如果您完全确定源缓冲区的大小并且源缓冲区包含终止字符串的NULL字符,那么当目标缓冲区足够大时,您可以安全地使用strcat。

I still recommend using strncat and give it the size of the destination buffer - length of the destination string - 1 我仍然建议使用strncat并给它目标缓冲区大小 - 目标字符串的长度 - 1

Note: I edited this since comments noted that my previous answer was horribly wrong. 注意:我编辑了这个,因为评论指出我之前的回答是非常错误的。

They don't do the same thing so they can't be substituted for one another. 他们不做同样的事情,所以他们不能互相替代。 Both have different data models. 两者都有不同的数据模型。

  • A string for strcat is a null terminated string for which you (as the programmer) guarantee that it has enough space. strcat的字符串是一个以空字符结尾的字符串,您(作为程序员)保证它有足够的空间。
  • A string for strncat is a sequence of char that is either terminated at the length you are indicating or by a null termination if it is supposed to be shorter than that length. strncat的字符串是一个char序列,它以您指示的长度终止, 或者如果它应该短于该长度则由null终止终止。

So the use of these functions just depends on the assumptions that you may (or want to) do about your data. 因此,这些函数的使用仅取决于您可能(或想要)对数据做出的假设。

Static tools are generally poor at understanding the circumstances around the use of a function. 静态工具通常很难理解使用函数的情况。 I bet most of them just warn for every strcat encountered instead of actually looking whether the data passed to the function is deterministic or not. 我打赌他们中的大多数只是警告每个遇到的strcat而不是实际查看传递给函数的数据是否是确定性的。 As already mentioned, if you have control over your input data neither function is unsafe. 如前所述,如果您可以控制输入数据,则功能都不安全。

Though note that strncat() is slightly slower, as it has to check against '\\0' termination and a counter, and also explicitly add it to the end. 虽然注意strncat()稍慢,因为它必须检查'\\ 0'终止和计数器,并且还明确地将它添加到结尾。 strcat() on the other hand just checks for '\\0', and it adds the trailing '\\0' to the new string by copying the terminator from the second string along with all the data. 另一方面,strcat()只检查'\\ 0',并通过从第二个字符串复制终结符以及所有数据,将尾部'\\ 0'添加到新字符串。

It's very simple strcat is used to concatenate two strings , for example 例如,strcat用于连接两个字符串非常简单

String a= data 
String b = structures 

If use perform strcat 如果使用执行strcat

Strcat(a, b) 

then 然后

a= data structures

But if you want to concatenate specific numer of word r elements then you can use strncat Example if you want to concatenate only the first two alphabet lts of b into a then you have to write Strncat(a,b,2) (It means that you just cancatenate the fist two alphabets of b into a , and a becomes a = data st 但是如果你想连接单词r元素的特定数字,那么你可以使用strncat示例如果你想只连接b的前两个字母lts然后你必须编写Strncat(a,b,2)(这意味着你只需将b的两个字母组合成a,然后变成a = data st

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM