最近在stackoverflow(为什么有人会使用strncpy而不是strcpy?)上有一个问题,其中有回答(回答1,回答2),让我对其他带有“n”的字符串函数感到不确定,例如snprintf
(我一直在广泛使用)。 snprintf是否安全?总的来说,“n”系列中的哪些函数是安全的?
最近在stackoverflow(为什么有人会使用strncpy而不是strcpy?)上有一个问题,其中有回答(回答1,回答2),让我对其他带有“n”的字符串函数感到不确定,例如snprintf
(我一直在广泛使用)。 snprintf是否安全?总的来说,“n”系列中的哪些函数是安全的?
strncpy()
是一个奇怪的函数,它的命名不太准确 - 它的原始目的是确保一个缓冲区完全被初始化为一个字符串的内容(而不会溢出目标),并将缓冲区的其余部分用零填充。据我所知,最初的目的是处理文件系统目录条目 - 目标缓冲区在某种意义上并不像C库中的其他strxxx()
函数一样是一个字符串。 strncpy()
的主要问题是,如果源字符串大于目标缓冲区,则结果将不会以空字符结尾。
大多数其他处理字符串的“n”函数都会正确终止字符串,但也有例外,例如微软的扭曲版本_snprintf()
。正确的C99snprintf()
会始终将目标字符串以空字符结尾(只要目标缓冲区的大小大于0)。
有一个名为TR 24731的技术报告,提出了一组边界检查替代方案,用于处理字符串和内存缓冲区的函数。 TR的目标之一是使函数的参数、结果和错误行为在函数之间更加相似。 TR似乎具有一定的接受度,但我认为它除了Microsoft的编译器之外并没有得到广泛实现(我认为微软是TR的主要推动者)。您可以在此处获取更多信息:
即使您不是这些提议的粉丝,我认为它们对于了解现有函数存在的问题非常有教育意义。
snprintf
虽然不会在给出正确参数的情况下溢出缓冲区,但请记住它与*printf
家族的其他成员共享所有格式字符串漏洞。例如,%n
说明符很危险,因为攻击者可以使用它将任意字节写入任意内存位置。请参见CERT C编码标准维基上的FIO30-C. Exclude user input from format strings。
snprintf确保缓冲区不会被覆盖,但它并不保证以null结尾。如果您愿意使用非标准的方法,可以在MSVC上使用sprintf_s。
请参见http://msdn.microsoft.com/en-us/library/2ts7cx93(VS.71).aspx
snprintf
确保在缓冲区末尾写入\0
,并且不会发生缓冲区溢出。当然,这取决于您传递的大小参数,但您可以对snprintf_s
执行完全相同的操作,并且由于相同的原因而失败。 - undefined注意:不同的平台在传递给 snprintf
的字符串的空终止行为方面有不同的行为。
snprintf
函数保证以空字符结尾。 - Pavel Minaev