PHP is Bit by the Y-2.2250738585072011e-308 Bug

On January 3rd, 2011 Rick Regan reported on his blog Exploring Binary that the following statement causes PHP to hang in an infinite loop.

               <?php $d = '2.2250738585072011e-308'; echo $d; ?>

The problem occurred when the string '2.2250738585072011e-308' is converted to a double precision floating point number in a subroutine named zend_strtod().  The code takes a string that represents a floating point number and tries to return the nearest double precision floating point number.  A standard double precision floating point number is 64 bits wide: 1 bit for the sign, 11 bits for the exponent, and 52 bits for the fractional part.  The problem number written as a hexadecimal floating point constant looks like 0x0FFFFFFFFFFFFFp-1022.  This means the number is almost the smallest number that can be represented in 64 bits that is close to zero without being zero and the fractional part is all 1’s.  The routine zend_strtod() works by converting the string into an approximate floating point number and then tries to refine the approximation in successive loops.  The problem comes when the routine uses the 80 bit floating point registers in most Intel processors.  The 80 bit floating point registers are a legacy from the 8087 Floating Point Coprocessor that Intel introduced in 1980.  With the wider 80 bit hardware registers, the processor can represent more values between the problem number and zero.  The unwanted precision ended up causing the routine to loop endlessly trying to refine the approximate floating point number.  This “unwanted precision” has been at the root of many floating point bugs and it’s likely to show up again in other programs and operating system libraries. [more]

The solution chosen by the PHP committers was to mark the variables used in the refinement to be “volatile”. This causes the compiler to keep the values in memory and not use the hardware registers for comparison or arithmetic operations.

This bug has been fixed in PHP version 5.3.5 and 5.2.17 on January 6th, 2011.  Here is a link to a test script to determine if your version of PHP is affected by this bug

Security and Compliance PHP