PHP 浮动错误:PHP 挂在数值上

发布于 2024-10-10 10:56:16 字数 538 浏览 8 评论 0原文

我刚刚读了一篇关于 php 挂在某些浮点数上的有趣文章,请参阅 The Register< /a> 和探索二进制

我从不明确使用浮点数,我使用 number_format() 来清理我的输入并显示例如价格。

另外,据我所知,来自例如表单的所有输入都是字符串,直到我告诉他们否则,所以我认为这个问题不会影响我。

我是对的吗,或者我是否需要检查我的服务器上的 WordPress 和 Squirrelmail 安装,看看它们是否将任何内容投射到浮动?或者更好的是,grep 我的服务器上的所有 php 文件都为 float

I just read an interesting article about php hanging on certain float numbers, see The Register and Exploring Binary.

I never explicitly use floats, I use number_format() to clean my input and display for example prices.

Also, as far as I am aware, all input from for example forms are strings until I tell them otherwise so I am supposing that this problem does not affect me.

Am I right, or do I need to check for example Wordpress and Squirrelmail installations on my server to see if they cast anything to float? Or better, grep all php files on my servers for float?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(8

谷夏 2024-10-17 10:56:17

如果您无法修补您的 php 安装,您可以使用以下内容: 以下针对 php bug #53632 的解决方法存在任何问题

这只是一个临时解决方法,直到您可以真正修补您的 php 安装为止

If you can't patch your php installation you can use the following: Any problems with the following work around for php bug #53632

It's just a temporary workaround until you can actually patch your php install

清风疏影 2024-10-17 10:56:17

为了捕获数字的所有可能的符号,必须使用子字符串搜索。

请参阅 http://www.aircraft24.com/en/info/ php-float-dos-quickfix.htm 了解我们最新的解决方法。

In order to catch all possible notations of the number, substring-search must be used.

See http://www.aircraft24.com/en/info/php-float-dos-quickfix.htm for our latest workaround.

绝情姑娘 2024-10-17 10:56:16

缓解该问题的方法:

  1. 使用现代 CPU。大多数现代 64 位 CPU 都不会受到影响(实际上我很难找到允许重现它的主机,因为它们倾向于使用更现代的硬件)。亚马逊虚拟机似乎也能幸免。
  2. 升级您的 PHP 版本 - 5.3.5 和 5.2.17 一旦发布(可能是今天)就包含修复程序。
  3. 在 CFLAGS 中使用 -ffloat-store 进行构建(会减慢代码速度)。
  4. 手动应用 补丁到您的代码并重建 PHP。

寻找具有 float 的代码可能不会有帮助,因为引擎在许多字符串 > 数字转换场景中使用 zend_strtod 。

PS 顺便说一句,这段代码是标准 BSD 库 strtod 代码,不是 PHP 独有的。因此使用此代码的其他项目也可能会受到影响。

Ways to mitigate the problem:

  1. Use a modern CPU. Most modern 64-bit CPUs would be immune (I actually had trouble finding host that allows to reproduce it since they tend to use more modern hardware). Amazon VMs seem to be immune too.
  2. Upgrade your PHP version - 5.3.5 and 5.2.17 once released (probably today) include the fix.
  3. Build with -ffloat-store in CFLAGS (will slow down the code).
  4. Manually apply the patch to your code and rebuild PHP.

Looking for the code that has float probably won't help as zend_strtod is used by the engine in many string->number conversion scenarios.

P.S. this code btw is standard BSD library strtod code, not unique to PHP. So other projects using this code might be affected too.

悸初 2024-10-17 10:56:16

来自黑客新闻

出现此问题是由于 IA-32 的
80 位浮点运算。这
简单修复:添加“-ffloat-store”标志
到您的 CFLAGS。

有问题的
函数 zend_strtod 似乎解析
尾数(2.225...011 部分)和
单独的指数(-308 部分),
c>计算 m*10^e 的近似值
并不断改进
近似,直到误差变为
小于0.5ulp。问题是
这个特定的数字导致
无限循环(即迭代
根本没有改善错误)
80 位 FP,但 64 位 FP 不支持。
由于 x86-64 通常使用 SSE2
指令集(带 64 位 FP)
它代替了已弃用的 x87
没有这个问题。

From hackernews:

This problem occurs due to IA-32's
80-bit floating point arithmetic. The
simple fix: add a "-ffloat-store" flag
to your CFLAGS.

The problematic
function, zend_strtod, seems to parse
the mantissa (2.225...011 part) and
the exponent (-308 part) separately,
c> alculate the approximation of m*10^e
and successively improve that
approximation until the error becomes
less than 0.5ulp. The problem is that
this particular number causes the
infinite loop (i.e. the iteration does
not improve the error at all) in
80-bit FP, but does not in 64-bit FP.
Since x86-64 in general uses the SSE2
instruction set (with 64-bit FP)
instead of the deprecated x87 it does
not have this problem.

书信已泛黄 2024-10-17 10:56:16

作为快速解决方法,您可以扫描输入数组:

foreach(array("_GET","_POST","_REQUEST","_COOKIES") as $G) {
    if (in_array('2.2250738585072011e-308', $G)) {
         header("Status: 422 Unprocessable Entity");
         exit;
    }
}

如果您不在输入变量中使用子数组,这就足够了。它会起作用,因为它将浮点作为字符串保存,输入数组保存字符串,并且 in_array 也在字符串上下文中运行。

但是我还没有考虑是否还有该值的其他表示形式。这是迄今为止唯一已知有效的方法,但可能还有更多。因此,更新是更可取的:|

As quick workaround, you could scan the input arrays:

foreach(array("_GET","_POST","_REQUEST","_COOKIES") as $G) {
    if (in_array('2.2250738585072011e-308', $G)) {
         header("Status: 422 Unprocessable Entity");
         exit;
    }
}

This is sufficient, if you don't use subarrays in the input vars. It would work because it holds the float as string, the input arrays hold strings, and in_array operates in string context too.

However I haven't considered if there are other representations of that value. This is the only one that's known to work so far, but there might be more. So, updating is more advisable :|

傲世九天 2024-10-17 10:56:16

正如 marcog 所说,这是 x87 数学的浮点算术错误。如果您想了解更多相关信息,请查看 GCC bug,链接

As marcog said it's a floating point arithmetic bug with the x87 math. If you want to read more about it check out the GCC bug, Link

流云如水 2024-10-17 10:56:16

仅仅搜索 float 是不够的,因为您随后正在寻找将变量值显式转换为 float 的代码,但您不会找到任何隐式转换的实例。

$d = '2.2250738585072011e-308';
$f = float($d);

是显式转换,但是像这样的代码呢:

$d = '2.2250738585072011e-308';
$f = $d + 0.1;

或者

$d = '2.2250738585072011e-308';
if ($d == 0.5) {

我相信这个错误现在也已经在最新的 PHP 构建代码中得到修复,尽管像 xampp 这样的包仍然受到影响。

It isn't enough to simply search for float, as you're then looking for code that explicitly casts a variable value to a float, but you won't find any instances where the casting is implicit.

$d = '2.2250738585072011e-308';
$f = float($d);

is explicit casting, but what about code like:

$d = '2.2250738585072011e-308';
$f = $d + 0.1;

or

$d = '2.2250738585072011e-308';
if ($d == 0.5) {

I believe that this bug has also now been fixed within the latest PHP build code, although packages such as xampp are still affected.

怂人 2024-10-17 10:56:16

搜索显式浮点转换不会对您有帮助 - 在 php 中,变量被视为其用途。小例子:

$mystring = "123.45"; //mystring is a string here
$myvalue = $mystring * 4; // mystring is a float here
                          // and there's no explicit float-cast

如您所见:升级/修复您的 php 安装是避免服务器死机的唯一保存方法。

编辑:您的评论:

浮动确实不是那么容易。即使是像 0.7 或 0.8 这样的简单数字也无法精确存储,因此经过一些计算,您的 0.8 可能会是 0.799999999789...如果有更多这样的事情,出现问题只是时间问题。

举个例子(如果你是 Windows 用户):

  1. 打开 Windows 计算器
  2. 计算 4 的平方根(应该是 2)
  3. 从结果中减去 2(应该是 0 但是... woooow ;))

这个错误一直存在于 Windows 计算器中 - 它表明即使是大公司也可能会使用浮点数失败,但计算器不会杀死你的系统 - 如果这样的错误可以杀死你的系统系统(比如这个 php-bug)你将必须升级/修复它,没有。

searching for explicit float-casts won't help you - in php, a variable is treated as what it's used for. little example:

$mystring = "123.45"; //mystring is a string here
$myvalue = $mystring * 4; // mystring is a float here
                          // and there's no explicit float-cast

as you can see: upgrade/fix your php-installation is the only save way to avoid a dead server.

EDIT: to your comment:

floats really arn't that easy. even simple numbers like 0.7 or 0.8 can't be exactly stored and so it could happen that you 0.8, after some calculations, is 0.799999999789... with even more of this shit, it's just a matter of time until you get problems.

just as an example (and if you're a windows-user):

  1. open the windows-calculator
  2. calculate the sqare-root of 4 (should be 2)
  3. substract 2 from the result (should be 0 but... woooow ;) )

this bug is in the windows-calculator since... ever - and it shows that even big companys can fail using floats, but the calculator doesn't kill your system - if such a bug can kill your system (like this php-bug) you'll have to upgrade/fix it, bar none.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文