freeBuf
主站

分类

漏洞 工具 极客 Web安全 系统安全 网络安全 无线安全 设备/客户端安全 数据安全 安全管理 企业安全 工控安全

特色

头条 人物志 活动 视频 观点 招聘 报告 资讯 区块链安全 标准与合规 容器安全 公开课

点我创作

试试在FreeBuf发布您的第一篇文章 让安全圈留下您的足迹
我知道了

官方公众号企业安全新浪微博

FreeBuf.COM网络安全行业门户,每日发布专业的安全资讯、技术剖析。

FreeBuf+小程序

FreeBuf+小程序

PHP中的“数学悖论”
FreeBuf_318889 2020-11-10 16:31:29 141541

最近翻看PHP手册的时突然想到的一个点子,今天拿来复现一下觉得特别有趣,借此记录一下

案例

首先来看我测试时写的题目案例

<?php
highlight_file(__FILE__);
$a = $_GET[a];
$b = $_GET[b];
if (($a * 10) + ($b * 10) != ($a + $b) * 10){
echo 'flag';
}
?>

在数学公式中a*10+b*10=(a+b)*10是完全成立的 但在php中发生了意外,导致我们可以用一些手段来绕过这个公式

为什么在php中(0.1+0.7)*10=7?

我们查看php手册可以发现:

PHP 通常使用 IEEE 754 双精度格式,则由于取整而导致的最大相对误差为 1.11e-16。 十进制能够精确表示的有理数如 0.1 或 0.7,无论有多少尾数都不能被内部所使用的二进制精确表示,也因为存在这些误差,在进行数学运算时就会导致出现混乱的结果。首先我们需要了解什么是浮点数

浮点数

我们以双浮点数为例

1位符号位(E)

符号位:最高位表示数据的正负,0表示正数,1表示负数。

11指数位(Q)

指数位:表示数据以2为底的幂,指数采用偏移码表示

52位尾数(M)

尾数:表示数据小数点后的有效数字.

总共为64位

其实十进制0.1和0.7,对于二进制来说却是无限长的,由于浮点数存在位数长度的限制,就出现了误差

最后使得0.1+0.7=0.799999999999999......

这点其实不只是存在PHP语言中

python

JavaScript

分析

此时我们回到最上面的的问题

<?php
highlight_file(__FILE__);
$a = $_GET[a];
$b = $_GET[b];
if (($a * 10) + ($b * 10) != ($a + $b) * 10){
echo 'flag';
}
?>

($a * 10) + ($b * 10)得到的结果是0.1*10+0.7*10=1+7=8最后结果是8

($a + $b) * 10得到的结果是0.1+0.7=0.79999999*10=7.9999999最后结果是7.9999999

相互比较出现了不等的问题,导致了绕过

1604997163_5faa502b40f92d45ece31.png!small?1604997163429

总结

引用官方的一句话:永远不要相信浮点数结果精确到了最后一位,也永远不要比较两个浮点数是否相等。如果确实需要更高的精度,应该使用任意精度数学函数或者 gmp 函数

# web安全 # php # 弱类型
免责声明
1.一般免责声明:本文所提供的技术信息仅供参考,不构成任何专业建议。读者应根据自身情况谨慎使用且应遵守《中华人民共和国网络安全法》,作者及发布平台不对因使用本文信息而导致的任何直接或间接责任或损失负责。
2. 适用性声明:文中技术内容可能不适用于所有情况或系统,在实际应用前请充分测试和评估。若因使用不当造成的任何问题,相关方不承担责任。
3. 更新声明:技术发展迅速,文章内容可能存在滞后性。读者需自行判断信息的时效性,因依据过时内容产生的后果,作者及发布平台不承担责任。
本文为 FreeBuf_318889 独立观点,未经授权禁止转载。
如需授权、对文章有疑问或需删除稿件,请联系 FreeBuf 客服小蜜蜂(微信:freebee1024)
被以下专辑收录,发现更多精彩内容
+ 收入我的专辑
+ 加入我的收藏
FreeBuf_318889 LV.1
这家伙太懒了,还未填写个人描述!
  • 1 文章数
  • 0 关注者
文章目录