Tim*_*Tim 40
看看这个网站 ; 这是一个相当详细的解释.基本上,strncpy()
不需要NUL终止,因此容易受到各种攻击.
Dig*_*oss 12
最初的问题显然是strcpy(3)不是一个内存安全的操作,因此攻击者可以提供比缓冲区更长的字符串,这将覆盖堆栈上的代码,如果仔细安排,可以执行来自攻击者的任意代码.
但是strncpy(3)还有一个问题,就是它在目的地的每种情况下都不提供空终止.(想象一下源字符串比目标缓冲区更长.)当结果被复制到第三个缓冲区时,未来的操作可能期望在相同大小的缓冲区之间符合C nul终止的字符串并且下游出现故障.
使用strncpy(3)比strcpy(3)好,但strlcpy(3)之类的东西更好.
要安全地使用strncpy,必须(1)手动将空字符粘贴到结果缓冲区上,(2)知道缓冲区事先以null结尾,并将(length-1)传递给strncpy,或者(3)知道永远不会使用任何不将其长度限制为缓冲区长度的方法复制缓冲区.
重要的是要注意strncpy将填充缓冲区中的所有内容超过复制的字符串,而其他长度限制的strcpy变体则不会.在某些情况下,这可能会导致性能下降,但在其他情况下则具有安全优势.例如,如果使用strlcpy将"supercalifragilisticexpalidocious"复制到缓冲区然后复制"it",则缓冲区将保持"it ^ ercalifragilisticexpalidocious ^"(使用"^"表示零字节).如果缓冲区被复制到固定大小的格式,则额外数据可能会随之标记.
该问题基于“加载”前提,这使得问题本身无效。
这里的底线strncpy
是不被认为是不安全的,也从未被认为是不安全的。可以附加到该函数的唯一“不安全”声明是 C 内存模型和 C 语言本身的一般不安全性的广泛声明。(但这显然是一个完全不同的话题)。
在 C 语言领域内,对某种固有的“不安全”的错误信念strncpy
源自广泛存在的strncpy
用于“安全字符串复制”的可疑模式,即此函数不执行且从未打算执行的操作。这种用法确实很容易出错。但是即使你在“高度容易出错”和“不安全”之间加上一个等号,它仍然是一个使用问题(即缺乏教育问题)而不是strncpy
问题。
基本上,可以说唯一的问题strncpy
是不幸的命名,这让新手程序员认为他们了解这个函数的作用,而不是实际阅读规范。查看函数名称,一个不称职的程序员假定它strncpy
是 的“安全版本” strcpy
,而实际上这两个函数完全无关。
例如,可以对除法运算符提出完全相同的要求。正如你们大多数人所知,关于 C 语言最常见的问题之一是“我认为这1/2
会评估为,0.5
但我得到了0
。为什么?” 然而,我们不会仅仅因为语言初学者倾向于误解其行为而声称除法运算符是不安全的。
再举一个例子,我们不会把伪随机数生成器函数称为“不安全”,因为无能的程序员经常对他们的输出不是真正随机的事实感到不快。
这正是它的strncpy
功能。就像初学者程序员需要时间了解伪随机数生成器的实际作用一样,他们也需要时间来了解strncpy
实际的作用。需要花时间了解这strncpy
是一个转换函数,旨在将零终止字符串转换为固定宽度的字符串。需要时间来了解这strncpy
与“安全字符串复制”完全无关,并且不能有意义地用于该目的。
诚然,语言学生通常需要更长的时间来学习目的,而strncpy
不是使用除法运算符来解决问题。但是,这是针对strncpy
.
PS 在接受的答案中链接的 CERT 文件正是致力于:证明典型的无能滥用strncpy
功能的不安全性作为strcpy
. 它绝不是要声称strncpy
自己在某种程度上是不安全的。