是sprintf(缓冲区,"%s [...]",缓冲区,[...])安全吗?

Pau*_*her 20 c printf c-strings

我看到使用这个模式连接到我正在处理的一些代码中的字符串:

sprintf(buffer, "%s <input type='file' name='%s' />\r\n", buffer, id);
sprintf(buffer, "%s</td>", buffer);
Run Code Online (Sandbox Code Playgroud)

而且我很确定它不安全C.你会注意到buffer它既是输出又是第一个输入.

除了缓冲区溢出的明显可能性之外,我相信不能保证缓冲区在函数的开始和结束之间不会发生变化(即,无法保证缓冲区的状态在执行功能).sprintf的签名还指定了目标字符串restrict.

我还记得一篇关于memcpy中的推测性写作的报告,我认为没有理由为什么某个C库可能在sprintf中做同样的事情.当然,在这种情况下,它会写入其来源.因此,这种行为是安全的?

仅供参考,我建议:

char *bufEnd = buffer + strlen(buffer);
/* sprintf returns the number of f'd and print'd into the s */
bufEnd += sprintf(bufEnd, " <input type='file' name='%s' />\r\n", id);
Run Code Online (Sandbox Code Playgroud)

替换这个.

Kar*_*and 19

glibc sprintf()文档:

如果在重叠的对象之间进行复制,则此函数的行为是不确定的 - 例如,如果s也作为参数给出,则在'%s'转换的控制下打印.

在特定实现中可能是安全的; 但你不能指望它是便携式的.

我不确定你的建议在所有情况下都是安全的.你仍然可以重叠缓冲区.现在已经很晚了,而且我的妻子是我的错误,但我认为您仍然可以在连接字符串中再次使用原始字符串并覆盖空字符,因此sprintf实现可能不知道重用的位置字符串结束.

您可能只想将snprint()粘贴到临时缓冲区,然后将strncat()粘贴到原始缓冲区上.

  • 好吧,只是想进行健全性检查。[POSIX 说同样的事情](http://www.opengroup.org/onlinepubs/9699919799/functions/sprintf.html): &gt; 如果由于调用 sprintf() 或 snprintf 而重叠的对象之间发生复制(),结果未定义。 (2认同)

Hav*_*ard 5

在这种特定情况下,它会起作用,因为字符串 inbuffer将是要输入的第一件事buffer(再次,无用),因此您应该使用它strcat()来获得 [几乎] 相同的效果。

但是,如果您试图结合strcat()的形成可能性sprintf(),您可以尝试以下操作:

sprintf(&buffer[strlen(buffer)], " <input type='file' name='%s' />\r\n", id);
Run Code Online (Sandbox Code Playgroud)