summaryrefslogtreecommitdiff
path: root/Zend
diff options
context:
space:
mode:
authorRudi Theunissen <rudolf.theunissen@gmail.com>2018-06-28 18:56:30 -0400
committerNikita Popov <nikita.ppv@gmail.com>2018-07-02 16:41:59 +0200
commit30156d588c07e26d4e752ddb62344e96854d4773 (patch)
tree569af90625c7a0397f444cb871172fa77a153da9 /Zend
parent6d61814d0e2115b834b1e6cbc27c6b05299b3e7a (diff)
downloadphp-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.phpt14
-rw-r--r--Zend/tests/bug55135.phpt2
-rw-r--r--Zend/tests/bug63217.phpt123
-rw-r--r--Zend/tests/empty_str_offset.phpt26
-rw-r--r--Zend/tests/isset_str_offset.phpt26
-rw-r--r--Zend/zend_compile.c1
-rw-r--r--Zend/zend_execute.c6
-rw-r--r--Zend/zend_vm_def.h12
-rw-r--r--Zend/zend_vm_execute.h90
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)) {