sprintf(缓冲区,“%s ”,缓冲区,)是否安全?

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

sprintf(buffer, "%s \r\n", buffer, id); sprintf(buffer, "%s", buffer); 

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

除了缓冲区溢出的明显可能性之外 ,我相信无法保证缓冲区在函数的开始和结束之间不会发生变化(即,无法保证缓冲区的状态在执行function)。 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, " \r\n", id); 

替换这个。

从glibc sprintf()文档 :

如果在重叠的对象之间进行复制,则此函数的行为是未定义的 – 例如,如果s也作为参数给出,则在’%s’转换的控制下打印。

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

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

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

在这个特定的情况下,它会起作用,因为buffer的字符串将是第一个进入buffer (再次,无用),所以你应该使用strcat()来获得[几乎]相同的效果。

但是,如果您尝试将strcat()sprintf()的格式化可能性结合起来,您可以尝试这样做:

 sprintf(&buffer[strlen(buffer)], " \r\n", id); 

如果要使用printf()将格式化文本连接到缓冲区的末尾,我建议您使用整数来跟踪结束位置。

 int i = strlen(buffer); i += sprintf(&buffer[i], " \r\n", id); i += sprintf(&buffer[i], ""); 

要么:

 int i = strlen(buffer); i += sprintf(&buffer[i], " \r\n", id); strcat(&buffer[i], ""); 

在人们狂奔之前(“这不安全!你可以超越缓冲区!”),我只是在寻找一种合理的方式在C / C ++中构建一个格式化的字符串。