OWASP说:
"诸如strcpy(),strcat(),sprintf()和vsprintf()之类的C库函数对空终止字符串进行操作,并且不执行边界检查."
sprintf将格式化数据写入字符串int sprintf(char*str,const char*format,...);
例:
sprintf(str, "%s", message); // assume declaration and
// initialization of variables
Run Code Online (Sandbox Code Playgroud)
如果我理解OWASP的评论,那么使用sprintf的危险就是那样
1)如果消息的长度> str的长度,则存在缓冲区溢出
和
2)如果消息没有以null结尾\0,则消息可能被复制到超出消息内存地址的str,导致缓冲区溢出
请确认/否认.谢谢
str*_*ger 24
你在这两个问题上都是正确的,尽管它们实际上都是同一个问题(访问超出数组边界的数据).
第一个问题的解决方案是使用std::snprintf,它接受缓冲区大小作为参数.
第二个问题的解决方案是给出一个最大长度参数snprintf.例如:
char buffer[128];
std::snprintf(buffer, sizeof(buffer), "This is a %.4s\n", "testGARBAGE DATA");
// std::strcmp(buffer, "This is a test\n") == 0
Run Code Online (Sandbox Code Playgroud)
如果要存储整个字符串(例如,在案例sizeof(buffer)中太小),请运行snprintf两次:
int length = std::snprintf(nullptr, 0, "This is a %.4s\n", "testGARBAGE DATA");
++length; // +1 for null terminator
char *buffer = new char[length];
std::snprintf(buffer, length, "This is a %.4s\n", "testGARBAGE DATA");
Run Code Online (Sandbox Code Playgroud)
(您可以将其放入使用的函数中va.)
Joh*_*ing 10
你的两个断言都是正确的.
还有一个未提及的问题.没有类型检查参数.如果格式字符串和参数不匹配,可能会导致未定义和不良行为.例如:
char buf[1024] = {0};
float f = 42.0f;
sprintf(buf, "%s", f); // `f` isn't a string. the sun may explode here
Run Code Online (Sandbox Code Playgroud)
这对于调试来说尤其令人讨厌.
所有这些导致许多C++开发人员得出结论,你永远不应该使用sprintf它和它的兄弟.实际上,您可以使用一些设施来避免上述所有问题.一,流,内置于语言:
#include <sstream>
#include <string>
// ...
float f = 42.0f;
stringstream ss;
ss << f;
string s = ss.str();
Run Code Online (Sandbox Code Playgroud)
...对于像我这样仍然喜欢使用的人来说,另一个受欢迎的选择sprintf来自boost格式库:
#include <string>
#include <boost\format.hpp>
// ...
float f = 42.0f;
string s = (boost::format("%1%") %f).str();
Run Code Online (Sandbox Code Playgroud)
你应该采用"从不使用sprintf"的咒语吗?自行决定.通常有一个最好的工具,取决于你正在做什么,sprintf也许就是这样.