C++ 为什么strncpy不安全?

C++ 为什么strncpy不安全?,c++,c,string,strncpy,C++,C,String,Strncpy,我想知道为什么strncpy被认为是不安全的。有人有关于这方面的文档或使用它的漏洞利用的例子吗?看看;这是一个相当详细的解释。基本上,strncpy()不需要NUL终止,因此容易受到各种攻击。要安全地使用strncpy,必须(1)手动将空字符粘贴到结果缓冲区,(2)事先知道缓冲区以空结束,并将(长度-1)传递给strncpy,或者(3)要知道,永远不会使用任何不会将缓冲区长度绑定到缓冲区长度的方法来复制缓冲区 需要注意的是,strncpy将零填充缓冲区中经过复制字符串的所有内容,而其他长度受限的

我想知道为什么strncpy被认为是不安全的。有人有关于这方面的文档或使用它的漏洞利用的例子吗?

看看;这是一个相当详细的解释。基本上,
strncpy()
不需要NUL终止,因此容易受到各种攻击。

要安全地使用strncpy,必须(1)手动将空字符粘贴到结果缓冲区,(2)事先知道缓冲区以空结束,并将(长度-1)传递给strncpy,或者(3)要知道,永远不会使用任何不会将缓冲区长度绑定到缓冲区长度的方法来复制缓冲区


需要注意的是,strncpy将零填充缓冲区中经过复制字符串的所有内容,而其他长度受限的strcpy变体则不会。这在某些情况下可能会导致性能下降,但在其他情况下可能会带来安全优势。例如,如果使用strlcpy将“supercalifragilisticexpalidocious”复制到缓冲区中,然后复制“it”,则缓冲区将保存“it^ercalisticsexpalidocious^”(使用“^”表示零字节)。如果将缓冲区复制为固定大小的格式,则额外的数据可能会随之标记。

原始问题显然不是,因此攻击者可以提供比缓冲区长的字符串,从而覆盖堆栈上的代码,如果仔细安排,攻击者可以执行任意代码

但是还有另一个问题,它不能在目的地的任何情况下都提供空终止。(想象一个源字符串比目标缓冲区长。)未来的操作可能会期望在大小相同的缓冲区之间有一致的C nul终止字符串,并且当结果复制到第三个缓冲区时,下游会出现故障


使用strncpy(3)比strcpy(3)好,但是strlcpy(3)这样的东西更好。

这个问题基于一个“加载”的前提,这使得问题本身无效

这里的底线是,
strncpy
不被认为是不安全的,也从来没有被认为是不安全的。唯一可以附加到该函数的“不安全性”声明是C内存模型和C语言本身的一般不安全性的广泛声明。(但这显然是一个完全不同的话题)

在C语言领域内,
strncpy
中固有的某种“不安全”的错误信念源于广泛存在的使用
strncpy
进行“安全字符串复制”的可疑模式,也就是说,这个函数不做,也从来没有打算做的事情。这种用法确实非常容易出错。但即使在“高度易出错”和“不安全”之间加上等号,这仍然是一个使用问题(即缺乏教育问题),而不是一个
strncpy
问题

基本上,我们可以说strncpy的唯一问题是一个不幸的命名,这使得新手程序员假定他们理解这个函数的作用,而不是实际阅读规范。看着函数名,一个不称职的程序员认为
strncpy
strcpy
的“安全版本”,而实际上这两个函数是完全不相关的

例如,可以对除法操作员提出完全相同的索赔。正如大多数人所知,关于C语言最常见的问题之一是“我假设
1/2
的计算结果为
0.5
,但我得到了
0
。为什么?”然而,我们并不是说除法运算符不安全,仅仅因为语言初学者往往会误解它的行为

再举一个例子,我们不把伪随机数生成器函数称为“不安全”函数,仅仅是因为不称职的程序员经常对其输出不是真正随机的事实感到不愉快的惊讶

这正是使用
strncpy
函数时的情况。就像初学者需要时间来学习伪随机数生成器的实际功能一样,他们也需要时间来学习strncpy的实际功能。了解
strncpy
是一个转换函数需要时间,用于将以零结尾的字符串转换为固定宽度的字符串。需要时间来了解
strncpy
与“安全字符串复制”完全无关,不能有意义地用于此目的

诚然,学习语言的学生学习strncpy的目的通常比用除法运算符进行排序要长得多。然而,这是针对
strncpy
的任何“不安全”索赔的基础

注:公认答案中链接的CERT文件正是为了证明典型的不合格滥用
strncpy
功能作为
strcpy
的“安全”版本的不安全性。这并不是说strncpy本身是不安全的。

Git 2.19(2018年第3季度)的pathc发现它太容易滥用系统API函数,例如
strcat()
<代码>strncpy()。。。并禁止在此代码库中使用这些函数

参见(2018年7月24日)和(2018年7月26日)作者。
(于2018年8月15日合并)

banked.h
:将
strcat()标记为禁止
strcat()
函数具有与
strcpy()相同的溢出问题
作为奖励,很容易意外地结束二次调用,因为每个后续调用都必须遍历现有字符串

最后一个
strcat()
调用在(守护进程:use)中消失 cld->env_阵列重新繁殖时,2015-09-24,Git 2.7.0)。
通常,
strcat()
可以用动态字符串替换 (
strbuf
xstrfmt
),或使用
xsnprintf
,如果您知道长度有界


据我所知,strcpy是不安全的,而且