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

输入%n至fgets()导致C程序终止的原因是什么?

为什么输入%n会导致程序异常终止?

这是典型的格式化字符串漏洞引发的崩溃问题,咱们来仔细拆解原因:

1. 代码里的核心风险点

先看你代码里的这行关键代码:

snprintf(buf, sizeof buf, s);

这里你把用户从标准输入读取的s直接作为snprintf的格式化模板参数了。而snprintf这类格式化函数的设计逻辑是:前两个参数是输出缓冲区和缓冲区大小,第三个参数是格式化模板字符串,后面需要跟着模板对应的参数列表。但你这里只传了模板,没传任何匹配的参数——这就给恶意输入留了可乘之机。

2. %n的特殊作用

%n是C语言格式化函数里一个特殊的占位符:它不会像%s、%d那样输出内容,而是会把当前已经输出的字符总数写入到对应的指针参数指向的内存地址中。举个合法的使用例子:

int count;
printf("hello%n", &count);
// 此时count的值会被设为5,因为"hello"有5个字符

3. 输入%n时到底发生了什么?

当你输入%n后,snprintf会按照格式化规则,试图找到一个对应的指针参数来写入数据。但你的代码里根本没有提供这个参数,于是函数会从调用栈上读取一个随机的内存地址(因为可变参数函数会从栈上按顺序取参数),然后尝试往这个地址写数据。

这个随机地址大概率是:

  • 不属于当前程序的内存空间,或者
  • 是只读内存区域(比如代码段)

操作系统一旦检测到程序非法访问/写入内存,就会触发段错误(Segmentation Fault),直接终止程序。

快速修复方法

要解决这个问题,你需要把用户输入的内容当作普通字符串来处理,而不是格式化模板。修改snprintf这一行即可:

snprintf(buf, sizeof buf, "%s", s);

这样不管用户输入什么内容(包括%n、%s这类格式化符),都会被当作普通字符复制到buf里,不会触发格式化解析逻辑。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.22 09:01:20