PHP Floating Point Bug Crashes Servers 213
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."
1 day turn-around (Score:4, Informative)
The 1 day turn around for a patch is pretty impressive. I wish some bigger companies would offer such fast patches against vulnerabilities..
Re: (Score:2)
1 day, really that long ? ;-)
I've sometimes even seen 1 hour or even minutes from certain OSS projects. I guess it was trivial to fix.
Re:1 day turn-around (Score:5, Informative)
It's because they're not spending their time improving thread-safe modules, ternary operators, flip flopping again on defaulting magic_quotes, or understanding pragmatism :)
Re: (Score:2)
That's the first time I've heard someone complain about Zend not being pragmatic.. Usually the argument is that they're too pragmatic and need to break backwards compatibility, fix inconsistencies, and make the language less forgiving.
As someone who has used PHP quite a bit I'm curious about what you think the alternative is though:
Re: (Score:3)
But was it tested well? Does it break anything else? :P
Re:1 day turn-around (Score:5, Informative)
Two primary reasons:
1. This was a relatively trivial, extremely specific, easily reproducible bug, so fixing it was quick and low risk.
2. A major vendor like Microsoft has to do extensive testing of patches as well as give ample warning to dozens of software partners who may or may not be using some bizarre workaround for the bug or be depending on it's broken behavior. An OSS project can just put it out and let their users choose whether or not to upgrade and deal with the potential ramifications.
Note that I'm not necessarily saying one or the other is better here, it's a matter of preference and for most people it's probably situational.
Re: (Score:2)
I was talking about OSS in general, PHP is not a very good example of that though. They made many mistakes in the past. :-/
Re:1 day turn-around (Score:4, Funny)
PHP is made of 100% pure premium stupid decision.
Re: (Score:3)
Re: (Score:2)
This is not available in the latest PHP release either. So, for most people it will have to wait until the next release, which can be a long time. Often, you can get a specific patch from microsoft before their monthly release cycle, so I guess it's pretty much the same.
Re: (Score:2)
Microsoft pitches this as an advantage (predictable updates!), and I laugh out loud every time I hear one of their marketing people say it.
You might laugh out loud, but given that Microsoft has the infrastructure in place to perform the immediate release of patches, what advantage would there be for them to delay the updates other than to placate the needs of their business customers? They used to do updates as soon as they were ready, but they changed this practice based on feedback from their larger clients.
Prior "Windows Updates", people used to run systems that remained unpatched for years, so having to wait a month is still way better tha
Re:1 day turn-around (Score:5, Insightful)
Risk management.
Every change is a potential new bug. Even your security patch may bring a new security issue.
You test and you test and you test, but nothing's certain in the eyes of management. So the shipping is delayed, the testing continues, and eventually you have a batch of bugfixes and patches you're fairly certain works well together. Traditionally, you call that collection a service pack, and you ship... ;-)
(Remember the blue-screen problems a Microsoft patch caused some folks a while back? That was embarrassing. So don't kid yourself that this isn't risky.)
This is also why companies prefer to move to an established "cadence" or rhythm. Monthly security patching is Microsoft's preference, for example. IBM has some software divisions which keep to a four or six month "point release" shipping schedule. Not good enough for v9.0.2? Well, it'll probably be in v9.0.3in six month's time...
That cadence helps with testing, and reduces the risk you're taking, and therefore helps to preserve your reputation and therefore your business.
Open source projects often just ship "when it's ready", and are more open anyway. They're not thinking like a company which is trying to manage its reputation and maximise business (well, profits really).
An open source project just wants to ship something that's reliably usable and useful. That changes their motivations, and therefore changes their management of patching and shipping...
Re: (Score:2)
"You test and you test and you test, but nothing's certain in the eyes of management. So the shipping is delayed, the testing continues"
This is how Microsoft does it:
http://www.youtube.com/watch?v=rOwMW6agpTI [youtube.com]
That does not look like how you described it.
Re: (Score:2)
It actually starts at 5 minute, 44 seconds:
http://www.youtube.com/watch?v=rOwMW6agpTI#t=5m44s [youtube.com]
Re:1 day turn-around (Score:4, Informative)
I'm as anti-microsoft as the next guy here, but the cases really aren't comparable, and you have to give them credit for their thoroughness.
Re: (Score:2)
Joel hasn't worked for Microsoft for more then a decade now.
Re: (Score:2)
Re: (Score:2)
Can someone please explain to me why all these OSS projects are able to turn around security updates so fast and Microsoft cannot?
Sure:
- This isn't a security update, it's a bug fix.
- It was probably a very simple bug fix.
- No liability.
- The nature of the bug is "it's broke" as opposed to "It's behaving differently". So it's not like a million people are going to complain when their random applications lock up.
Re: (Score:3, Insightful)
Or, the OSS software gives it to you for free, but 'as is'. So they can go "Here's a fix for it. If we break something else, we're not responsible. We may try to fix that, or you can go fix it yourself."
In Microsoft's case, if they break something down the line, they have potential lawsuits against them. They try to use EULA's to try and protect themselves, but it's not foolproof. They're dealing with real money, so they have people trying to mitigate further issues. And that usually means heavy testi
Re: (Score:2)
Actually, Microsoft's EULAs disclaim liability just like FLOSS licenses do. The difference is that Microsoft has deep pockets. Your average FLOSS project does not.
Re: (Score:2)
He's not kidding nor exaggerating at all. If a security fix breaks $foo, then, only because Microsoft and $foo's company is in the USA, can be liable to be sued for it.
http://blog.seattlepi.com/microsoft/archives/109471.asp [seattlepi.com] An example of a bad update breaking an MS product.
Also if it breaks the system on a laptop or desktop environment as in it won't boot, then people would be extremely mad and businesses will sue.
Re:1 day turn-around (Score:4, Insightful)
He's not kidding nor exaggerating at all. If a security fix breaks $foo, then, only because Microsoft and $foo's company is in the USA, can be liable to be sued for it.
When was the last time anyone successfully sued a software company for something like that?
Re: (Score:2)
Microsoft hardware driver updates have repeatedly bricked my systems over the years. I no longer allow them to install hardware updates.
I bitched and whined about the reinstall, but I never even thought about suing anyone for it.
Maybe if I was 'merican...
Re: (Score:2)
...Breaking other shit by mistake with the update is not nearly as serious as not taking action against a known problem.
Let's say Microsoft writes a patch for an issue affecting 0.01% of its user base and deploys it immediately. The patch fixes the problem that 0.01% of the user base is having, but causes a different problem that 0.02% of its user base encounters. Is that a good thing? Sure, for those people who were affected by the first problem but not the second. Those who were affected by neither don't care. Those who were affected by both are still stuck (albeit with a different problem.) And those who were not af
Re:1 day turn-around (Score:4, Informative)
I looked. Seems they fixed it: http://svn.php.net/viewvc/php/php-src/trunk/Zend/zend_strtod.c?r1=307095&r2=307094&pathrev=307095 [php.net]
Re: (Score:3)
In typical PHP fashion, the patch doesn't actually fix the underlying problem, it simply checks for that one specific string. Seriously, stop gloating for 30 seconds, check the source and cringe at the incompetence.
What are you talking about? There is more than one number that triggers the problem, and the patch does not do a simple string comparison.
http://svn.php.net/viewvc/php/php-src/trunk/Zend/zend_strtod.c?r1=304407&r2=307095&pathrev=307095 [php.net]
Re: (Score:2)
They... added a volatile?
What the hell is that function doing, if it requires that?
Re: (Score:2)
They... added a volatile?
What the hell is that function doing, if it requires that?
Good question - I asked the same thing in a post below, but no one has answered yet.
Re: (Score:2)
If you need to add volatiles to your code to get it to run right, then either code is doing low-level hardware accesses, is multithreaded (and some say you shouldn't be using volatile even for that), or else it is completely broken. That, or the compiler is broken.
I have a really hard time thinking up a scenario where adding a volatile like that would actually be the correct fix, and not just a change that makes the code work by random chance. It sure seems like the actual problem should be elsewhere.
Re: (Score:2)
I have a really hard time thinking up a scenario where adding a volatile like that would actually be the correct fix, and not just a change that makes the code work by random chance. It sure seems like the actual problem should be elsewhere.
I take it you've never had to program the x87 FPU?
I presume this is a weird consequence of the FPU hiding bits from you and using a volatile forces the compiler to pull the value out of the FPU to memory instead of leaving it in there with the extra bits of precision? If I remember correctly, it's something like 80-bits internally but 64-bits externally, so you can get different floating point results depending on the code the compiler generates..
Re:1 day turn-around (Score:5, Informative)
On the x87 (traditional FPU for x86, still used by most code because of support for older processors) the internal temporaries are fixed size. This means if the compiler chooses to keep temporaries in FPU registers you can get marginally different results from if the compiler spills them to memory.
This has some nasty implications like doing the same comparison twice may give different results if the first comparision was done with the value still in the FPU registers and the second was done after the compiler had moved it to memory and back.
By making a variable volatile you force the compailer to store it in memory at all times and therefore ensure consistent results for comparisions involving it.
Re: (Score:2)
That's precisely why pretty much all languages explicitly allow floating-point computations to be performed at precision higher than that indicated by operand types (and Java even went so far as to add "strictfp" to let you disable that behavior if desired). Reason being that your code really shouldn't care about such things. If it does, it is very likely that it is doing FP comparisons improperly in the first place. So why do they need it for a simple string-to-number conversion function?
Re: (Score:2)
That's a decent enough band-aid so long as a more comprehensive fix follows. The question is will it?
Hmmmm (Score:5, Funny)
Step 1: Write stuff in PHP
Step 2: ???
Step 2.9999990834239320: Profit!
You remember the php bug you found yesterday ? (Score:2)
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 ?
Re: (Score:3)
Please - don't you remember the last time we did that?
Oh, I guess you wouldn't.
Why does this code even exist? (Score:5, Interesting)
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?
Re: (Score:2)
Re: (Score:2)
Re:Why does this code even exist? (Score:4, Informative)
>Maybe I'm missing something, but why does PHP have its own version of strtod()?
That's a very good question. PHP's strtod is quite complicated, has its own memory allocator, does its own localization and rounding, and it is going to some lengths to ensure its own thread safety. If I were to guess, my guess would be that some of the target platforms for PHP/Zend are deficient in these areas.
Re: (Score:2)
Re: (Score:2)
Localization I can almost understand. OS X is the only platform I know of that lets you specify a per-thread locale that functions like this respect. But memory allocator? It's converting a string to a double - it shouldn't need a memory allocator at all, it just scans a string and collects the digits into a mantissa and exponent then. And thread safety? It's a pure function! It doesn't need any thread safety!
each thread in windows has its own independent localization settings also.
strtod() (Score:2)
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?
Re: (Score:3)
As for thread safety, there's a lot of math that has to happen to cacluate that fraction. On many systems, particularly embedded systems on micros without a float
Re: (Score:2)
Re: (Score:2)
Re: (Score:2)
FTFY. (disclaimer: I'm programming in php daily and I like it).
Re: (Score:2)
The thing with PHP is that you rather have to learn how not to use it to be better with it - there's so many minefields there.
Re: (Score:3)
Last I checked Ruby didn't have abominations such as implicit conversion of stings to numbers in operator ==.
Yes, every language and framework have some nasty bits, but some have more than others, and PHP is on the "oh fuck!" end of that spectrum.
Re: (Score:2)
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
Sometimes the overhead required to take values between languages actually makes doing it in the lower performance language slower, even if it's more highly optimized. This obviously manifests itself much more readily in quicker functions like strtod() where the overhead is likely to be large relative to the actual execution time. .
Just for a taste, in Python (I'm no php expert) in order to call a C function you must context switch (flush registers), unbox the value into the native type, perform the operatio
Re: (Score:2)
I don't think you understood the question. The question is why PHP build its own implementation of a rather low-level library function that's actually part of the C99 standard. (And I'm pretty sure PHP requires C99 to compile.)
No one's saying people who program in PHP should do anything different. They're saying that PHP itself should do things using standard libraries.
One of the reason standard libraries exist is to get bugs like this being centralized to one location, so they're only fixed once ever.
Re: (Score:2)
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.
A number of languages have their own versions of strtod(), and it's because the system version is often deeply sub-optimal. (Going the other direction is even worse, especially if you want minimal representations of numbers.) Typically, system library authors stop once they've got something that works well enough, whereas other clients of that sort of functionality are much more exposed to it and so care much more about it being optimal. (After all, system library authors tend to think that people don't con
Re: (Score:2)
Yes, because PHP is so widely known as a hard-number-crunching progra
PUSH START TO RICH (Score:2)
FORTRAN is just too damn slow for such things.
Especially when he spends most of his time riching [youtube.com].
Re:Why does this code even exist? (Score:4, Informative)
DoS also needed (Score:2)
To try the bug for yourself: $a = (float) "2.2250738585072011e-308";
Re: (Score:2)
Floating point bugs (Score:2)
Infinite loop seems appropriate (Score:3, Funny)
Very large? (Score:5, Interesting)
Apparently, some journalists need a patch too.
My 2.2250738585072011e-308 cents.
Nope not just you. (Score:2)
And yep TFA did qualify it as the largest subnormal double-precision number. Of course the journalist probably didn't know what that meant.
Re: (Score:2)
Am I the only one to notice that 2.2250738585072011e-308 is not very large?
It depends on what font you display it in.
It is a string, after all.
Re: (Score:2)
Hey! That's the combination to my luggage! (Score:2)
*Now* can we admit PHP sucks? (Score:2, Insightful)
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?
Re: (Score:3)
PHP has namespaces.
Re: (Score:3)
PHP has namespaces.
syntax\\choices\\stupid->agree();
Re: (Score:3, Insightful)
ignorant hypocritical marketeering = the highest level of insight.
slashdot = stagnated.
Re: (Score:2)
I wish I could mod you up. Pretty much everything the OP complained about has been addressed.
Re: (Score:2)
Alternate suggestions? Just curious as I do some PHP scripting for various things.
[John]
Re: (Score:3)
The OP is full of shit. It does have unicode support and does support namespaces. The generalization of the parser I have no idea what he's talking about and == vs. === makes sense if you know what you're comparing.
Re: (Score:2, Informative)
PHP Warning: assert(): Assertion "strlen("£") == 1" failed in /home/ant/nou.php on line 3
Awesome Unicode support there, buddy. Performance of C combined with the user-friendliness of an interpreted high-level language! Oh wait.
Who's full of shit again?
Re: (Score:2, Troll)
PHP Warning: assert(): Assertion "strlen("£") == 1" failed in /home/ant/nou.php on line 3
Awesome Unicode support there, buddy. Performance of C combined with the user-friendliness of an interpreted high-level language! Oh wait.
Who's full of shit again?
Awesome incorrect use of a language while trying to sound smart. If you don't even know how to use a language please refrain from commenting on perceived deficiencies.
?php
mb_internal_encoding('UTF-8');
if (mb_strlen("£") == 1) {
print "lol@op being full of shit\n";
}
Re:*Now* can we admit PHP sucks? (Score:4, Insightful)
"Correct" use of the language is to ignore string functions entirely and use an optional extension, because they don't actually support Unicode. In 2011. Amazing.
You know, C actually has a valid excuse for that sort of thing. But I'm sure you'd rather call people names all day like a retarded skript kiddie, than admit PHP's Unicode handling is ass-backwards and crippled compared to everything else out there.
Re: (Score:2)
Python 2 has Unicode string literals...
$ python ... print "Lawl @ some kid thinking PHP's a real language" ...
Python 2.6.6 (r266:84292, Sep 15 2010, 16:22:56)
[GCC 4.4.5] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> if len(u"£") == 1:
Lawl @ some kid thinking PHP's a real language
And of course, Python 3's strings *default* to Unicode...
$ python3
Python 3.1.2 (release31-maint, Sep 17 2010, 20:27:33)
[GCC 4.4.5] on linux2
Type "help", "copyright", "credits" or
mb_internal_encoding is not defined (Score:2)
mb_internal_encoding('UTF-8');
Fatal error: mb_internal_encoding is not defined because mbstring is not enabled by default [php.net]. And no, you can't install this extension on your hosting company's copy of PHP.
Re: (Score:2)
If you think strlen should return the number of "characters" in Unicode then you are the one that is full of shit.
I assume this is returning the length of the UTF-8 encoding, which is an actually useful value.
Only beginner programmers think "characters" are important. Eventually they will learn, but only after making boneheaded screwups like you just did. Your sort of thinking is why I18N is not working after 20 years of trying.
Re: (Score:3, Insightful)
The only reason to use PHP is if you're scripting in a shared hosting environment where PHP or Perl CGI scripts are the only options available.
If you're not, you should look at either Python or Ruby. Either will be vastly better, along with some less popular choices like Lua, Groovy, Scala, Erlang...
Basically, anything else. It's not that PHP can't be sufficient, it's that it has a long and hideously compromised development history and actually demands far more of you, the scripter, to make it safe and us
Re: (Score:2)
The "excellent design" of Perl?
Good one, AST.
Re: (Score:2)
> *Now* can we admit PHP... ... is perfectly suitable for literally thousands upon thousands of tasks?
In other news, Euclidian geometry cannot correctly describe Mercury's orbit. Therefore the value of everything ever done with this type of math, from the pyramids to Apollo 11, is negated.
THERE IS NO PERFECT LANGUAGE. PHP is 100% good enough for absolutely everything I do day to day, and has been a paying gig for nearly a decade. My job does not require me to perform calculations on very large numbers.
My submission mention the cause of the problem (Score:2)
http://slashdot.org/submission/1435314/DoS-attack-found-in-PHP-thanks-to-x87-FP [slashdot.org]
Comment removed (Score:3)
how does the patch work? (Score:2)
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 [php.net]
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 appe
Re:how does the patch work? (Score:4, Informative)
The x87 registers are all 80 bits long, while standard doubles are only 64 bits. You can get into a situation where two floating point registers contain different values that round to the same double value, yet they don't compare equal. Adding the volatile keyword forces the compiler to copy the registers to the stack and read them back every time they are accessed, truncating them to 64 bits. The patch is only needed on x86 because x86_64 uses SSE3 for floating point, which works with 64-bit floats natively.
Re: (Score:2)
Sounds like a very reasonable explanation and makes sense. But....shouldn't the compiler already know this and pull the variable out of the 80 bit FPU register into a 64 bit double before doing an == comparison between doubles? Seems like this problem would nearly always be the case when doing floating point equality comparisons.
Re: (Score:2)
If you are using memory-mapped IO, the compiler won't know if you are reading from an external device like an FPU or a simple memory location.
This kind of coding is standard for IO libraries. Things like reading values from memory mapped UART registers. A smart compiler will optimize the actual memory access away and rely on the previous read that is has stored in a local register. Without calling the address volatile you can wait all day for the IORDY b
Re: (Score:2)
I understand why you'd use a volatile variable for something that can be touched by an external event or process, but that's not what happened here. I'm talking about this specific case involving the FPU where it was the compiler that put my variable into the FPU register, it didn't happen by some external event that the compiler had no knowledge of.
If the compiler is the one that decided to move my variable into a high precision FPU register, then shouldn't it be smart enough to convert it to the appropria
Re: (Score:2)
Look at this small c function
void fun(double a,double b) {
double c=a*b;
// Misc other code
double d=c*2;
/*
The value of d here may differ based on compiler optimisation, because the representation of the variable c may be either 64bit or 80 bit depending on if the value were written to memory, and then read back or not between Line 1 and Line 3. And both result would be co
Re: (Score:2)
You can get into a situation where two floating point registers contain different values that round to the same double value, yet they don't compare equal
Pretty much every FAQ on the use of floating point types in programming has "do not ever compare two floating point values for equality" in the first 3 items. Why the hell do they need a comparison like that there?
Re: (Score:3)
(2) A partial but simple solution: Do comparisons on volatile variables only.
Hope this has been enlightening!
Re: (Score:2)
I'm too lazy to actually figure out exactly what's happening, but that's most likely correct. The volatile keyword prevents the compiler from doing things like moving values into registers, and the patch mentions that it is a problem with the FPU. I'm guessing that there's some sort of approximation algorithm happening, which stops when the error is sufficiently low. If that value got moved to something with different precision, it could stop converging.
C purists will say that you can look at code and tell
Re: (Score:2)
The volatile keyword prevents the compiler from doing things like moving values into registers,
What "volatile" actually means is that the memory location underlying the variable is able to change without the CPU knowing it and thus not only can the variable not be assigned to a register (which is what the "register" keyword causes), it must be accessed anew each time it is referenced. Thus, code that says something like:
if( x==0 )
do something;
if( x >
You tried it, didn't you? Come on now, admit it! (Score:2)
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?
Re: (Score:2)
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
Non-event. No crash here. (Score:2)
<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
Re: (Score:2)
I thought people who used Perl only spoke in regular expressions?
Re: (Score:3)
Re: (Score:3)
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.
Re: (Score:2)
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.
Re: (Score:2)
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...."