据我所知,strlcpy
和strlcat
被设计为strncpy
和strncat
的安全替代品。然而,有些人仍然认为他们是insecure, and simply cause a different type of problem。
谁能举个例子,说明使用strlcpy
或strlcat
(例如,一个总是以null结尾的函数)会如何导致安全问题?
Ulrich Drepper和James Antill声明这是真的,但从来没有提供例子或澄清这一点。
发布于 2010-01-22 12:43:36
首先,strlcpy
从未被设计为strncpy
的安全版本( strncpy
也从未被设计为strcpy
的安全版本)。这两个功能是完全不相关的。strncpy
是一个与C字符串(即以null结尾的字符串)没有任何关系的函数。它的名字中有str...
前缀的事实只是一个历史错误。strncpy
的历史和目的是众所周知的,并且有很好的文档记录。这是为处理Unix文件系统的一些历史版本中使用的所谓“固定宽度”字符串(而不是C字符串)而创建的函数。今天,一些程序员被它的名字搞糊涂了,他们认为strncpy
以某种方式被认为是有限长度的C字符串复制函数(strcpy
的“安全”兄弟),实际上这完全是胡说八道,并导致糟糕的编程实践。当前形式的C标准库没有任何用于有限长度C字符串复制的函数。这正是strlcpy
的用武之地。strlcpy
确实是一个真正的有限长度复制函数,它是为处理C字符串而创建的。strlcpy
正确地完成了有限长度复制函数应该执行的所有操作。唯一可以针对它的批评是,很遗憾,它不是标准的。
其次,另一方面,strncat
确实是一个使用C字符串并执行有限长度连接的函数(它确实是strcat
的“安全”兄弟)。为了正确地使用这个函数,程序员必须特别小心,因为这个函数接受的size参数实际上不是接收结果的缓冲区的大小,而是其剩余部分的大小(另外,终止字符也是隐式计算的)。这可能会令人困惑,因为为了将该大小与缓冲区的大小绑定在一起,程序员必须记得执行一些额外的计算,这些计算通常用于批评strncat
。strlcat
解决了这些问题,更改了接口,这样就不需要额外的计算(至少在调用代码中是这样)。同样,我看到的唯一可以批评这一点的基础是该函数不是标准的。此外,由于基于重新扫描的字符串连接概念的可用性有限,因此在专业代码中不会经常看到来自strcat
组的函数。
至于这些函数如何导致安全问题...它们根本不能。它们不会导致比C语言本身“导致安全问题”更大程度的安全问题。你看,在相当长的一段时间里,有一种强烈的观点认为,Java语言必须朝着某种奇怪的C++风格发展。这种情绪有时也会蔓延到C语言领域,导致对C语言特性和C标准库特性的相当愚蠢和强迫的批评。我怀疑,在这种情况下,我们可能也会处理类似的事情,尽管我当然希望事情不会真的那么糟糕。
发布于 2010-01-22 12:54:31
Ulrich的批评是基于这样一种想法,即程序没有检测到的字符串截断可能会通过不正确的逻辑导致安全问题。因此,为了安全起见,您需要检查截断。要对字符串连接执行此操作,意味着您将按照以下方式进行检查:
if (destlen + sourcelen > dest_maxlen)
{
/* Bug out */
}
现在,如果程序员记得检查结果,那么strlcat
确实可以有效地执行此检查-因此您可以安全地使用它:
if (strlcat(dest, source, dest_bufferlen) >= dest_bufferlen)
{
/* Bug out */
}
乌尔里希的观点是,既然你必须使用destlen
和sourcelen
(或者重新计算它们,这就是strlcat
有效地做的事情),你最好还是使用更高效的memcpy
:
if (destlen + sourcelen > dest_maxlen)
{
goto error_out;
}
memcpy(dest + destlen, source, sourcelen + 1);
destlen += sourcelen;
(在上面的代码中,dest_maxlen
是可以存储在dest
中的字符串的最大长度-比dest
缓冲区的大小小一。dest_bufferlen
是dest buffer
的完整大小)。
发布于 2010-01-22 13:50:52
我认为Ulrich和其他人认为这会给人一种虚假的安全感。意外截断字符串可能会对代码的其他部分产生安全隐患(例如,如果文件系统路径被截断,则程序可能不会对目标文件执行操作)。
https://stackoverflow.com/questions/2114896
复制相似问题