【发布时间】:2018-09-27 12:35:36
【问题描述】:
我正在编写需要格式化字符串的代码,并且我想避免缓冲区溢出。
我知道如果vsnprintf 可用(C99 及以上)我们可以这样做:
char* formatString(const char *format, ...)
{
char* result = NULL;
va_list ap;
va_start(ap, format);
/* Get the size of the formatted string by getting vsnprintf return the
* number of remaining characters if we ask it to write 0 characters */
int size = vsnprintf(NULL, 0, format, ap);
if (size > 0)
{
/* String formatted just fine */
result = (char *) calloc(size + 1, sizeof(char));
vsnprintf(result, size + 1, format, ap);
}
va_end(ap);
return result;
}
我想不出在 C90 中做类似事情的方法(没有vsnprintf)。如果不编写极其复杂的逻辑就无法实现,我很乐意为结果设置最大长度,但我不确定如何在不冒缓冲区溢出风险的情况下实现这一点。
【问题讨论】:
-
如果移植到较新的 C 版本不是一个选项,我会为
vsnprintf寻找开源替代品。更简单的vsprintf实在是太破了,无法使用。 -
vsnprintf()被添加到 C99 的主要原因是难以保护vsprintf()或类似内容。一种解决方法是打开/dev/null,使用vfprintf()将数据格式化为它,注意需要多大的结果,然后决定是否可以安全继续。恶心,尤其是如果您在每次通话时都打开设备。 -
@JonathanLeffler 感谢您的提示,请随时将其作为答案发布(带有警告):)