1
0
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:
Thomas Punt
2016-01-12 07:07:51 +01:00
committed by Anatol Belski
parent f53a5dcca3
commit 3bbcd84e2f
3 changed files with 72 additions and 32 deletions

View File

@@ -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) /* {{{ */
{

View 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)

View 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--