PHP float bug: PHP Hangs On Numeric Value

佐手、 提交于 2019-12-10 09:28:17

问题


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?


回答1:


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.




回答2:


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.




回答3:


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 :|




回答4:


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




回答5:


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.




回答6:


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.




回答7:


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




回答8:


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.



来源:https://stackoverflow.com/questions/4605590/php-float-bug-php-hangs-on-numeric-value

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!