首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >当vsnprintf不可用时,安全地格式化字符串

当vsnprintf不可用时,安全地格式化字符串
EN

Stack Overflow用户
提问于 2018-09-27 12:35:36
回答 1查看 1.5K关注 0票数 3

我正在编写需要格式化字符串的代码,并且希望避免缓冲区溢出。

我知道,如果vsnprintf可用(C99以后),我们可以:

代码语言:javascript
复制
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)。如果不编写非常复杂的逻辑就无法实现,我很乐意为结果设置一个最大长度,但我不确定如何在不发生缓冲区溢出的情况下实现这一点。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2018-09-27 17:05:02

Pre-C99不提供简单的解决方案来格式化具有高度安全的防止缓冲区溢出的字符串。

正是那些烦人的"%s""%[]""%f"格式说明符需要如此仔细地考虑其潜在的长输出。因此,需要这样一种功能。@Jonathan Leffler

为了做到这一点,早期编译器要求代码分析format和参数以找到所需的大小。此时,代码几乎可以使您拥有完整的my_vsnprintf()。我会寻求解决这个问题的办法。@user694733 694733

即使使用C99,*printf()也有环境限制。

任何一次转换可产生的字符数应至少为4095。C11dr§7.21.6.1 15

因此,任何试图使用char buf[10000]; snprintf(buf, sizeof buf, "%s", long_string);的代码都有可能出现问题,即使使用了足够的buf[]strlen(long_string) > 4095也是如此。

这意味着快速而肮脏的代码可以计算%和格式长度,并合理地假设所需的大小不超过:

代码语言:javascript
复制
size_t sz = 4095*percent_count + strlen(format) + 1;

当然,对说明符的进一步分析可能会导致更保守的sz。继续写这个路径,我们结束在编写我们自己的my_vsnprintf()

即使使用您自己的my_vsnprintf(),安全性也只有这么好。没有运行时检查format (可能是动态的)是否与以下参数匹配。要做到这一点,就需要采取一种新的办法。

厚颜无耻的C99解决方案的自我广告,以确保匹配的说明符和参数:通用

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/52537188

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档