猿问
下载APP

为什么strncpy不为null终止?

为什么strncpy不为null终止?

strncpy()据说可以防止缓冲区溢出。但是如果它在没有null终止的情况下防止溢出,那么随后的字符串操作将会溢出。所以为了防止这种情况,我发现自己在做:

strncpy( dest, src, LEN );dest[LEN - 1] = '\0';

man strncpy 得到:

strncpy()函数类似,只是复制了不超过n个字节的src。因此,如果src的前n个字节中没有空字节,则结果将不会以空值终止。

没有null终止看似无辜的东西,如:

   printf( "FOO: %s\n", dest );

......可能会崩溃


是否有更好,更安全的替代品strncpy()


繁华开满天机
浏览 48回答 3
3回答

12345678_0001

strncpy不打算用作更安全的strcpy,它应该用于在另一个中间插入一个字符串。所有那些“安全”的字符串处理函数,例如snprintf并且vsnprintf是在以后的标准中添加的修复,以减轻缓冲区溢出漏洞等。维基百科提到strncat作为编写自己的安全的替代方法strncpy:*dst = '\0'; strncat(dst, src, LEN);编辑我错过了strncat超过LEN字符,当null终止字符串时,如果它长于或等于LEN char的话。无论如何,使用strncat而不是任何自行开发的解决方案,例如memcpy(...,strlen(...))/无论strncat的实现可能是库中的目标/平台优化。当然你需要检查dst是否至少保存了nullchar,所以正确使用strncat会是这样的:if(LEN) { *dst = '\0'; strncat(dst, src, LEN-1); }我还承认strncpy对于将子字符串复制到另一个字符串并不是很有用,如果src比n字符短,则目标字符串将被截断。

缥缈止盈

已经有像strlcpy这样的开源实现可以进行安全复制。http://en.wikipedia.org/wiki/Strlcpy在参考文献中有链接到源。

达令说

最初,第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个空值是严重的过度杀伤,并且可以很容易如果您反复向长缓冲区添加材料,则会导致二次行为。)
打开App,查看更多内容
随时随地看视频慕课网APP
我要回答