PHP hangs on numeric value 2.2250738585072011e-308

If you’re running PHP on a 32-bit system, you’ll need make sure that your install has been compiled with the -ffloat-store flag. Otherwise, the PHP process will enter an infinite loop when you try to perform mathematic operations on the floating number 2.2250738585072011e-308.

It’s been noticed lately, that when asked to perform mathematic operations on a very specific number (2.2250738585072011e-308 to be precise), PHP throws itself into an infinite loop.

tl;dr: If you’re running PHP on a 32-bit system, you’ll need make sure that your install has been compiled with the -ffloat-store flag. Otherwise, the PHP process will enter an infinite loop when you try to perform mathematic operations on the floating number 2.2250738585072011e-308.

According to Rick Regan (who posted the initial observation): (source)

2.2250738585072011e-308 represents the largest subnormal double-precision floating-point number; written as a hexadecimal floating-point constant, it’s 0x0.fffffffffffffp-1022. 2.2250738585072011e-308 is one of five 17-digit decimal values that convert (correctly) to 0x0.fffffffffffffp-1022:

2.2250738585072007e-308
2.2250738585072008e-308
2.2250738585072009e-308
2.2250738585072010e-308
2.2250738585072011e-308
Only 2.2250738585072011e-308 causes the problem. It happens to be the largest of the five decimal values, so I guess that matters somehow.

The PHP hacker community was quick to notice, and shortly after the article was posted had tracked down both the reason behind the errant behaviour, as well as the conditions under which said flaw exposes itself: (source)

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, calculate 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.

Luckily my server here wasn’t affected.