当前位置: 首页 > news >正文

sprintf(...)溢出边界导致程序崩溃的问题

文章目录

  • 小结
  • 问题及解决
  • 参考

小结

使用sprintf(...)进行格式化是一种标准的做法,但是这样做是有一个极大的风险,由于sprintf(...)不进行边界检查,这样会有写操作溢出边界的风险,并导致程序崩溃。本文进行了简单写操作溢出边界的测试,模拟程序崩溃,并建议了更为安全的snprintf(...)方法进行格式化。

问题及解决

众所周知,sprintf(...)不进行边界检查,再加上double或者是float的内建的数据类型一起使用(有时候会是一个比较大的正数),比较容易出现写操作溢出边界并导致程序崩溃,已经是臭名昭著了。

以代码sprintf(str, "%.2fMB(%.2f%%)", double_a, double_b);为例。

sprintf的说明指示符%.2f规定了小数点后面截取两位,但小数点前面有多少位就采用多少位,例如像2.4008127812204012E+159这样的大数,基本上小数点前面就超过160位数字了。如果数组str比较小,就抓瞎了,写操作会溢出边界,并致程序崩溃。这种错误有时候极难定位,浪费很多宝贵的时候来找bug。

如果采用比较安全的做法, 例如: snprintf(str_short, 30, "%.2fMB(%.2f%%)", double_a, double_b);,规定了边界,只写入前29位(最后再加一个结尾符),这样就不用担心写操作会溢出边界的问题了。

以下是程序测试很好地模拟了几种情况(double_a是一个很大的数,double_b是一个很小的数):

	char str[200];char str_short[30];double double_a= 2.4008127812204012E+159;double double_b= 1.3906711615670009E-309;cout << "double_a= " << double_a<< endl;cout << "double_b= " << double_b<< endl;//以下代码不会出现溢出边界,程序正常运行sprintf(str, "%.2fMB(%.2f%%)", double_a, double_b);cout << "str string = " << strStorage << endl;//以下代码会出现溢出边界并导致程序崩溃, 注释之//sprintf(str_short, "%.2fMB(%.2f%%)", double_a, double_b);//cout << "str_short string = " << str_short<< endl;//以下代码是比较安全的做法,进行有效的边界检查, 不会出现溢出边界,程序正常运行,输出了29位数字(后接一个结尾符)snprintf(str_short, 30, "%.2fMB(%.2f%%)", double_a, double_b);cout << "str_short string = " << str_short<< endl;system("pause");return 0;

输出结果:

double_a= 2.40081e+159
double_b= 1.39067e-309
str string = 2400812781220401246196118053255811918339999978374591715533604156445593861118215728144462510983065193819073699313679732935503602200085321608454731838025375940608.00MB(0.00%)
str_short string = 24008127812204012461961180532
Press any key to continue . . .

参考

sprintf(str,“%f”, voltage_temp ); works in C but not C ++
C++ Buffer Overflow: Format String (%f/%F)
Stackoverflow: understanding the dangers of sprintf(…)
C++ float and double

http://www.lryc.cn/news/37994.html

相关文章:

  • 公式推导+dfs简版
  • 论文笔记 | 标准误聚类问题
  • 银行管理系统--课后程序(Python程序开发案例教程-黑马程序员编著-第7章-课后作业)
  • 【18】组合逻辑 - VL18 实现3-8译码器①
  • 2020蓝桥杯真题最长递增 C语言/C++
  • 华为OD机试题 - 寻找连续区间(JavaScript)| 机考必刷
  • 一次疲惫的调试--累了及时透气
  • 综合练习7 摄氏度转华氏温度(“\t“的使用,循环语句)
  • AWS数据库总结
  • 2个步骤就能批量给视频添加滚动字幕
  • PHP 的运行方式有哪些?
  • Web学习3_JavaScript
  • 「MySQL基础」不可重复读和幻读的区别
  • CorelDRAW2023最新版新增功能200多个新模板
  • springboot自定义日志以及行号正确展示
  • 【GAOPS055】verilog 乘法、除法和取余
  • TCP UPD详解
  • 金三银四、金九银十 面试宝典 MySQL面试题 超级无敌全的面试题汇总(超万字的面试题,让你的MySQL无可挑剔)
  • 【Java】初识Java
  • JVM相关知识
  • 【LeetCode】剑指 Offer(21)
  • 线性求解器Ax=b的验证
  • java 事件处理机制 观察者模式
  • 使用 HTML5 轻松验证表单插件
  • 【Error: ImagePullBackOff】Kubernetes中Nginx服务启动失败排查流程
  • 九龙证券|直逼1.5万亿!A股融资余额创年内新高,青睐这些行业和个股
  • 【JavaScript】36_正则表达式
  • 参考 | 辨别真假笔记本三星内存条 (ddr4)
  • JavaScript Math(算数)对象
  • MyBatis里面用了多少种设计模式?