From 4ed88343cc51a1d8e14ce633cca26b7d724230dc Mon Sep 17 00:00:00 2001 From: Felipe Pena Date: Mon, 5 Jan 2009 19:47:13 +0000 Subject: [PATCH] - Fixed bug #46701 (Creating associative array with long values in the key fails on 32bit linux) Patch by Shire --- Zend/tests/bug46701.phpt | 42 +++++++++++++++++++++ Zend/zend_execute.c | 6 +-- Zend/zend_operators.c | 36 ------------------ Zend/zend_operators.h | 36 ++++++++++++++++++ Zend/zend_vm_def.h | 4 +- Zend/zend_vm_execute.h | 80 ++++++++++++++++++++++++++++++---------- 6 files changed, 144 insertions(+), 60 deletions(-) create mode 100644 Zend/tests/bug46701.phpt diff --git a/Zend/tests/bug46701.phpt b/Zend/tests/bug46701.phpt new file mode 100644 index 00000000000..d76b810cadf --- /dev/null +++ b/Zend/tests/bug46701.phpt @@ -0,0 +1,42 @@ +--TEST-- +Bug #46701 (Creating associative array with long values in the key fails on 32bit linux) +--SKIPIF-- + +--FILE-- + 1, + 0xce331a00 => 2 +); +$test_array[0xce359000] = 3; + +var_dump($test_array); +var_dump($test_array[0xce331a00]); + +class foo { + public $x; + + public function __construct() { + $this->x[0xce359000] = 3; + var_dump($this->x); + } +} + +new foo; + +?> +--EXPECT-- +array(3) { + [-866368000]=> + int(1) + [-835511808]=> + int(2) + [-835350528]=> + int(3) +} +int(2) +array(1) { + [-835350528]=> + int(3) +} diff --git a/Zend/zend_execute.c b/Zend/zend_execute.c index f87fc483abd..7789e021633 100644 --- a/Zend/zend_execute.c +++ b/Zend/zend_execute.c @@ -938,10 +938,10 @@ fetch_string_dim: efree(offset_key.v); } break; - case IS_DOUBLE: - index = (long)Z_DVAL_P(dim); + case IS_DOUBLE: { + DVAL_TO_LVAL(Z_DVAL_P(dim), index); goto num_index; - + } case IS_RESOURCE: zend_error(E_STRICT, "Resource ID#%ld used as offset, casting to integer (%ld)", Z_LVAL_P(dim), Z_LVAL_P(dim)); /* Fall Through */ diff --git a/Zend/zend_operators.c b/Zend/zend_operators.c index b66e95216cc..b03c441327c 100644 --- a/Zend/zend_operators.c +++ b/Zend/zend_operators.c @@ -268,42 +268,6 @@ ZEND_API int convert_scalar_to_number(zval *op TSRMLS_DC) /* {{{ */ /* }}} */ -/* {{{ DVAL_TO_LVAL */ -#define MAX_UNSIGNED_INT ((double) LONG_MAX * 2) + 1 -#ifdef _WIN64 -# define DVAL_TO_LVAL(d, l) \ - if ((d) > LONG_MAX) { \ - (l) = (long)(unsigned long)(__int64) (d); \ - } else { \ - (l) = (long) (d); \ - } -#elif !defined(_WIN64) && __WORDSIZE == 64 -# define DVAL_TO_LVAL(d, l) \ - if ((d) >= LONG_MAX) { \ - (l) = LONG_MAX; \ - } else if ((d) <= LONG_MIN) { \ - (l) = LONG_MIN; \ - } else {\ - (l) = (long) (d); \ - } -#else -# define DVAL_TO_LVAL(d, l) \ - if ((d) > LONG_MAX) { \ - if ((d) > MAX_UNSIGNED_INT) { \ - (l) = LONG_MAX; \ - } else { \ - (l) = (unsigned long) (d); \ - } \ - } else { \ - if((d) < LONG_MIN) { \ - (l) = LONG_MIN; \ - } else { \ - (l) = (long) (d); \ - } \ - } -#endif -/* }}} */ - /* {{{ zendi_convert_to_long */ #define zendi_convert_to_long(op, holder, result) \ if (op == result) { \ diff --git a/Zend/zend_operators.h b/Zend/zend_operators.h index 1289274403c..5411f46ec78 100644 --- a/Zend/zend_operators.h +++ b/Zend/zend_operators.h @@ -78,6 +78,42 @@ ZEND_API unsigned long zend_u_strtoul(const UChar *nptr, UChar **endptr, int bas ZEND_API double zend_u_strtod(const UChar *nptr, UChar **endptr); END_EXTERN_C() +/* {{{ DVAL_TO_LVAL */ +#define MAX_UNSIGNED_INT ((double) LONG_MAX * 2) + 1 +#ifdef _WIN64 +# define DVAL_TO_LVAL(d, l) \ + if ((d) > LONG_MAX) { \ + (l) = (long)(unsigned long)(__int64) (d); \ + } else { \ + (l) = (long) (d); \ + } +#elif !defined(_WIN64) && __WORDSIZE == 64 +# define DVAL_TO_LVAL(d, l) \ + if ((d) >= LONG_MAX) { \ + (l) = LONG_MAX; \ + } else if ((d) <= LONG_MIN) { \ + (l) = LONG_MIN; \ + } else {\ + (l) = (long) (d); \ + } +#else +# define DVAL_TO_LVAL(d, l) \ + if ((d) > LONG_MAX) { \ + if ((d) > MAX_UNSIGNED_INT) { \ + (l) = LONG_MAX; \ + } else { \ + (l) = (unsigned long) (d); \ + } \ + } else { \ + if((d) < LONG_MIN) { \ + (l) = LONG_MIN; \ + } else { \ + (l) = (long) (d); \ + } \ + } +#endif +/* }}} */ + static inline zend_uchar is_numeric_string(char *str, int length, long *lval, double *dval, int allow_errors) { long local_lval; diff --git a/Zend/zend_vm_def.h b/Zend/zend_vm_def.h index 306b4e6edec..8177ec6b3b8 100644 --- a/Zend/zend_vm_def.h +++ b/Zend/zend_vm_def.h @@ -3150,9 +3150,11 @@ ZEND_VM_HANDLER(72, ZEND_ADD_ARRAY_ELEMENT, CONST|TMP|VAR|CV, CONST|TMP|VAR|UNUS } } if (offset) { + long l; switch (Z_TYPE_P(offset)) { case IS_DOUBLE: - zend_hash_index_update(Z_ARRVAL_P(array_ptr), (long) Z_DVAL_P(offset), &expr_ptr, sizeof(zval *), NULL); + DVAL_TO_LVAL(Z_DVAL_P(offset), l); + zend_hash_index_update(Z_ARRVAL_P(array_ptr), l, &expr_ptr, sizeof(zval *), NULL); break; case IS_LONG: case IS_BOOL: diff --git a/Zend/zend_vm_execute.h b/Zend/zend_vm_execute.h index 4a790d2ac69..6153fbe092c 100644 --- a/Zend/zend_vm_execute.h +++ b/Zend/zend_vm_execute.h @@ -2920,9 +2920,11 @@ static int ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_CONST_CONST_HANDLER(ZEND_O } } if (offset) { + long l; switch (Z_TYPE_P(offset)) { case IS_DOUBLE: - zend_hash_index_update(Z_ARRVAL_P(array_ptr), (long) Z_DVAL_P(offset), &expr_ptr, sizeof(zval *), NULL); + DVAL_TO_LVAL(Z_DVAL_P(offset), l); + zend_hash_index_update(Z_ARRVAL_P(array_ptr), l, &expr_ptr, sizeof(zval *), NULL); break; case IS_LONG: case IS_BOOL: @@ -3453,9 +3455,11 @@ static int ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_CONST_TMP_HANDLER(ZEND_OPC } } if (offset) { + long l; switch (Z_TYPE_P(offset)) { case IS_DOUBLE: - zend_hash_index_update(Z_ARRVAL_P(array_ptr), (long) Z_DVAL_P(offset), &expr_ptr, sizeof(zval *), NULL); + DVAL_TO_LVAL(Z_DVAL_P(offset), l); + zend_hash_index_update(Z_ARRVAL_P(array_ptr), l, &expr_ptr, sizeof(zval *), NULL); break; case IS_LONG: case IS_BOOL: @@ -3933,9 +3937,11 @@ static int ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_CONST_VAR_HANDLER(ZEND_OPC } } if (offset) { + long l; switch (Z_TYPE_P(offset)) { case IS_DOUBLE: - zend_hash_index_update(Z_ARRVAL_P(array_ptr), (long) Z_DVAL_P(offset), &expr_ptr, sizeof(zval *), NULL); + DVAL_TO_LVAL(Z_DVAL_P(offset), l); + zend_hash_index_update(Z_ARRVAL_P(array_ptr), l, &expr_ptr, sizeof(zval *), NULL); break; case IS_LONG: case IS_BOOL: @@ -4137,9 +4143,11 @@ static int ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_CONST_UNUSED_HANDLER(ZEND_ } } if (offset) { + long l; switch (Z_TYPE_P(offset)) { case IS_DOUBLE: - zend_hash_index_update(Z_ARRVAL_P(array_ptr), (long) Z_DVAL_P(offset), &expr_ptr, sizeof(zval *), NULL); + DVAL_TO_LVAL(Z_DVAL_P(offset), l); + zend_hash_index_update(Z_ARRVAL_P(array_ptr), l, &expr_ptr, sizeof(zval *), NULL); break; case IS_LONG: case IS_BOOL: @@ -4616,9 +4624,11 @@ static int ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_CONST_CV_HANDLER(ZEND_OPCO } } if (offset) { + long l; switch (Z_TYPE_P(offset)) { case IS_DOUBLE: - zend_hash_index_update(Z_ARRVAL_P(array_ptr), (long) Z_DVAL_P(offset), &expr_ptr, sizeof(zval *), NULL); + DVAL_TO_LVAL(Z_DVAL_P(offset), l); + zend_hash_index_update(Z_ARRVAL_P(array_ptr), l, &expr_ptr, sizeof(zval *), NULL); break; case IS_LONG: case IS_BOOL: @@ -6285,9 +6295,11 @@ static int ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_TMP_CONST_HANDLER(ZEND_OPC } } if (offset) { + long l; switch (Z_TYPE_P(offset)) { case IS_DOUBLE: - zend_hash_index_update(Z_ARRVAL_P(array_ptr), (long) Z_DVAL_P(offset), &expr_ptr, sizeof(zval *), NULL); + DVAL_TO_LVAL(Z_DVAL_P(offset), l); + zend_hash_index_update(Z_ARRVAL_P(array_ptr), l, &expr_ptr, sizeof(zval *), NULL); break; case IS_LONG: case IS_BOOL: @@ -6758,9 +6770,11 @@ static int ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_TMP_TMP_HANDLER(ZEND_OPCOD } } if (offset) { + long l; switch (Z_TYPE_P(offset)) { case IS_DOUBLE: - zend_hash_index_update(Z_ARRVAL_P(array_ptr), (long) Z_DVAL_P(offset), &expr_ptr, sizeof(zval *), NULL); + DVAL_TO_LVAL(Z_DVAL_P(offset), l); + zend_hash_index_update(Z_ARRVAL_P(array_ptr), l, &expr_ptr, sizeof(zval *), NULL); break; case IS_LONG: case IS_BOOL: @@ -7231,9 +7245,11 @@ static int ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_TMP_VAR_HANDLER(ZEND_OPCOD } } if (offset) { + long l; switch (Z_TYPE_P(offset)) { case IS_DOUBLE: - zend_hash_index_update(Z_ARRVAL_P(array_ptr), (long) Z_DVAL_P(offset), &expr_ptr, sizeof(zval *), NULL); + DVAL_TO_LVAL(Z_DVAL_P(offset), l); + zend_hash_index_update(Z_ARRVAL_P(array_ptr), l, &expr_ptr, sizeof(zval *), NULL); break; case IS_LONG: case IS_BOOL: @@ -7325,9 +7341,11 @@ static int ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_TMP_UNUSED_HANDLER(ZEND_OP } } if (offset) { + long l; switch (Z_TYPE_P(offset)) { case IS_DOUBLE: - zend_hash_index_update(Z_ARRVAL_P(array_ptr), (long) Z_DVAL_P(offset), &expr_ptr, sizeof(zval *), NULL); + DVAL_TO_LVAL(Z_DVAL_P(offset), l); + zend_hash_index_update(Z_ARRVAL_P(array_ptr), l, &expr_ptr, sizeof(zval *), NULL); break; case IS_LONG: case IS_BOOL: @@ -7795,9 +7813,11 @@ static int ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_TMP_CV_HANDLER(ZEND_OPCODE } } if (offset) { + long l; switch (Z_TYPE_P(offset)) { case IS_DOUBLE: - zend_hash_index_update(Z_ARRVAL_P(array_ptr), (long) Z_DVAL_P(offset), &expr_ptr, sizeof(zval *), NULL); + DVAL_TO_LVAL(Z_DVAL_P(offset), l); + zend_hash_index_update(Z_ARRVAL_P(array_ptr), l, &expr_ptr, sizeof(zval *), NULL); break; case IS_LONG: case IS_BOOL: @@ -10981,9 +11001,11 @@ static int ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_VAR_CONST_HANDLER(ZEND_OPC } } if (offset) { + long l; switch (Z_TYPE_P(offset)) { case IS_DOUBLE: - zend_hash_index_update(Z_ARRVAL_P(array_ptr), (long) Z_DVAL_P(offset), &expr_ptr, sizeof(zval *), NULL); + DVAL_TO_LVAL(Z_DVAL_P(offset), l); + zend_hash_index_update(Z_ARRVAL_P(array_ptr), l, &expr_ptr, sizeof(zval *), NULL); break; case IS_LONG: case IS_BOOL: @@ -12825,9 +12847,11 @@ static int ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_VAR_TMP_HANDLER(ZEND_OPCOD } } if (offset) { + long l; switch (Z_TYPE_P(offset)) { case IS_DOUBLE: - zend_hash_index_update(Z_ARRVAL_P(array_ptr), (long) Z_DVAL_P(offset), &expr_ptr, sizeof(zval *), NULL); + DVAL_TO_LVAL(Z_DVAL_P(offset), l); + zend_hash_index_update(Z_ARRVAL_P(array_ptr), l, &expr_ptr, sizeof(zval *), NULL); break; case IS_LONG: case IS_BOOL: @@ -14720,9 +14744,11 @@ static int ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_VAR_VAR_HANDLER(ZEND_OPCOD } } if (offset) { + long l; switch (Z_TYPE_P(offset)) { case IS_DOUBLE: - zend_hash_index_update(Z_ARRVAL_P(array_ptr), (long) Z_DVAL_P(offset), &expr_ptr, sizeof(zval *), NULL); + DVAL_TO_LVAL(Z_DVAL_P(offset), l); + zend_hash_index_update(Z_ARRVAL_P(array_ptr), l, &expr_ptr, sizeof(zval *), NULL); break; case IS_LONG: case IS_BOOL: @@ -15671,9 +15697,11 @@ static int ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_VAR_UNUSED_HANDLER(ZEND_OP } } if (offset) { + long l; switch (Z_TYPE_P(offset)) { case IS_DOUBLE: - zend_hash_index_update(Z_ARRVAL_P(array_ptr), (long) Z_DVAL_P(offset), &expr_ptr, sizeof(zval *), NULL); + DVAL_TO_LVAL(Z_DVAL_P(offset), l); + zend_hash_index_update(Z_ARRVAL_P(array_ptr), l, &expr_ptr, sizeof(zval *), NULL); break; case IS_LONG: case IS_BOOL: @@ -17231,9 +17259,11 @@ static int ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_VAR_CV_HANDLER(ZEND_OPCODE } } if (offset) { + long l; switch (Z_TYPE_P(offset)) { case IS_DOUBLE: - zend_hash_index_update(Z_ARRVAL_P(array_ptr), (long) Z_DVAL_P(offset), &expr_ptr, sizeof(zval *), NULL); + DVAL_TO_LVAL(Z_DVAL_P(offset), l); + zend_hash_index_update(Z_ARRVAL_P(array_ptr), l, &expr_ptr, sizeof(zval *), NULL); break; case IS_LONG: case IS_BOOL: @@ -25320,9 +25350,11 @@ static int ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_CV_CONST_HANDLER(ZEND_OPCO } } if (offset) { + long l; switch (Z_TYPE_P(offset)) { case IS_DOUBLE: - zend_hash_index_update(Z_ARRVAL_P(array_ptr), (long) Z_DVAL_P(offset), &expr_ptr, sizeof(zval *), NULL); + DVAL_TO_LVAL(Z_DVAL_P(offset), l); + zend_hash_index_update(Z_ARRVAL_P(array_ptr), l, &expr_ptr, sizeof(zval *), NULL); break; case IS_LONG: case IS_BOOL: @@ -27042,9 +27074,11 @@ static int ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_CV_TMP_HANDLER(ZEND_OPCODE } } if (offset) { + long l; switch (Z_TYPE_P(offset)) { case IS_DOUBLE: - zend_hash_index_update(Z_ARRVAL_P(array_ptr), (long) Z_DVAL_P(offset), &expr_ptr, sizeof(zval *), NULL); + DVAL_TO_LVAL(Z_DVAL_P(offset), l); + zend_hash_index_update(Z_ARRVAL_P(array_ptr), l, &expr_ptr, sizeof(zval *), NULL); break; case IS_LONG: case IS_BOOL: @@ -28814,9 +28848,11 @@ static int ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_CV_VAR_HANDLER(ZEND_OPCODE } } if (offset) { + long l; switch (Z_TYPE_P(offset)) { case IS_DOUBLE: - zend_hash_index_update(Z_ARRVAL_P(array_ptr), (long) Z_DVAL_P(offset), &expr_ptr, sizeof(zval *), NULL); + DVAL_TO_LVAL(Z_DVAL_P(offset), l); + zend_hash_index_update(Z_ARRVAL_P(array_ptr), l, &expr_ptr, sizeof(zval *), NULL); break; case IS_LONG: case IS_BOOL: @@ -29649,9 +29685,11 @@ static int ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_CV_UNUSED_HANDLER(ZEND_OPC } } if (offset) { + long l; switch (Z_TYPE_P(offset)) { case IS_DOUBLE: - zend_hash_index_update(Z_ARRVAL_P(array_ptr), (long) Z_DVAL_P(offset), &expr_ptr, sizeof(zval *), NULL); + DVAL_TO_LVAL(Z_DVAL_P(offset), l); + zend_hash_index_update(Z_ARRVAL_P(array_ptr), l, &expr_ptr, sizeof(zval *), NULL); break; case IS_LONG: case IS_BOOL: @@ -31090,9 +31128,11 @@ static int ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_CV_CV_HANDLER(ZEND_OPCODE_ } } if (offset) { + long l; switch (Z_TYPE_P(offset)) { case IS_DOUBLE: - zend_hash_index_update(Z_ARRVAL_P(array_ptr), (long) Z_DVAL_P(offset), &expr_ptr, sizeof(zval *), NULL); + DVAL_TO_LVAL(Z_DVAL_P(offset), l); + zend_hash_index_update(Z_ARRVAL_P(array_ptr), l, &expr_ptr, sizeof(zval *), NULL); break; case IS_LONG: case IS_BOOL: