You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用%d格式符的fscanf是否会引发缓冲区溢出?Fortify误报分析

Fortify检测fscanf("%d")缓冲区溢出的疑问解答

是否为误报?

这不算严格意义上的误报,但风险触发场景非常极端。Fortify之所以告警,是因为%d格式符没有显式限制输入长度,当输入的十进制整数超出int类型的可表示范围时,会触发C标准中的未定义行为——这种行为理论上可能导致写入int内存之外的区域,比如篡改数组相邻元素的内存。不过正常业务场景下的合法输入不会触发,但恶意构造的超大数值输入存在潜在风险。

传入int地址是否可能越界?

是的,但仅在输入数值超出int的取值范围时才会触发。举个例子:如果系统中int是4字节(取值范围为-2^31到2^31-1),当输入一个远大于2^31-1的十进制数时,fscanf无法将其完整存入int变量,此时的行为是未定义的,极端情况下可能溢出到_RWHour数组的相邻内存位置,甚至更远处。

安全规避方案

针对这个问题,有几种可靠的修复方式:

  • 限制输入长度+范围校验
    给%d加上长度限制,同时在读取后校验数值是否在int的合法范围内:

    // 针对32位int限制最多10位输入(覆盖最大取值的十进制位数)
    if (fscanf(fp, "%10d", &_RWHour[i][j]) <= 0) {
        // 处理读取失败
    }
    // 校验数值是否在int范围内
    if (_RWHour[i][j] < INT_MIN || _RWHour[i][j] > INT_MAX) {
        // 处理超范围数值
    }
    

    注意:如果是64位int,需要把长度限制调整为19位。

  • 改用更可控的输入函数组合
    用fgets读取固定长度的字符串,再配合strtol解析,这种方式能完全掌控输入处理流程:

    char input_buf[16]; // 足够容纳int类型的十进制字符串
    if (fgets(input_buf, sizeof(input_buf), fp) == NULL) {
        // 读取失败处理
    }
    
    char *end_ptr;
    errno = 0;
    long parsed_val = strtol(input_buf, &end_ptr, 10);
    
    // 多重校验:确保是有效整数、无多余字符、未超出范围
    if (end_ptr == input_buf || (*end_ptr != '\n' && *end_ptr != '\0') || errno == ERANGE || parsed_val < INT_MIN || parsed_val > INT_MAX) {
        // 无效输入处理
    }
    _RWHour[i][j] = (int)parsed_val;
    
  • 启用运行时边界检查
    编译时开启编译器的未定义行为检测选项,比如GCC的-fsanitize=undefined,可以在运行时及时发现整数溢出等问题,提前排查风险。


内容的提问来源于stack exchange,提问作者Shane Bishop

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.18 10:07:08