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

C语言中scanf/sscanf读入字符超缓冲区容量时会引发什么问题?

问题结论

在C语言开发场景下,若调用scanf、sscanf等格式化输入函数时,读入字符数超出目标缓冲区预留的可用存储空间,属于典型的缓冲区溢出问题,会触发C语言标准定义的未定义行为,不存在固定、可预测的运行结果。

对应示例代码如下:

char foo[2], bar[5]="abcd";
sscanf(bar, "%s", foo);
实际运行中常见的后果

未定义行为意味着程序可能出现任意表现,开发和生产环境中最常遇到的情况包括:

  • 相邻内存数据被意外篡改:以上述代码为例,foo仅分配了2字节空间,最多只能存储1个有效字符+1个字符串结束符\0,但不带长度限制的%s格式符会从bar中读入全部4个字符abcd,再自动追加1个结束符\0,总共往foo的起始地址写入5字节数据。多写入的3字节会覆盖foo数组后方的栈内存,如果这部分内存存储了其他局部变量、函数栈帧基址、返回地址,会直接导致变量值错乱、程序逻辑跑飞。
  • 程序直接崩溃:如果溢出写入的地址属于不可写内存区间,或者覆盖的函数返回地址指向非法地址,会触发内存访问违规,直接抛出段错误(Segmentation Fault)终止运行。
  • 存在高危安全风险:攻击者可以构造特定长度和内容的输入,通过溢出覆盖函数返回地址,让程序跳转到攻击者植入的恶意代码段执行,实现权限提升、代码注入等攻击,这是C/C++程序最经典的高危漏洞类型之一。
  • 防护机制主动拦截:如果编译时开启了栈保护(如GCC默认开启的栈金丝雀防护),程序运行时会检测到栈关键数据被篡改,直接触发异常终止,避免进一步破坏。
  • 无即时异常:如果溢出写入的内存区间刚好是未被使用的可写内存,程序可能暂时不会表现出异常,但内存破坏已经发生,后续运行中会出现随机、难以复现排查的逻辑错误或崩溃。
正确规避方式

使用scanf/sscanf的%s格式符读入字符串时,必须明确指定最大读入长度,长度值为「目标缓冲区大小-1」(预留1字节存储字符串结束符)。比如上述示例中要安全读入到foo数组,应将格式化字符串写为%1s,从接口层面杜绝溢出可能。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.29 04:42:10