PHP Floating Point Bug Crashes Servers
angry tapir writes "A newly unearthed bug in certain versions of the PHP scripting language could crash servers when the software is given the task of converting a large floating point number, raising the possibility that the glitch could be exploited by hackers. The bug will cause the PHP processing software to enter an infinite loop when it tries to convert the series of digits "2.2250738585072011e-308" from the string format into the floating point format. The bug only seems to affect version 5.2 and 5.3 of the language." Adds reader alphadogg: "Computer scientist Rick Regan first reported the bug on Monday, and the PHP development team issued patches the following day."
The 1 day turn around for a patch is pretty impressive. I wish some bigger companies would offer such fast patches against vulnerabilities..
Step 1: Write stuff in PHP
Step 2: ???
Step 2.9999990834239320: Profit!
imgladiusedperl
you actually havent found it ! hahaha. something like that ?
a better patch performance than this would be to actually go back in time and fix the bug before it is discovered. but then again, there would be no bug and no bugfixing would be needed. alternate timecycle breakdown ?
Read radical news here
Maybe I'm missing something, but why does PHP have its own version of strtod()? It's a standard C99 function, so you'll find it in libc or equivalent in any C99-compliant platform (including Windows) and more effort has probably gone into optimising that version than the PHP version, although if you're converting from strings to floating point values anywhere performance critical then you're probably Doing It Wrong.
Did the Zend team think that there weren't enough security holes in PHP and decide to increase the attack surface?
I am TheRaven on Soylent News
Yes each time someone access it will start an infinite loop, but each PHP page has a max. processing time (usually set to around 30 seconds). So still quite a number of requests to the offending page are needed to bring the server down.
To try the bug for yourself: $a = (float) "2.2250738585072011e-308";
Sweet. PHP finally has the qualifications to enter the X86 CPU market.
I mean, for all practical purposes, it's an infinitely small number, so why shouldn't it be an infinite loop?
make imaginary.friends COUNT=100 VISIBLE=false
Am I the only one to notice that 2.2250738585072011e-308 is not very large?
Apparently, some journalists need a patch too.
My 2.2250738585072011e-308 cents.
It's one digit (the last one before the e; should be a 4 instead of a 1) from the minimum positive value for an IEEE-754 double precision floating-point number.
GLaDOS for President 2016! "Well here we are again. It's always such a pleasure." -- GLaDOS, 2011
I guess I'll have to keep the copy of the combo somewhere other than on my PHP server now...
Damn_registrars has no butt-hole. Damn_registrars has no use for a butt-hole.
Are blackbird OS's written in PHP? Also fishes?
Who would win this election: Andrew Weiner vs Andrew Weiner's weiner.
And yep TFA did qualify it as the largest subnormal double-precision number. Of course the journalist probably didn't know what that meant.
Pet peeve: Profane people propagating perfunctory pedantry.
This number is just smaller than 2^(-1022).
According to python, 2.0 ** -1022 == 2.2250738585072014e-308. You can check that last significant digit in the mantissa using integer math in python:
>>> x = 22250738585072011 ... ... 51323238920926265344 ... 77840486139094368256
>>> y = 22250738585072014
>>> for num in xrange(1022): x *= 2; y *= 2
>>> print str(x)[:20], '...', str(x)[-20:]
99999999999999987277
>>> print str(y)[:20], '...', str(y)[-20:]
10000000000000000075
The number in question is just beyond the range that fp is intended enough to handle, but probably not far enough for some initial validation logic to catch. It is probably not too difficult for the bug fixers to verify that the range issues are handled properly now that they know about it.
1.112537e-308 ought to be enough for anybody.
I'm sorry, I only accept criticism in the form of sed expressions.
The inconsistent type system, lack of Unicode support, lack of namespaces, quirky parser, and other stupidities (== vs. ===) weren't enough, so. Is this bug inane enough to actually get people to realize that PHP bites?
~ C.
http://slashdot.org/submission/1435314/DoS-attack-found-in-PHP-thanks-to-x87-FP
Comment removed based on user account deletion
I don't understand why the patch solves the problem....though I haven't done any serious software development for years. It looks like all they did was add the "volatile" keyword to a variable declaration.
http://svn.php.net/viewvc/php/php-src/branches/PHP_5_2/Zend/zend_strtod.c?r1=307095&r2=307094&pathrev=307095
From:
double aadj, aadj1, adj;
To:
volatile double aadj, aadj1, adj;
But after quickly reviewing the code, I don't see why the volatile keyword fixes this problem. It doesn't appear to be multithreaded code where another thread could stomp on the variable, and it just seems to be straight arithmetic, it doesn't seem like they are handing it off to a math coprocessor and then later waiting for the variable to be set.
Does the volatile keyword change the compiler optimizations in a way that avoids the problem?
Anything that deals with shipping with USPS apis would. I've seen people get hung up on why some value (i forget example what now) was being returned incorrectly. Turns out they had to cast the value to a float before passing it to the api.
"Ubuntu" -- an African word, meaning "Slackware is too hard for me". - stolen from Dan C alt.os.linux.slackware
I wonder how many of you read this article's summary and them immediately wrote a quick PHP script to perform this exact conversion. If you did, did you crash your machine or did you encounter a disappointing non-event?
- James
The i387 (and its successors) suck as floating-point hardware; this we know. However, this bug isn't as crippling as it might seem. This bug won't affect amd64 machines running in 64-bit mode where the compiler is GCC (since GCC uses SSE2 in that case). It also won't affect any Mac OS X machines, since they made the smart move to always use SSE2 on Intel hardware since all of the Intel chips they've ever shipped support it. And I think FreeBSD uses double precision mode by default, so this probably won't affect them either, unless PHP puts the libc into extended-precision mode.
That server must be 32bit then as this bug is pretty much limited to 32bit versions of php (reference: http://www.exploringbinary.com/php-hangs-on-numeric-value-2-2250738585072011e-308/)
Any USPS inteface that deals with numbers like 2e-308 is, well, fascinating to think about but hardly relevant to the real world.
I mean, "I'd like a penny stamp please". "Here are 5e307 2e-308 cent stamps instead...."
PHP, my days of not taking you seriously are certainly coming to a middle.
<php echo "start\n"; $a = (float) "2.2250738585072011e-308"; echo $a,"\n"; echo "end\n"; ?>
It got this: /home/dougie/public_html/test_crud/bug.php on line 3
[Thu Jan 06 23:30:49 2011] [error] [client 10.1.1.30] PHP Fatal error: Maximum execution time of 30 seconds exceeded in
Sigs. We don't need no steenking sigs.
And thread safety? It's a pure function! It doesn't need any thread safety!
strtod() has no side effects, but it still reads global variables. Does your locale use a period or a comma as a decimal point? And did another thread change the locale behind your function's back?
FORTRAN is just too damn slow for such things.
Especially when he spends most of his time riching.
mb_internal_encoding('UTF-8');
Fatal error: mb_internal_encoding is not defined because mbstring is not enabled by default. And no, you can't install this extension on your hosting company's copy of PHP.
I didn't test PHP, because I never use it.
I did, however, do the responsible thing and ask myself, "does code that I maintain have a similar bug, and does its test suite validate it?" I checked the Tcl test suite, and discovered that it lacked a test for the case. I added test cases for input and output conversion of the largest positive subnormal, the smallest negative subnormal, the smallest positive normal, and the largest negative normal. (All the test cases passed, so committing them ended what I had to do.)
Tcl, too, has its own conterparts to strtod and sprintf("%g"), because it depends on float->string->float being 100% lossless and on having the string representation of a float be the shortest string that reconverts to the given number. It's quite tricky to get right; this particular corner case is the tip of the iceberg.
You probably wouldn't do it directly, but as soon as you do any math on the value it will get cast to a float (or int, depending on the values). I'd bet a lot of database abstraction layers will do just such a thing, among plenty of other tools.
$ php -a
Interactive shell
php > var_dump('1.1');
string(3) "1.1"
php > var_dump('1.1' + 0);
float(1.1)
How are sites slashdotted when nobody reads TFAs?
That's my favorite number.
Why is this joke of a programming language so popular is beyond me. It's a complete failure, obviously created by a bunch of first grade students who have no clear idea about syntax and uniformity. Every new version breaks compatibility with older scripts and at the same time adds more moronisms. Ugh!
You could always change the combination to 12345. It's always worked for me.
$x = 2.2250738585072011e-308;
$x = 2.2250738585072011e-308;
$x = 2.2250738585072011e-308;
Table-ized A.I.
Maybe because the target number is slashdotted?
Table-ized A.I.