From f8689552a4c7b210bbfef59a4a74dfb34bf809c4 Mon Sep 17 00:00:00 2001 From: Felipe Pena Date: Mon, 5 Jan 2009 20:31:54 +0000 Subject: [PATCH] MFH: - 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 | 34 ----------------- Zend/zend_operators.h | 34 +++++++++++++++++ Zend/zend_vm_def.h | 4 +- Zend/zend_vm_execute.h | 80 ++++++++++++++++++++++++++++++---------- 6 files changed, 142 insertions(+), 58 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 0000000000..d76b810cad --- /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 5726ea6081..86c4c8cf6c 100644 --- a/Zend/zend_execute.c +++ b/Zend/zend_execute.c @@ -837,10 +837,10 @@ fetch_string_dim: } } 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 c125525dce..57e4e7f5ab 100644 --- a/Zend/zend_operators.c +++ b/Zend/zend_operators.c @@ -211,40 +211,6 @@ ZEND_API void convert_scalar_to_number(zval *op TSRMLS_DC) } \ } -#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 - #define zendi_convert_to_long(op, holder, result) \ if (op == result) { \ diff --git a/Zend/zend_operators.h b/Zend/zend_operators.h index 523f04deb9..19f3a32461 100644 --- a/Zend/zend_operators.h +++ b/Zend/zend_operators.h @@ -75,6 +75,40 @@ ZEND_API zend_bool instanceof_function_ex(const zend_class_entry *instance_ce, c ZEND_API zend_bool instanceof_function(const zend_class_entry *instance_ce, const zend_class_entry *ce TSRMLS_DC); END_EXTERN_C() +#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 + #define ZEND_IS_DIGIT(c) ((c) >= '0' && (c) <= '9') #define ZEND_IS_XDIGIT(c) (((c) >= 'A' && (c) <= 'F') || ((c) >= 'a' && (c) <= 'f')) diff --git a/Zend/zend_vm_def.h b/Zend/zend_vm_def.h index 4c166a8009..aa44574b37 100644 --- a/Zend/zend_vm_def.h +++ b/Zend/zend_vm_def.h @@ -3065,9 +3065,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 54ce1cdd87..3c7b0ca9f2 100644 --- a/Zend/zend_vm_execute.h +++ b/Zend/zend_vm_execute.h @@ -2820,9 +2820,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: @@ -3338,9 +3340,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: @@ -3807,9 +3811,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: @@ -4000,9 +4006,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: @@ -4468,9 +4476,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: @@ -6015,9 +6025,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: @@ -6481,9 +6493,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: @@ -6947,9 +6961,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: @@ -7040,9 +7056,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: @@ -7503,9 +7521,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: @@ -10511,9 +10531,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: @@ -12287,9 +12309,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: @@ -14114,9 +14138,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: @@ -15002,9 +15028,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: @@ -16547,9 +16575,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: @@ -24198,9 +24228,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: @@ -25862,9 +25894,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: @@ -27576,9 +27610,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: @@ -28358,9 +28394,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: @@ -29794,9 +29832,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: -- 2.50.1