admin 管理员组文章数量: 887021
c语言字符串缺少终止符,c
c-为什么strncpy不为null终止?
strncpy()应该可以防止缓冲区溢出。 但是,如果它可以防止溢出而不终止为null,则很可能随后的字符串操作都会溢出。 因此,为了防止这种情况,我发现自己正在做:
strncpy( dest, src, LEN );
dest[LEN - 1] = '\0';
strncpy()提供:
strncpy()函数与之类似,只是复制的src字节数不超过n个。 因此,如果src的前n个字节中没有空字节,则结果将不会以空值结尾。
在没有null终止的情况下,看起来像是无辜的事情如下:
printf( "FOO: %s\n", dest );
...可能会崩溃。
是否有strncpy()更好,更安全的替代品?
Timothy Pratley asked 2019-09-28T03:04:45Z
11个解决方案
41 votes
strncat不能用作更安全的strncpy,应该用于将一个字符串插入另一个字符串的中间。
所有这些“安全”字符串处理功能(例如strncat和strncpy)都是已在以后的标准中添加的修补程序,以减轻缓冲区溢出漏洞等。
Wikipedia提到strncat作为编写自己的安全strncpy的替代方法:
*dst = '\0'; strncat(dst, src, LEN);
编辑
我错过了strncat在以空字符终止时,如果字符串长于或等于LEN char,则超过LEN个字符。
无论如何,使用strncat代替任何本地解决方案(例如memcpy(...,strlen(...))/)的意义在于,strncat的实现可能是库中目标/平台优化的。
当然,您需要检查dst是否至少包含nullchar,因此正确使用strncat的方法如下:
if(LEN) { *dst = '\0'; strncat(dst, src, LEN-1); }
我也承认strncpy对于将子字符串复制到另一个字符串不是很有用,如果src比n char短,则目标字符串将被截断。
Ernelli answered 2019-09-28T03:05:42Z
23 votes
已经有像strlcpy这样的开源实现可以进行安全复制。
[]
在参考文献中有到资源的链接。
StampedeXV answered 2019-09-28T03:06:21Z
23 votes
最初,第7版UNIX文件系统(请参见DIR(5))具有目录条目,该目录条目将文件名限制为14个字节。 目录中的每个条目都由2个字节的inode编号和14个字节的名称组成,将null填充为14个字符,但不一定以null结尾。 我相信strncpy()是为与这些目录结构一起使用而设计的,或者至少可以完美地用于该目录结构。
考虑:
14个字符的文件名不能为空终止。
如果名称少于14个字节,则将其空填充为全长(14个字节)。
这正是通过以下方式实现的:
strncpy(inode->d_name, filename, 14);
因此,strncpy()非常适合其原始利基应用。 巧合的是,防止以null终止的字符串溢出。
(请注意,将空值填充到长度14并不是一个严重的开销-如果缓冲区的长度为4 KB,而您想要的只是安全地将20个字符复制到其中,那么额外的4075个空值将是严重的矫kill过正,并且很容易 如果您将材料反复添加到较长的缓冲区中,则会导致二次行为。)
Jonathan Leffler answered 2019-09-28T03:07:23Z
8 votes
ISO / IEC TR 24731中指定了一些新的替代方法(有关信息,请检查[.html])。 这些函数中的大多数都带有一个附加参数,该参数指定目标变量的最大长度,确保所有字符串都以null终止,并以strcpy_s()656结尾(以“ safe”表示),以区别于它们之前的“ unsafe”名称。versions.1
不幸的是,他们仍在获得支持,可能不适用于您的特定工具集。 如果您使用旧的不安全功能,则更高版本的Visual Studio将引发警告。
如果您的工具不支持新功能,则为旧功能创建自己的包装器应该很容易。 这是一个例子:
errCode_t strncpy_safe(char *sDst, size_t lenDst,
const char *sSrc, size_t count)
{
// No NULLs allowed.
if (sDst == NULL || sSrc == NULL)
return ERR_INVALID_ARGUMENT;
// Validate buffer space.
if (count >= lenDst)
return ERR_BUFFER_OVERFLOW;
// Copy and always null-terminate
memcpy(sDst, sSrc, count);
*(sDst + count) = '\0';
return OK;
}
您可以更改功能以满足自己的需要,例如,始终复制尽可能多的字符串而不会溢出。 实际上,如果将strcpy_s()传递为count,则VC ++实现可以做到这一点。
1当然,您仍然需要准确了解目标缓冲区的大小:如果您提供3个字符的缓冲区,但告诉strcpy_s()它有25个字符的空间,您仍然会遇到麻烦。
Adam Liss answered 2019-09-28T03:08:17Z
7 votes
Strncpy可以更安全地防止程序用户的堆栈溢出攻击,它不能保护您免受程序员所犯的错误的影响,例如按照您所描述的方式打印非空终止的字符串。
您可以通过限制printf打印的字符数来避免由于描述的问题而崩溃:
char my_string[10];
//other code here
printf("%.9s",my_string); //limit the number of chars to be printed to 9
Liran Orevi answered 2019-09-28T03:08:51Z
5 votes
使用strlcpy()(在此处指定):[.html]
如果您的libc没有实现,请尝试以下一种:
size_t strlcpy(char* dst, const char* src, size_t bufsize)
{
size_t srclen =strlen(src);
size_t result =srclen; /* Result is always the length of the src string */
if(bufsize>0)
{
if(srclen>=bufsize)
srclen=bufsize-1;
if(srclen>0)
memcpy(dst,src,srclen);
dst[srclen]='\0';
}
return result;
}
(我于2004年撰写-致力于公共领域。)
alex tingle answered 2019-09-28T03:09:31Z
3 votes
strncpy直接与可用的字符串缓冲区一起使用,如果您直接与内存一起使用,则现在必须缓冲区大小,并且可以手动设置'\ 0'。
我相信普通C语言中没有更好的替代方法,但是如果您在处理原始内存时要格外小心,它的确不是那么糟糕。
Arkaitz Jimenez answered 2019-09-28T03:10:06Z
3 votes
您可以使用size-1代替size-1
snprintf(buffer, BUFFER_SIZE, "%s", src);
这是一个单行代码,最多将2545145963619025925920个非空字符从src复制到dest,并添加一个空终止符:
static inline void cpystr(char *dest, const char *src, size_t size)
{ if(size) while((*dest++ = --size ? *src++ : 0)); }
Christoph answered 2019-09-28T03:10:41Z
3 votes
我一直喜欢:
memset(dest, 0, LEN);
strncpy(dest, src, LEN - 1);
进行后续修复,但这实际上只是一个优先事项。
stonemetal answered 2019-09-28T03:11:19Z
2 votes
这些功能的发展远不止是设计,因此确实没有“为什么”。您只需要学习“如何”。 不幸的是,Linux手册页至少是缺少这些功能的常见用例示例,我注意到很多我审查过的代码中的滥用问题。 我在这里做了一些笔记:[.html]
pixelbeat answered 2019-09-28T03:11:49Z
2 votes
在不依赖更新的扩展的情况下,我过去做过这样的事情:
/* copy N "visible" chars, adding a null in the position just beyond them */
#define MSTRNCPY( dst, src, len) ( strncpy( (dst), (src), (len)), (dst)[ (len) ] = '\0')
甚至:
/* pull up to size - 1 "visible" characters into a fixed size buffer of known size */
#define MFBCPY( dst, src) MSTRNCPY( (dst), (src), sizeof( dst) - 1)
为什么用宏而不是较新的“内置”(?)函数? 因为过去有很多不同的unice,以及其他每天在执行C语言时必须移植回的非unix(非Windows)环境。
Roboprog answered 2019-09-28T03:12:30Z
本文标签: c语言字符串缺少终止符 c
版权声明:本文标题:c语言字符串缺少终止符,c 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.freenas.com.cn/jishu/1730799462h1384892.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论