]> granicus.if.org Git - php/commitdiff
Resolve bug #72017
authorThomas Punt <tpunt@hotmail.co.uk>
Fri, 15 Apr 2016 22:13:50 +0000 (23:13 +0100)
committerAnatol Belski <ab@php.net>
Mon, 16 May 2016 17:15:40 +0000 (19:15 +0200)
ext/standard/array.c
ext/standard/tests/array/range_bug72017.phpt [new file with mode: 0644]

index 9e21295d85bb4d9c165e91ea45d5f46b09b8aae4..0800ac017ca3304b8bdfed67233b5b58a2d676ec 100644 (file)
@@ -2104,7 +2104,7 @@ PHP_FUNCTION(array_fill_keys)
                        php_error_docref(NULL, E_WARNING, "The supplied range exceeds the maximum array size: start=%0.0f end=%0.0f", end, start); \
                        RETURN_FALSE; \
                } \
-               size = (uint32_t)__calc_size; \
+               size = (uint32_t)round(__calc_size); \
                array_init_size(return_value, size); \
                zend_hash_real_init(Z_ARRVAL_P(return_value), 1); \
        } while (0)
@@ -2216,7 +2216,7 @@ PHP_FUNCTION(range)
                        zend_hash_next_index_insert_new(Z_ARRVAL_P(return_value), &tmp);
                }
        } else if (Z_TYPE_P(zlow) == IS_DOUBLE || Z_TYPE_P(zhigh) == IS_DOUBLE || is_step_double) {
-               double low, high;
+               double low, high, element;
                uint32_t i, size;
 double_str:
                low = zval_get_double(zlow);
@@ -2237,8 +2237,8 @@ double_str:
                        RANGE_CHECK_DOUBLE_INIT_ARRAY(low, high);
 
                        ZEND_HASH_FILL_PACKED(Z_ARRVAL_P(return_value)) {
-                               for (i = 0; i < size; ++i) {
-                                       Z_DVAL(tmp) = low - (i * step);
+                               for (i = 0; i < size && (element = low - (i * step)) <= low && element >= high; ++i) {
+                                       Z_DVAL(tmp) = element;
                                        ZEND_HASH_FILL_ADD(&tmp);
                                }
                        } ZEND_HASH_FILL_END();
@@ -2251,8 +2251,8 @@ double_str:
                        RANGE_CHECK_DOUBLE_INIT_ARRAY(high, low);
 
                        ZEND_HASH_FILL_PACKED(Z_ARRVAL_P(return_value)) {
-                               for (i = 0; i < size; ++i) {
-                                       Z_DVAL(tmp) = low + (i * step);
+                               for (i = 0; i < size && (element = low + (i * step)) <= high && element >= low; ++i) {
+                                       Z_DVAL(tmp) = element;
                                        ZEND_HASH_FILL_ADD(&tmp);
                                }
                        } ZEND_HASH_FILL_END();
diff --git a/ext/standard/tests/array/range_bug72017.phpt b/ext/standard/tests/array/range_bug72017.phpt
new file mode 100644 (file)
index 0000000..b5a56d7
--- /dev/null
@@ -0,0 +1,17 @@
+--TEST--
+Bug #72017 (incorrect truncation due to floating point precision issue)
+--FILE--
+<?php
+var_dump(range(4.5, 4.2, 0.1));
+?>
+--EXPECT--
+array(4) {
+  [0]=>
+  float(4.5)
+  [1]=>
+  float(4.4)
+  [2]=>
+  float(4.3)
+  [3]=>
+  float(4.2)
+}