gpt4 book ai didi

c++ - strncpy 复制超过指定大小

转载 作者:塔克拉玛干 更新时间:2023-11-03 08:03:13 29 4
gpt4 key购买 nike

我有以下模仿应用程序中代码的示例代码。

#include <iostream>
#include <string.h>
#include <cstring>
#include <atlstr.h>
using namespace std;

void test(char *s, int size)
{
//s = "";
int lens = strlen(s);
char *str1 = "(( State:0.000000 Std30c5 = State:T ) OR (( State:0.000000 Std30c6 = State:T ) OR (( State:0.000000 Std30c7 = State:T ) OR (( State:0.000000 Std30c8 = State:T ) OR (( State:0.000000 Std30c9 = State:T ) OR (( State:0.000000 Std30ca = State:T ) OR (( State:0.000000 Std30cb = State:T ) OR (( State:0.000000 Std30cc = State:T ) OR (( State:0.000000 Std30cd = State:T ) OR (( State:0.000000 Std30ce = State:T ) OR (( State:0.000000 Std30cf = State:T ) OR ( ...0.000000 = State:T ))))))))))))";
int len1 = strlen(str1);
strncpy(s, str1, 512);
int len = strlen(s);

}

int main()
{

char strDisplay[512] = "";
test(strDisplay, 512);


cout << strDisplay << endl;
system("pause");
return 0;
}

结果是:lenofstrtest = 523;lenofstr1 = 512;

strtest =“((状态:0.000000 Std30c5 =状态:T)或((状态:0.000000 Std30c6 =状态:T)或((状态:0.000000 Std30c7 =状态:T)或((状态:0.000000 Std30c8 =状态:T ) OR (( State:0.000000 Std30c9 = State:T ) OR (( State:0.000000 Std30ca = State:T ) OR (( State:0.000000 Std30cb = State:T ) OR (( State:0.000000 Std30cc = State:T ) 或 (( 州:0.000000 Std30cd = 州:T ) 或 (( 州:0.000000 Std30ce = 州:T ) 或 (( 州:0.000000 Std30cf = 州:T ) 或 ( ...0.000000 = 州:T ))) ))))))))ÌÌÌÌJ¢Š£øø)"

为什么 strncpy 复制额外的字符?

(这导致了一个问题,因为不正确的 strnlen 导致解包逻辑失控!)

我猜这与“strncpy 错误 512 字节”有关...请帮助我理解此错误。

最佳答案

strncpy 不会将终止字符“\0”添加到截断的字符串中,这会导致您遇到的问题。当字符串未正确终止时,它看起来更长,但您实际看到的是内存中缓冲区之后放置的数据。它可能会导致严重的问题。

您应该使用 strlcpy 而不是 strncpy,它会正确终止字符串并返回源字符串的长度,您可以将其与缓冲区的长度进行比较以了解字符串是否被截断。 strncpy 返回指向缓冲区指针的指针(这不是很有用,因为您已经知道它 - 您将它作为第一个参数传递)并且不会告诉您是否发生了任何截断。

参见 man strlcpy:

The strlcpy() and strlcat() functions copy and concatenate strings with the same input parameters and output result as snprintf(3). They are designed to be safer, more consistent, and less error prone replacements for the easily misused functions strncpy(3) and strncat(3). strlcpy() and strlcat() take the full size of the destination buffer and guarantee NUL-termination if there is room. Note that room for the NUL should be included in dstsize.

C string handling - Replacements在维基百科上:

The most popular[a] replacement are the strlcat and strlcpy functions, which appeared in OpenBSD 2.4 in December, 1998.[84] These functions always write one NUL to the destination buffer, truncating the result if necessary, and return the size of buffer that would be needed, which allows detection of the truncation and provides a size for creating a new buffer that will not truncate.

不幸的是,它不包含在 glibc 中 - 请参阅 Secure Portability纸达米安·米勒 (PDF):

The strlcpy and strlcat API properly check the target buffer’s bounds, nul-terminate in all cases and return the length of the source string, allowing detection of truncation. This API has been adopted by most modern operating systems and many standalone software packages, including OpenBSD (where it originated), Sun Solaris, FreeBSD, NetBSD, the Linux kernel, rsync and the GNOME project. The notable exception is the GNU standard C library, glibc [12], whose maintainer steadfastly refuses to include these improved APIs, labelling them “horribly inefficient BSD crap” [4], despite prior evidence that they are faster is most cases than the APIs they replace [13]. As a result, over 100 of the software packages present in the OpenBSD ports tree maintain their own strlcpy and/or strlcat replacements or equivalent APIs - not an ideal state of affairs.

它在 libbsd 库中可用于 Linux:

在 Debian 和 Ubuntu 以及其他发行版中有软件包:

即使您不想依赖 glibc 以外的任何东西,也可以很容易地将其添加到您的项目中,因为整个源代码很短,并且在许可下可用:

/*
* Copyright (c) 1998 Todd C. Miller <Todd.Miller@courtesan.com>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/

#include <sys/types.h>
#include <string.h>

/*
* Copy src to string dst of size siz. At most siz-1 characters
* will be copied. Always NUL terminates (unless siz == 0).
* Returns strlen(src); if retval >= siz, truncation occurred.
*/
size_t
strlcpy(char *dst, const char *src, size_t siz)
{
char *d = dst;
const char *s = src;
size_t n = siz;

/* Copy as many bytes as will fit */
if (n != 0) {
while (--n != 0) {
if ((*d++ = *s++) == '\0')
break;
}
}

/* Not enough room in dst, add NUL and traverse rest of src */
if (n == 0) {
if (siz != 0)
*d = '\0'; /* NUL-terminate dst */
while (*s++)
;
}

return(s - src - 1); /* count does not include NUL */
}

来源:http://cvsweb.openbsd.org/cgi-bin/cvsweb/src/lib/libc/string/strlcpy.c?rev=1.11

关于c++ - strncpy 复制超过指定大小,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27330913/

29 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com