C语言使用sprintf触发format-overflow警告如何消除?
警告原因
你收到的是格式化字符串溢出警告,根本原因是sprintf()不会主动检查缓冲区边界,你的代码存在明确的缓冲区溢出风险:
note: ‘sprintf’ output between 13 and 62 bytes into a destination of size 50
编译器已经自动计算出输出长度范围:格式串"fopen-ing \"%s\""的固定前缀、后缀共占12字节,全局变量data_file是长度为50的char数组,最多可以存储49个有效字符(末尾需要预留1字节存储\0结束符),两者拼接后有效内容最长可达61字节,再加1字节的结束符总长度最大为62字节,而你定义的msg数组只有50字节空间,不足以容纳最坏情况的输出内容,因此触发了警告。
修复方案
以下三种方案都可以消除警告,按推荐优先级排序:
- 方案1:改用带长度限制的安全函数
snprintf()
这是最通用的修复方案,snprintf()的第二个参数可以指定缓冲区的总大小,写入内容超过缓冲区容量时会自动截断,永远不会出现越界写入的问题:char msg[50]; // 第二个参数传入缓冲区总长度即可 snprintf(msg, sizeof(msg), "fopen-ing \"%s\"", data_file); perror(msg); - 方案2:扩大
msg缓冲区的容量
直接按最大所需长度定义msg数组,从根源上避免空间不足的问题。所需最大长度为:固定内容长度 +data_file最大有效长度 + 结束符 = 12 + 49 + 1 = 62,你可以直接定义为64字节对齐:char msg[64]; // 调整为足够大的容量 sprintf(msg,"fopen-ing \"%s\"",data_file); - 方案3:规避字符串拼接操作,分开输出错误信息
不需要把文件名拼接到传给perror的参数中,分开输出即可完全规避缓冲区拼接的风险:if((fpS = fopen(data_file,"r")) == NULL) { fprintf(stderr, "fopen-ing \"%s\": ", data_file); perror(""); // perror会紧接着输出系统对应的错误描述 exit(1); }
额外提示
日常C语言开发中不建议使用无边界检查的sprintf()、gets()这类函数,它们很容易引发缓冲区溢出漏洞,优先使用snprintf()、fgets()这类带长度校验的安全函数。
内容的提问来源于stack exchange,提问作者Dev
相关产品推荐
相关产品推荐

