mirror of
https://github.com/php/php-src.git
synced 2026-03-24 08:12:21 +01:00
re-apply patch for github PR #1695
This commit is contained in:
committed by
Anatol Belski
parent
f53a5dcca3
commit
3bbcd84e2f
@@ -81,8 +81,6 @@
|
||||
#define INTERSECT_COMP_DATA_USER 1
|
||||
#define INTERSECT_COMP_KEY_INTERNAL 0
|
||||
#define INTERSECT_COMP_KEY_USER 1
|
||||
|
||||
#define DOUBLE_DRIFT_FIX 0.000000000000001
|
||||
/* }}} */
|
||||
|
||||
ZEND_DECLARE_MODULE_GLOBALS(array)
|
||||
@@ -2061,13 +2059,25 @@ PHP_FUNCTION(array_fill_keys)
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
#define RANGE_CHECK_INIT_ARRAY(start, end) do { \
|
||||
#define RANGE_CHECK_DOUBLE_INIT_ARRAY(start, end) do { \
|
||||
double __calc_size = ((start - end) / step) + 1; \
|
||||
if (fabs(__calc_size) >= (double)HT_MAX_SIZE) { \
|
||||
php_error_docref(NULL, E_WARNING, "The supplied range exceeds the maximum array size: start=%0.0f end=%0.0f", start > end ? end : start, start > end ? start : end); \
|
||||
if (__calc_size >= (double)HT_MAX_SIZE) { \
|
||||
php_error_docref(NULL, E_WARNING, "The supplied range exceeds the maximum array size: start=%0.0f end=%0.0f", end, start); \
|
||||
RETURN_FALSE; \
|
||||
} \
|
||||
array_init_size(return_value, (uint32_t)fabs(__calc_size)); \
|
||||
size = (uint32_t)__calc_size; \
|
||||
array_init_size(return_value, size); \
|
||||
zend_hash_real_init(Z_ARRVAL_P(return_value), 1); \
|
||||
} while (0)
|
||||
|
||||
#define RANGE_CHECK_LONG_INIT_ARRAY(start, end) do { \
|
||||
zend_ulong __calc_size = (start - end) / lstep; \
|
||||
if (__calc_size >= HT_MAX_SIZE - 1) { \
|
||||
php_error_docref(NULL, E_WARNING, "The supplied range exceeds the maximum array size: start=%pd end=%pd", end, start); \
|
||||
RETURN_FALSE; \
|
||||
} \
|
||||
size = (uint32_t)(__calc_size + 1); \
|
||||
array_init_size(return_value, size); \
|
||||
zend_hash_real_init(Z_ARRVAL_P(return_value), 1); \
|
||||
} while (0)
|
||||
|
||||
@@ -2167,12 +2177,11 @@ 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, value;
|
||||
zend_long i;
|
||||
double low, high;
|
||||
uint32_t i, size;
|
||||
double_str:
|
||||
low = zval_get_double(zlow);
|
||||
high = zval_get_double(zhigh);
|
||||
i = 0;
|
||||
|
||||
if (zend_isinf(high) || zend_isinf(low)) {
|
||||
php_error_docref(NULL, E_WARNING, "Invalid range supplied: start=%0.0f end=%0.0f", low, high);
|
||||
@@ -2186,12 +2195,13 @@ double_str:
|
||||
goto err;
|
||||
}
|
||||
|
||||
RANGE_CHECK_INIT_ARRAY(low, high);
|
||||
RANGE_CHECK_DOUBLE_INIT_ARRAY(low, high);
|
||||
|
||||
ZEND_HASH_FILL_PACKED(Z_ARRVAL_P(return_value)) {
|
||||
for (value = low; value >= (high - DOUBLE_DRIFT_FIX); value = low - (++i * step)) {
|
||||
Z_DVAL(tmp) = value;
|
||||
ZEND_HASH_FILL_ADD(&tmp);
|
||||
}
|
||||
for (i = 0; i < size; ++i) {
|
||||
Z_DVAL(tmp) = low - (i * step);
|
||||
ZEND_HASH_FILL_ADD(&tmp);
|
||||
}
|
||||
} ZEND_HASH_FILL_END();
|
||||
} else if (high > low) { /* Positive steps */
|
||||
if (high - low < step || step <= 0) {
|
||||
@@ -2199,10 +2209,11 @@ double_str:
|
||||
goto err;
|
||||
}
|
||||
|
||||
RANGE_CHECK_INIT_ARRAY(high, low);
|
||||
RANGE_CHECK_DOUBLE_INIT_ARRAY(high, low);
|
||||
|
||||
ZEND_HASH_FILL_PACKED(Z_ARRVAL_P(return_value)) {
|
||||
for (value = low; value <= (high + DOUBLE_DRIFT_FIX); value = low + (++i * step)) {
|
||||
Z_DVAL(tmp) = value;
|
||||
for (i = 0; i < size; ++i) {
|
||||
Z_DVAL(tmp) = low + (i * step);
|
||||
ZEND_HASH_FILL_ADD(&tmp);
|
||||
}
|
||||
} ZEND_HASH_FILL_END();
|
||||
@@ -2212,43 +2223,53 @@ double_str:
|
||||
zend_hash_next_index_insert_new(Z_ARRVAL_P(return_value), &tmp);
|
||||
}
|
||||
} else {
|
||||
double low, high;
|
||||
zend_long lstep;
|
||||
zend_long low, high;
|
||||
/* lstep is a ulong so that comparisons to it don't overflow, i.e. low - high < lstep */
|
||||
zend_ulong lstep;
|
||||
uint32_t i, size;
|
||||
long_str:
|
||||
low = zval_get_double(zlow);
|
||||
high = zval_get_double(zhigh);
|
||||
lstep = (zend_long) step;
|
||||
low = zval_get_long(zlow);
|
||||
high = zval_get_long(zhigh);
|
||||
|
||||
if (step <= 0) {
|
||||
err = 1;
|
||||
goto err;
|
||||
}
|
||||
|
||||
lstep = step;
|
||||
|
||||
Z_TYPE_INFO(tmp) = IS_LONG;
|
||||
if (low > high) { /* Negative steps */
|
||||
if (low - high < lstep || lstep <= 0) {
|
||||
if (low - high < lstep) {
|
||||
err = 1;
|
||||
goto err;
|
||||
}
|
||||
|
||||
RANGE_CHECK_INIT_ARRAY(low, high);
|
||||
RANGE_CHECK_LONG_INIT_ARRAY(low, high);
|
||||
|
||||
ZEND_HASH_FILL_PACKED(Z_ARRVAL_P(return_value)) {
|
||||
for (; low >= high; low -= lstep) {
|
||||
Z_LVAL(tmp) = (zend_long)low;
|
||||
for (i = 0; i < size; ++i) {
|
||||
Z_LVAL(tmp) = low - (i * lstep);
|
||||
ZEND_HASH_FILL_ADD(&tmp);
|
||||
}
|
||||
} ZEND_HASH_FILL_END();
|
||||
} else if (high > low) { /* Positive steps */
|
||||
if (high - low < lstep || lstep <= 0) {
|
||||
if (high - low < lstep) {
|
||||
err = 1;
|
||||
goto err;
|
||||
}
|
||||
|
||||
RANGE_CHECK_INIT_ARRAY(high, low);
|
||||
RANGE_CHECK_LONG_INIT_ARRAY(high, low);
|
||||
|
||||
ZEND_HASH_FILL_PACKED(Z_ARRVAL_P(return_value)) {
|
||||
for (; low <= high; low += lstep) {
|
||||
Z_LVAL(tmp) = (zend_long)low;
|
||||
for (i = 0; i < size; ++i) {
|
||||
Z_LVAL(tmp) = low + (i * lstep);
|
||||
ZEND_HASH_FILL_ADD(&tmp);
|
||||
}
|
||||
} ZEND_HASH_FILL_END();
|
||||
} else {
|
||||
array_init(return_value);
|
||||
Z_LVAL(tmp) = (zend_long)low;
|
||||
Z_LVAL(tmp) = low;
|
||||
zend_hash_next_index_insert_new(Z_ARRVAL_P(return_value), &tmp);
|
||||
}
|
||||
}
|
||||
@@ -2260,7 +2281,8 @@ err:
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
#undef RANGE_CHECK_INIT_ARRAY
|
||||
#undef RANGE_CHECK_DOUBLE_INIT_ARRAY
|
||||
#undef RANGE_CHECK_LONG_INIT_ARRAY
|
||||
|
||||
static void php_array_data_shuffle(zval *array) /* {{{ */
|
||||
{
|
||||
|
||||
10
ext/standard/tests/array/range_bug71132.phpt
Normal file
10
ext/standard/tests/array/range_bug71132.phpt
Normal file
@@ -0,0 +1,10 @@
|
||||
--TEST--
|
||||
Bug #71132 (range function produces 2 segfaults with long integers)
|
||||
--FILE--
|
||||
<?php
|
||||
var_dump(count(range(PHP_INT_MIN + 513, PHP_INT_MIN)));
|
||||
var_dump(count(range(PHP_INT_MIN, PHP_INT_MIN + 513)));
|
||||
?>
|
||||
--EXPECT--
|
||||
int(514)
|
||||
int(514)
|
||||
8
ext/standard/tests/array/range_bug71197.phpt
Normal file
8
ext/standard/tests/array/range_bug71197.phpt
Normal file
@@ -0,0 +1,8 @@
|
||||
--TEST--
|
||||
Bug #71197 (range function produces another 2 segfaults with long integers)
|
||||
--FILE--
|
||||
<?php
|
||||
range(PHP_INT_MIN, PHP_INT_MIN + 513, .01);
|
||||
range(PHP_INT_MIN + 513, PHP_INT_MIN, .01);
|
||||
?>
|
||||
--EXPECT--
|
||||
Reference in New Issue
Block a user