C snprintf和朋友使用安全吗?

C snprintf和朋友使用安全吗?,c,buffer-overflow,printf,C,Buffer Overflow,Printf,最近有一个关于SO()的问题,hade回答了(,),这让我无法确定名称中有“n”的其他字符串函数,比如snprintf(我一直在广泛使用)。snprintf使用安全吗?一般来说,“n”系列的安全功能是什么?注意:不同的平台在传递给snprintf的字符串的空终止方面有不同的行为。snprintf确实保证缓冲区不会被覆盖,但不保证空终止。如果您愿意成为非标准的,您可以在MSVC上使用sprintf_s 请参见只要为缓冲区提供正确的长度,它是安全的。strncpy()是一个命名错误的奇怪函数-其最初

最近有一个关于SO()的问题,hade回答了(,),这让我无法确定名称中有“n”的其他字符串函数,比如
snprintf
(我一直在广泛使用)。snprintf使用安全吗?一般来说,“n”系列的安全功能是什么?

注意:不同的平台在传递给
snprintf
的字符串的空终止方面有不同的行为。snprintf确实保证缓冲区不会被覆盖,但不保证空终止。如果您愿意成为非标准的,您可以在MSVC上使用
sprintf_s


请参见

只要为缓冲区提供正确的长度,它是安全的。

strncpy()
是一个命名错误的奇怪函数-其最初目的是确保缓冲区完全初始化为字符串内容(不会溢出目标)并用零提示缓冲区。据我所知,最初的目的是处理文件系统目录项-目标缓冲区实际上不是一个字符串,与C库中的其他
strxxx()
函数的意义不同。
strncpy()
的主要问题是,如果源字符串大于目标缓冲区,结果将不会以null结尾

大多数其他处理字符串的“n”函数都会正确终止字符串,但也有例外,如Microsoft的bastardized
\u snprintf()
。正确的C99
snprintf()
将始终为空终止目标字符串(只要目标缓冲区的大小大于0)

有一份“技术报告”,TR 24731为处理字符串和内存缓冲区的函数提出了一组边界检查备选方案。TR的目标之一是使函数的参数、结果和错误行为在函数之间更加相似。TR的接受程度似乎有点参差不齐,我认为除了微软的编译器(我认为MS是TR背后的主要驱动因素)之外,它并没有得到广泛的实现。您可以在此处获得更多信息:


即使你不喜欢这些建议,我认为它们有助于对现有函数的问题进行教育性阅读。

snprintf
如果你给出正确的参数,它不会溢出缓冲区,请记住,它与
*printf
系列的其他成员共享所有格式字符串漏洞。例如,
%n
说明符令人讨厌,因为攻击者可以使用它将任意字节写入任意内存位置。请参阅CERT C编码标准维基。

snprintf
如ISO C99中所规定,保证为空终止。您能给出一个不符合此响应中标准C的平台示例吗?Microsoft的变体,\u snprintf(),如果缓冲区不够大,则不会终止目标:如果可以用一个函数的标准名称包装它,同时修复没有终止错误,那么为什么有人会担心名称开头带有下划线的非标准函数不符合要求?如果可以,我会投反对票。这是完全错误的。如果您选择使用非标准的、不同名称的_snprintf,那么它的行为可能会有所不同。然而,这不是提交者所要求的。看起来snprintf在Windows上不可用;但是,您可以自己编写,没有太多困难。实际上,snprintf根本不能保证缓冲区溢出。这取决于你提供的缓冲区大小,它可能是不正确的。不用说,没有CRT函数神奇地知道传入的缓冲区实际有多大。那么,不用说,没有CRT函数是“安全的”,人们假装在他们的名字后面加上“U”违反了这条规则,这没有多大意义;-)-1:您应该澄清,您所说的是损坏的Microsoft实现,而不是C标准。相关:请注意snprintf/swprintf/snwprintf/etc以及%ls和%s在不同平台上的不同行为。它们都是不同的,只是在不一致的、不完整的实现上。C标准非常清楚这些格式说明符应该做什么。您提供的长度(以及您是否手动null终止缓冲区的结尾)取决于您所处的平台。顺便说一句,MS实现是不一致的。