Browse Source

merged branch eriksencosta/issue-4718 (PR #4794)

Commits
-------

28f002d [Locale] fixed bug on the parsing of TYPE_INT64 integers in 32 bit and 64 bit environments, caused by PHP bug fix :) (closes #4718)

Discussion
----------

[Locale] fixed bug on the parsing of TYPE_INT64 integers in 32 bit and 64 bit environments, caused by PHP bug fix

Bug fix: yes
Feature addition: no
Backwards compatibility break: no
Symfony2 tests pass: yes
Fixes the following tickets: #4718
License of the code: MIT

[![Build Status](https://secure.travis-ci.org/eriksencosta/symfony.png?branch=issue-4718)](http://travis-ci.org/eriksencosta/symfony)

Tests pass on PHP 5.3.3, 5.3.14 and 5.4.4 with ICU 4.2, 4.4 and 4.6 on 32 and 64 bit environments.
Fabien Potencier 13 năm trước cách đây
mục cha
commit
fd1d5e8c10

+ 26 - 2
src/Symfony/Component/Locale/Stub/StubNumberFormatter.php

@@ -819,6 +819,8 @@ class StubNumberFormatter
      * @param mixed $value The value to be converted
      *
      * @return int|float       The converted value
+     *
+     * @see https://bugs.php.net/bug.php?id=59597 Bug #59597
      */
     private function getInt64Value($value)
     {
@@ -827,11 +829,33 @@ class StubNumberFormatter
         }
 
         if (PHP_INT_SIZE !== 8 && ($value > self::$int32Range['positive'] || $value <= self::$int32Range['negative'])) {
+            // Bug #59597 was fixed on PHP 5.3.14 and 5.4.4
+            // The negative PHP_INT_MAX was being converted to float
+            if (
+                $value == self::$int32Range['negative'] &&
+                (
+                    (version_compare(PHP_VERSION, '5.4.0', '<') && version_compare(PHP_VERSION, '5.3.14', '>=')) ||
+                    version_compare(PHP_VERSION, '5.4.4', '>=')
+                )
+            ) {
+                return (int) $value;
+            }
+
             return (float) $value;
         }
 
-        if (PHP_INT_SIZE === 8 && ($value > self::$int32Range['positive'] || $value < self::$int32Range['negative'])) {
-            $value = (-2147483648 - ($value % -2147483648)) * ($value / abs($value));
+        if (PHP_INT_SIZE === 8) {
+            // Bug #59597 was fixed on PHP 5.3.14 and 5.4.4
+            // A 32 bit integer was being generated instead of a 64 bit integer
+            if (
+                  ($value > self::$int32Range['positive'] || $value < self::$int32Range['negative']) &&
+                  (
+                      (version_compare(PHP_VERSION, '5.3.14', '<')) ||
+                      (version_compare(PHP_VERSION, '5.4.0', '>=') && version_compare(PHP_VERSION, '5.4.4', '<'))
+                  )
+            ) {
+                $value = (-2147483648 - ($value % -2147483648)) * ($value / abs($value));
+            }
         }
 
         return (int) $value;

+ 70 - 10
tests/Symfony/Tests/Component/Locale/Stub/StubNumberFormatterTest.php

@@ -806,10 +806,20 @@ class StubNumberFormatterTest extends LocaleTestCase
         $this->assertInternalType('integer', $parsedValue);
         $this->assertEquals(2147483647, $parsedValue);
 
-        // Look that the parsing of '-2,147,483,648' results in a float like the literal -2147483648
         $parsedValue = $formatter->parse('-2,147,483,648', \NumberFormatter::TYPE_INT64);
-        $this->assertInternalType('float', $parsedValue);
-        $this->assertEquals(((float) -2147483647 - 1), $parsedValue);
+
+        // Bug #59597 was fixed on PHP 5.3.14 and 5.4.4
+        // The negative PHP_INT_MAX was being converted to float
+        if (
+            (version_compare(PHP_VERSION, '5.4.0', '<') && version_compare(PHP_VERSION, '5.3.14', '>=')) ||
+            version_compare(PHP_VERSION, '5.4.4', '>=')
+        ) {
+            $this->assertInternalType('int', $parsedValue);
+        } else {
+            $this->assertInternalType('float', $parsedValue);
+        }
+
+        $this->assertEquals(-2147483648, $parsedValue);
     }
 
     public function testParseTypeInt64StubWith32BitIntegerInPhp64Bit()
@@ -857,11 +867,31 @@ class StubNumberFormatterTest extends LocaleTestCase
 
         $parsedValue = $formatter->parse('2,147,483,648', \NumberFormatter::TYPE_INT64);
         $this->assertInternalType('integer', $parsedValue);
-        $this->assertEquals(-2147483647 - 1, $parsedValue, '->parse() TYPE_INT64 does not use true 64 bit integers, using only the 32 bit range.');
+
+        // Bug #59597 was fixed on PHP 5.3.14 and 5.4.4
+        // A 32 bit integer was being generated instead of a 64 bit integer
+        if (
+            (version_compare(PHP_VERSION, '5.3.14', '<')) ||
+            (version_compare(PHP_VERSION, '5.4.0', '>=') && version_compare(PHP_VERSION, '5.4.4', '<'))
+        ) {
+            $this->assertEquals(-2147483648, $parsedValue, '->parse() TYPE_INT64 does not use true 64 bit integers, using only the 32 bit range (PHP < 5.3.14 and PHP < 5.4.4).');
+        } else {
+            $this->assertEquals(2147483648, $parsedValue, '->parse() TYPE_INT64 uses true 64 bit integers (PHP >= 5.3.14 and PHP >= 5.4.4).');
+        }
 
         $parsedValue = $formatter->parse('-2,147,483,649', \NumberFormatter::TYPE_INT64);
         $this->assertInternalType('integer', $parsedValue);
-        $this->assertEquals(2147483647, $parsedValue, '->parse() TYPE_INT64 does not use true 64 bit integers, using only the 32 bit range.');
+
+        // Bug #59597 was fixed on PHP 5.3.14 and 5.4.4
+        // A 32 bit integer was being generated instead of a 64 bit integer
+        if (
+            (version_compare(PHP_VERSION, '5.3.14', '<')) ||
+            (version_compare(PHP_VERSION, '5.4.0', '>=') && version_compare(PHP_VERSION, '5.4.4', '<'))
+        ) {
+            $this->assertEquals(2147483647, $parsedValue, '->parse() TYPE_INT64 does not use true 64 bit integers, using only the 32 bit range  (PHP < 5.3.14 and PHP < 5.4.4).');
+        } else {
+            $this->assertEquals(-2147483649, $parsedValue, '->parse() TYPE_INT64 uses true 64 bit integers (PHP >= 5.3.14 and PHP >= 5.4.4).');
+        }
     }
 
     // Intl Tests
@@ -877,10 +907,20 @@ class StubNumberFormatterTest extends LocaleTestCase
         $this->assertInternalType('integer', $parsedValue);
         $this->assertEquals(2147483647, $parsedValue);
 
-        // Look that the parsing of '-2,147,483,648' results in a float like the literal -2147483648
         $parsedValue = $formatter->parse('-2,147,483,648', \NumberFormatter::TYPE_INT64);
-        $this->assertInternalType('float', $parsedValue);
-        $this->assertEquals(((float) -2147483647 - 1), $parsedValue);
+
+        // Bug #59597 was fixed on PHP 5.3.14 and 5.4.4
+        // The negative PHP_INT_MAX was being converted to float.
+        if (
+            (version_compare(PHP_VERSION, '5.4.0', '<') && version_compare(PHP_VERSION, '5.3.14', '>=')) ||
+            version_compare(PHP_VERSION, '5.4.4', '>=')
+        ) {
+            $this->assertInternalType('int', $parsedValue);
+        } else {
+            $this->assertInternalType('float', $parsedValue);
+        }
+
+        $this->assertEquals(-2147483648, $parsedValue);
     }
 
     public function testParseTypeInt64IntlWith32BitIntegerInPhp64Bit()
@@ -931,11 +971,31 @@ class StubNumberFormatterTest extends LocaleTestCase
 
         $parsedValue = $formatter->parse('2,147,483,648', \NumberFormatter::TYPE_INT64);
         $this->assertInternalType('integer', $parsedValue);
-        $this->assertEquals(-2147483647 - 1, $parsedValue, '->parse() TYPE_INT64 does not use true 64 bit integers, using only the 32 bit range.');
+
+        // Bug #59597 was fixed on PHP 5.3.14 and 5.4.4
+        // A 32 bit integer was being generated instead of a 64 bit integer
+        if (
+            (version_compare(PHP_VERSION, '5.3.14', '<')) ||
+            (version_compare(PHP_VERSION, '5.4.0', '>=') && version_compare(PHP_VERSION, '5.4.4', '<'))
+        ) {
+            $this->assertEquals(-2147483648, $parsedValue, '->parse() TYPE_INT64 does not use true 64 bit integers, using only the 32 bit range (PHP < 5.3.14 and PHP < 5.4.4).');
+        } else {
+            $this->assertEquals(2147483648, $parsedValue, '->parse() TYPE_INT64 uses true 64 bit integers (PHP >= 5.3.14 and PHP >= 5.4.4).');
+        }
 
         $parsedValue = $formatter->parse('-2,147,483,649', \NumberFormatter::TYPE_INT64);
         $this->assertInternalType('integer', $parsedValue);
-        $this->assertEquals(2147483647, $parsedValue, '->parse() TYPE_INT64 does not use true 64 bit integers, using only the 32 bit range.');
+
+        // Bug #59597 was fixed on PHP 5.3.14 and 5.4.4
+        // A 32 bit integer was being generated instead of a 64 bit integer
+        if (
+            (version_compare(PHP_VERSION, '5.3.14', '<')) ||
+            (version_compare(PHP_VERSION, '5.4.0', '>=') && version_compare(PHP_VERSION, '5.4.4', '<'))
+        ) {
+            $this->assertEquals(2147483647, $parsedValue, '->parse() TYPE_INT64 does not use true 64 bit integers, using only the 32 bit range  (PHP < 5.3.14 and PHP < 5.4.4).');
+        } else {
+            $this->assertEquals(-2147483649, $parsedValue, '->parse() TYPE_INT64 uses true 64 bit integers (PHP >= 5.3.14 and PHP >= 5.4.4).');
+        }
     }
 
     /**