diff options
author | Rudi Theunissen <rudolf.theunissen@gmail.com> | 2018-06-28 18:56:30 -0400 |
---|---|---|
committer | Nikita Popov <nikita.ppv@gmail.com> | 2018-07-02 16:41:59 +0200 |
commit | 30156d588c07e26d4e752ddb62344e96854d4773 (patch) | |
tree | 569af90625c7a0397f444cb871172fa77a153da9 /Zend | |
parent | 6d61814d0e2115b834b1e6cbc27c6b05299b3e7a (diff) | |
download | php-git-30156d588c07e26d4e752ddb62344e96854d4773.tar.gz |
Fixed bug #63217
Don't automatically convert literal string keys to integers on
array access, as we may be dealing with an ArrayAccess object,
rather than a plain array.
Diffstat (limited to 'Zend')
-rw-r--r-- | Zend/tests/bug29883.phpt | 14 | ||||
-rw-r--r-- | Zend/tests/bug55135.phpt | 2 | ||||
-rw-r--r-- | Zend/tests/bug63217.phpt | 123 | ||||
-rw-r--r-- | Zend/tests/empty_str_offset.phpt | 26 | ||||
-rw-r--r-- | Zend/tests/isset_str_offset.phpt | 26 | ||||
-rw-r--r-- | Zend/zend_compile.c | 1 | ||||
-rw-r--r-- | Zend/zend_execute.c | 6 | ||||
-rw-r--r-- | Zend/zend_vm_def.h | 12 | ||||
-rw-r--r-- | Zend/zend_vm_execute.h | 90 |
9 files changed, 214 insertions, 86 deletions
diff --git a/Zend/tests/bug29883.phpt b/Zend/tests/bug29883.phpt index b6ad99aeaf..4e07b02d10 100644 --- a/Zend/tests/bug29883.phpt +++ b/Zend/tests/bug29883.phpt @@ -4,10 +4,18 @@ Bug #29883 (isset gives invalid values on strings) <?php $x = "bug"; var_dump(isset($x[-10])); +var_dump(isset($x[1])); var_dump(isset($x["1"])); -echo $x["1"]."\n"; +var_dump($x[-10])."\n"; +var_dump($x[1])."\n"; +var_dump($x["1"])."\n"; ?> ---EXPECT-- +--EXPECTF-- bool(false) bool(true) -u +bool(true) + +Notice: Uninitialized string offset: -10 in %s on line 6 +string(0) "" +string(1) "u" +string(1) "u" diff --git a/Zend/tests/bug55135.phpt b/Zend/tests/bug55135.phpt index f6d0aafaca..a1ffff21f9 100644 --- a/Zend/tests/bug55135.phpt +++ b/Zend/tests/bug55135.phpt @@ -19,7 +19,7 @@ unset($array[1]); print_r($array); $array = array(1 => 2); -$a = 1; + unset($array["1"]); print_r($array); ?> diff --git a/Zend/tests/bug63217.phpt b/Zend/tests/bug63217.phpt new file mode 100644 index 0000000000..ca9b900166 --- /dev/null +++ b/Zend/tests/bug63217.phpt @@ -0,0 +1,123 @@ +--TEST-- +Bug #63217 (Constant numeric strings become integers when used as ArrayAccess offset) +--INI-- +opcache.enable_cli=1 +opcache.enable=1 +opcache.optimization_level=-1 +--FILE-- +<?php +class Test implements ArrayAccess { + public function offsetExists($offset) { + echo "offsetExists given "; + var_dump($offset); + } + public function offsetUnset($offset) { + echo "offsetUnset given "; + var_dump($offset); + } + public function offsetSet($offset, $value) { + echo "offsetSet given "; + var_dump($offset); + } + public function offsetGet($offset) { + echo "offsetGet given "; + var_dump($offset); + } +} + +$test = new Test; + +/* These should all produce string(...) "..." output and not int(...) */ +isset($test['0']); +isset($test['123']); +unset($test['0']); +unset($test['123']); +$test['0'] = true; +$test['123'] = true; +$foo = $test['0']; +$foo = $test['123']; + +/* These caused the same bug, but in opcache rather than the compiler */ +isset($test[(string)'0']); +isset($test[(string)'123']); +unset($test[(string)'0']); +unset($test[(string)'123']); +$test[(string)'0'] = true; +$test[(string)'123'] = true; +$foo = $test[(string)'0']; +$foo = $test[(string)'123']; + +/** + * @see https://github.com/php/php-src/pull/2607#issuecomment-313781748 + */ +function test(): string { + $array["10"] = 42; + foreach ($array as $key => $value) { + return $key; + } +} + +var_dump(test()); + +/** + * Make sure we don't break arrays. + */ +$array = []; + +$key = '123'; + +$array[$key] = 1; +$array['321'] = 2; +$array['abc'] = 3; + +var_dump($array); + +/** + * Make sure that we haven't broken ArrayObject + */ +$ao = new ArrayObject(); + +$key = '123'; + +$ao = []; +$ao[$key] = 1; +$ao['321'] = 2; +$ao['abc'] = 3; + +var_dump($ao); + +?> +--EXPECT-- +offsetExists given string(1) "0" +offsetExists given string(3) "123" +offsetUnset given string(1) "0" +offsetUnset given string(3) "123" +offsetSet given string(1) "0" +offsetSet given string(3) "123" +offsetGet given string(1) "0" +offsetGet given string(3) "123" +offsetExists given string(1) "0" +offsetExists given string(3) "123" +offsetUnset given string(1) "0" +offsetUnset given string(3) "123" +offsetSet given string(1) "0" +offsetSet given string(3) "123" +offsetGet given string(1) "0" +offsetGet given string(3) "123" +string(2) "10" +array(3) { + [123]=> + int(1) + [321]=> + int(2) + ["abc"]=> + int(3) +} +array(3) { + [123]=> + int(1) + [321]=> + int(2) + ["abc"]=> + int(3) +} diff --git a/Zend/tests/empty_str_offset.phpt b/Zend/tests/empty_str_offset.phpt index 721844085a..044719a382 100644 --- a/Zend/tests/empty_str_offset.phpt +++ b/Zend/tests/empty_str_offset.phpt @@ -17,16 +17,24 @@ var_dump(empty($str[5])); // 1 var_dump(empty($str[8])); var_dump(empty($str[10000])); // non-numeric offsets -print "- string ---\n"; -var_dump(empty($str['-1'])); +print "- string literal ---\n"; +var_dump(empty($str['-1'])); // 3 var_dump(empty($str['-10'])); -var_dump(empty($str['-4'])); // 0 var_dump(empty($str['0'])); var_dump(empty($str['1'])); var_dump(empty($str['4'])); // 0 var_dump(empty($str['1.5'])); var_dump(empty($str['good'])); var_dump(empty($str['3 and a half'])); +print "- string variable ---\n"; +var_dump(empty($str[$key = '-1'])); // 3 +var_dump(empty($str[$key = '-10'])); +var_dump(empty($str[$key = '0'])); +var_dump(empty($str[$key = '1'])); +var_dump(empty($str[$key = '4'])); // 0 +var_dump(empty($str[$key = '1.5'])); +var_dump(empty($str[$key = 'good'])); +var_dump(empty($str[$key = '3 and a half'])); print "- bool ---\n"; var_dump(empty($str[true])); var_dump(empty($str[false])); @@ -54,7 +62,7 @@ var_dump(empty($str[$f])); print "done\n"; ?> ---EXPECT-- +--EXPECTF-- - empty --- bool(false) bool(true) @@ -65,9 +73,17 @@ bool(true) bool(false) bool(true) bool(true) -- string --- +- string literal --- bool(false) bool(true) +bool(false) +bool(false) +bool(true) +bool(true) +bool(true) +bool(true) +- string variable --- +bool(false) bool(true) bool(false) bool(false) diff --git a/Zend/tests/isset_str_offset.phpt b/Zend/tests/isset_str_offset.phpt index f37fd870bf..6be0f227a4 100644 --- a/Zend/tests/isset_str_offset.phpt +++ b/Zend/tests/isset_str_offset.phpt @@ -16,8 +16,8 @@ var_dump(isset($str[5])); // 1 var_dump(isset($str[8])); var_dump(isset($str[10000])); // non-numeric offsets -print "- string ---\n"; -var_dump(isset($str['-1'])); +print "- string literal ---\n"; +var_dump(isset($str['-1'])); // 3 var_dump(isset($str['-10'])); var_dump(isset($str['0'])); var_dump(isset($str['1'])); @@ -25,6 +25,15 @@ var_dump(isset($str['4'])); // 0 var_dump(isset($str['1.5'])); var_dump(isset($str['good'])); var_dump(isset($str['3 and a half'])); +print "- string variable ---\n"; +var_dump(isset($str[$key = '-1'])); // 3 +var_dump(isset($str[$key = '-10'])); +var_dump(isset($str[$key = '0'])); +var_dump(isset($str[$key = '1'])); +var_dump(isset($str[$key = '4'])); // 0 +var_dump(isset($str[$key = '1.5'])); +var_dump(isset($str[$key = 'good'])); +var_dump(isset($str[$key = '3 and a half'])); print "- bool ---\n"; var_dump(isset($str[true])); var_dump(isset($str[false])); @@ -51,7 +60,7 @@ var_dump(isset($str[$f])); print "done\n"; ?> ---EXPECT-- +--EXPECTF-- - isset --- bool(true) bool(false) @@ -61,7 +70,16 @@ bool(true) bool(true) bool(false) bool(false) -- string --- +- string literal --- +bool(true) +bool(false) +bool(true) +bool(true) +bool(true) +bool(false) +bool(false) +bool(false) +- string variable --- bool(true) bool(false) bool(true) diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c index 46fb089862..afc765b7c5 100644 --- a/Zend/zend_compile.c +++ b/Zend/zend_compile.c @@ -2672,7 +2672,6 @@ static zend_op *zend_delayed_compile_dim(znode *result, zend_ast *ast, uint32_t dim_node.op_type = IS_UNUSED; } else { zend_compile_expr(&dim_node, dim_ast); - zend_handle_numeric_op(&dim_node); } opline = zend_delayed_emit_op(result, ZEND_FETCH_DIM_R, &var_node, &dim_node); diff --git a/Zend/zend_execute.c b/Zend/zend_execute.c index 8e916c23a4..90addced09 100644 --- a/Zend/zend_execute.c +++ b/Zend/zend_execute.c @@ -1731,10 +1731,8 @@ num_undef: } } else if (EXPECTED(Z_TYPE_P(dim) == IS_STRING)) { offset_key = Z_STR_P(dim); - if (dim_type != IS_CONST) { - if (ZEND_HANDLE_NUMERIC(offset_key, hval)) { - goto num_index; - } + if (ZEND_HANDLE_NUMERIC(offset_key, hval)) { + goto num_index; } str_index: retval = zend_hash_find_ex(ht, offset_key, dim_type == IS_CONST); diff --git a/Zend/zend_vm_def.h b/Zend/zend_vm_def.h index 7495425cf2..c966e2a612 100644 --- a/Zend/zend_vm_def.h +++ b/Zend/zend_vm_def.h @@ -5538,10 +5538,8 @@ ZEND_VM_C_LABEL(unset_dim_array): ZEND_VM_C_LABEL(offset_again): if (EXPECTED(Z_TYPE_P(offset) == IS_STRING)) { key = Z_STR_P(offset); - if (OP2_TYPE != IS_CONST) { - if (ZEND_HANDLE_NUMERIC(key, hval)) { - ZEND_VM_C_GOTO(num_index_dim); - } + if (ZEND_HANDLE_NUMERIC(key, hval)) { + ZEND_VM_C_GOTO(num_index_dim); } ZEND_VM_C_LABEL(str_index_dim): if (ht == &EG(symbol_table)) { @@ -6286,10 +6284,8 @@ ZEND_VM_C_LABEL(isset_dim_obj_array): ZEND_VM_C_LABEL(isset_again): if (EXPECTED(Z_TYPE_P(offset) == IS_STRING)) { str = Z_STR_P(offset); - if (OP2_TYPE != IS_CONST) { - if (ZEND_HANDLE_NUMERIC(str, hval)) { - ZEND_VM_C_GOTO(num_index_prop); - } + if (ZEND_HANDLE_NUMERIC(str, hval)) { + ZEND_VM_C_GOTO(num_index_prop); } value = zend_hash_find_ex_ind(ht, str, OP2_TYPE == IS_CONST); } else if (EXPECTED(Z_TYPE_P(offset) == IS_LONG)) { diff --git a/Zend/zend_vm_execute.h b/Zend/zend_vm_execute.h index b54d505f14..3594b12304 100644 --- a/Zend/zend_vm_execute.h +++ b/Zend/zend_vm_execute.h @@ -5738,10 +5738,8 @@ isset_dim_obj_array: isset_again: if (EXPECTED(Z_TYPE_P(offset) == IS_STRING)) { str = Z_STR_P(offset); - if (IS_CONST != IS_CONST) { - if (ZEND_HANDLE_NUMERIC(str, hval)) { - goto num_index_prop; - } + if (ZEND_HANDLE_NUMERIC(str, hval)) { + goto num_index_prop; } value = zend_hash_find_ex_ind(ht, str, IS_CONST == IS_CONST); } else if (EXPECTED(Z_TYPE_P(offset) == IS_LONG)) { @@ -7632,10 +7630,8 @@ isset_dim_obj_array: isset_again: if (EXPECTED(Z_TYPE_P(offset) == IS_STRING)) { str = Z_STR_P(offset); - if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { - if (ZEND_HANDLE_NUMERIC(str, hval)) { - goto num_index_prop; - } + if (ZEND_HANDLE_NUMERIC(str, hval)) { + goto num_index_prop; } value = zend_hash_find_ex_ind(ht, str, (IS_TMP_VAR|IS_VAR) == IS_CONST); } else if (EXPECTED(Z_TYPE_P(offset) == IS_LONG)) { @@ -10716,10 +10712,8 @@ isset_dim_obj_array: isset_again: if (EXPECTED(Z_TYPE_P(offset) == IS_STRING)) { str = Z_STR_P(offset); - if (IS_CV != IS_CONST) { - if (ZEND_HANDLE_NUMERIC(str, hval)) { - goto num_index_prop; - } + if (ZEND_HANDLE_NUMERIC(str, hval)) { + goto num_index_prop; } value = zend_hash_find_ex_ind(ht, str, IS_CV == IS_CONST); } else if (EXPECTED(Z_TYPE_P(offset) == IS_LONG)) { @@ -14254,10 +14248,8 @@ isset_dim_obj_array: isset_again: if (EXPECTED(Z_TYPE_P(offset) == IS_STRING)) { str = Z_STR_P(offset); - if (IS_CONST != IS_CONST) { - if (ZEND_HANDLE_NUMERIC(str, hval)) { - goto num_index_prop; - } + if (ZEND_HANDLE_NUMERIC(str, hval)) { + goto num_index_prop; } value = zend_hash_find_ex_ind(ht, str, IS_CONST == IS_CONST); } else if (EXPECTED(Z_TYPE_P(offset) == IS_LONG)) { @@ -15716,10 +15708,8 @@ isset_dim_obj_array: isset_again: if (EXPECTED(Z_TYPE_P(offset) == IS_STRING)) { str = Z_STR_P(offset); - if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { - if (ZEND_HANDLE_NUMERIC(str, hval)) { - goto num_index_prop; - } + if (ZEND_HANDLE_NUMERIC(str, hval)) { + goto num_index_prop; } value = zend_hash_find_ex_ind(ht, str, (IS_TMP_VAR|IS_VAR) == IS_CONST); } else if (EXPECTED(Z_TYPE_P(offset) == IS_LONG)) { @@ -17582,10 +17572,8 @@ isset_dim_obj_array: isset_again: if (EXPECTED(Z_TYPE_P(offset) == IS_STRING)) { str = Z_STR_P(offset); - if (IS_CV != IS_CONST) { - if (ZEND_HANDLE_NUMERIC(str, hval)) { - goto num_index_prop; - } + if (ZEND_HANDLE_NUMERIC(str, hval)) { + goto num_index_prop; } value = zend_hash_find_ex_ind(ht, str, IS_CV == IS_CONST); } else if (EXPECTED(Z_TYPE_P(offset) == IS_LONG)) { @@ -23845,10 +23833,8 @@ unset_dim_array: offset_again: if (EXPECTED(Z_TYPE_P(offset) == IS_STRING)) { key = Z_STR_P(offset); - if (IS_CONST != IS_CONST) { - if (ZEND_HANDLE_NUMERIC(key, hval)) { - goto num_index_dim; - } + if (ZEND_HANDLE_NUMERIC(key, hval)) { + goto num_index_dim; } str_index_dim: if (ht == &EG(symbol_table)) { @@ -25990,10 +25976,8 @@ unset_dim_array: offset_again: if (EXPECTED(Z_TYPE_P(offset) == IS_STRING)) { key = Z_STR_P(offset); - if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { - if (ZEND_HANDLE_NUMERIC(key, hval)) { - goto num_index_dim; - } + if (ZEND_HANDLE_NUMERIC(key, hval)) { + goto num_index_dim; } str_index_dim: if (ht == &EG(symbol_table)) { @@ -29794,10 +29778,8 @@ unset_dim_array: offset_again: if (EXPECTED(Z_TYPE_P(offset) == IS_STRING)) { key = Z_STR_P(offset); - if (IS_CV != IS_CONST) { - if (ZEND_HANDLE_NUMERIC(key, hval)) { - goto num_index_dim; - } + if (ZEND_HANDLE_NUMERIC(key, hval)) { + goto num_index_dim; } str_index_dim: if (ht == &EG(symbol_table)) { @@ -40847,10 +40829,8 @@ unset_dim_array: offset_again: if (EXPECTED(Z_TYPE_P(offset) == IS_STRING)) { key = Z_STR_P(offset); - if (IS_CONST != IS_CONST) { - if (ZEND_HANDLE_NUMERIC(key, hval)) { - goto num_index_dim; - } + if (ZEND_HANDLE_NUMERIC(key, hval)) { + goto num_index_dim; } str_index_dim: if (ht == &EG(symbol_table)) { @@ -41050,10 +41030,8 @@ isset_dim_obj_array: isset_again: if (EXPECTED(Z_TYPE_P(offset) == IS_STRING)) { str = Z_STR_P(offset); - if (IS_CONST != IS_CONST) { - if (ZEND_HANDLE_NUMERIC(str, hval)) { - goto num_index_prop; - } + if (ZEND_HANDLE_NUMERIC(str, hval)) { + goto num_index_prop; } value = zend_hash_find_ex_ind(ht, str, IS_CONST == IS_CONST); } else if (EXPECTED(Z_TYPE_P(offset) == IS_LONG)) { @@ -44467,10 +44445,8 @@ unset_dim_array: offset_again: if (EXPECTED(Z_TYPE_P(offset) == IS_STRING)) { key = Z_STR_P(offset); - if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { - if (ZEND_HANDLE_NUMERIC(key, hval)) { - goto num_index_dim; - } + if (ZEND_HANDLE_NUMERIC(key, hval)) { + goto num_index_dim; } str_index_dim: if (ht == &EG(symbol_table)) { @@ -44596,10 +44572,8 @@ isset_dim_obj_array: isset_again: if (EXPECTED(Z_TYPE_P(offset) == IS_STRING)) { str = Z_STR_P(offset); - if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { - if (ZEND_HANDLE_NUMERIC(str, hval)) { - goto num_index_prop; - } + if (ZEND_HANDLE_NUMERIC(str, hval)) { + goto num_index_prop; } value = zend_hash_find_ex_ind(ht, str, (IS_TMP_VAR|IS_VAR) == IS_CONST); } else if (EXPECTED(Z_TYPE_P(offset) == IS_LONG)) { @@ -50084,10 +50058,8 @@ unset_dim_array: offset_again: if (EXPECTED(Z_TYPE_P(offset) == IS_STRING)) { key = Z_STR_P(offset); - if (IS_CV != IS_CONST) { - if (ZEND_HANDLE_NUMERIC(key, hval)) { - goto num_index_dim; - } + if (ZEND_HANDLE_NUMERIC(key, hval)) { + goto num_index_dim; } str_index_dim: if (ht == &EG(symbol_table)) { @@ -50211,10 +50183,8 @@ isset_dim_obj_array: isset_again: if (EXPECTED(Z_TYPE_P(offset) == IS_STRING)) { str = Z_STR_P(offset); - if (IS_CV != IS_CONST) { - if (ZEND_HANDLE_NUMERIC(str, hval)) { - goto num_index_prop; - } + if (ZEND_HANDLE_NUMERIC(str, hval)) { + goto num_index_prop; } value = zend_hash_find_ex_ind(ht, str, IS_CV == IS_CONST); } else if (EXPECTED(Z_TYPE_P(offset) == IS_LONG)) { |