最近有一个关于 SO 的问题(为什么会有人使用 strncpy 而不是 strcpy?),答案是(答案 1,答案 2),这让我不确定其他名称中带有 'n' 的字符串函数,比如snprintf
(我一直在广泛使用)。snprintf 使用安全吗?通常,“n”系列的安全功能是什么?
5 回答
strncpy()
是一个真正命名错误的古怪函数 - 其最初目的是确保使用字符串的内容完全初始化缓冲区(不会溢出目标)并用零提醒缓冲区。据我了解,最初的目的是处理文件系统目录条目——目标缓冲区实际上并不是一个strxxx()
与 C 库中其他函数相同意义上的字符串。主要问题strncpy()
是如果源字符串大于目标缓冲区,则结果不会以空值结尾。
大多数其他处理字符串的 'n' 函数确实可以正确终止字符串,但也有例外,例如 Microsoft 的 bastardized _snprintf()
. 正确的 C99snprintf()
将始终以空值终止目标字符串(只要目标缓冲区的大小大于 0)。
有一个“技术报告”,TR 24731,它为处理字符串和内存缓冲区的函数提出了一组边界检查替代方案。TR 的目标之一是使函数的参数、结果和错误行为在函数之间更加相似。TR 似乎接受程度参差不齐,我认为除了 Microsoft 的编译器(我认为 MS 是 TR 背后的主要驱动程序)之外,它没有被广泛实施。你可以在这里获得更多信息:
即使您不喜欢这些建议,我认为它们也有助于阅读有关现有功能问题的教育性阅读。
如果snprintf
你给它正确的参数,它不会溢出缓冲区,但请记住,它与其他*printf
家庭成员共享所有格式字符串漏洞。例如,说明%n
符很讨厌,因为攻击者可以使用它来将任意字节写入任意内存位置。见FIO30-C。从 CERT C 编码标准 wiki 的格式字符串中排除用户输入。
只要您为缓冲区提供正确的长度,它就是安全的。
snprintf 确实保证缓冲区不会被覆盖,但不保证空终止。sprintf_s
如果您愿意非标准,您可以在 MSVC 上使用。
请参阅http://msdn.microsoft.com/en-us/library/2ts7cx93(VS.71).aspx
注意:不同的平台对于传递给的字符串的空终止有不同的行为snprintf
。