]> granicus.if.org Git - php/commitdiff
Fixed bug #63217
authorRudi Theunissen <rudolf.theunissen@gmail.com>
Thu, 28 Jun 2018 22:56:30 +0000 (18:56 -0400)
committerNikita Popov <nikita.ppv@gmail.com>
Mon, 2 Jul 2018 14:41:59 +0000 (16:41 +0200)
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.

13 files changed:
NEWS
UPGRADING
Zend/tests/bug29883.phpt
Zend/tests/bug55135.phpt
Zend/tests/bug63217.phpt [new file with mode: 0644]
Zend/tests/empty_str_offset.phpt
Zend/tests/isset_str_offset.phpt
Zend/zend_compile.c
Zend/zend_execute.c
Zend/zend_vm_def.h
Zend/zend_vm_execute.h
ext/opcache/Optimizer/zend_inference.c
ext/opcache/Optimizer/zend_optimizer.c

diff --git a/NEWS b/NEWS
index 73c8c1ad6e91fd1cf92cb1aa1a1144736bb33c36..44a718a0287e6147862bd5a25dee39cdc40d4eaf 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -14,6 +14,8 @@ PHP                                                                        NEWS
   . Fixed bug #76439 (Changed behaviour in unclosed HereDoc). (Nikita, tpunt)
   . Added syslog.facility and syslog.ident INI entries for customizing syslog
     logging. (Philip Prindeville)
+  . Fixed bug #63217 (Constant numeric strings become integers when used as
+    ArrayAccess offset). (Rudi Theunissen)
 
 - DOM:
   . Fixed bug #76285 (DOMDocument::formatOutput attribute sometimes ignored).
index 2e0b8d2dccc68ae5d21f70e21f53adf6696fcd0a..f616bf9cda308e39087ca7ff33dc4e24aaaa7675 100644 (file)
--- a/UPGRADING
+++ b/UPGRADING
@@ -44,6 +44,12 @@ Core:
     the following "FOO;" will cause a syntax error. This issue can always be
     resolved by choosing an ending label that does not occur within the contents
     of the string.
+  . Array accesses of type $obj["123"], where $obj implements ArrayAccess and
+    "123" is an integral string literal will no longer result in an implicit
+    conversion to integer, i.e., $obj->offsetGet("123") will be called instead
+    of $obj->offsetGet(123). This matches existing behavior for non-literals.
+    The behavior of arrays is not affected in any way, they continue to
+    implicitly convert integeral string keys to integers.
   . In PHP, static properties are shared between inheriting classes, unless the
     static property is explicitly overridden in a child class. However, due to
     an implementation artifact it was possible to separate the static properties
index b6ad99aeaf618ecabaf39d62b51246e9f32c59cf..4e07b02d1048aab46c4faa510fac2f8e6012eea7 100644 (file)
@@ -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"
index f6d0aafacaeec01f54ce2fffa25252b520cb7ef4..a1ffff21f945f62a9a50193d65af2cc54c252df8 100644 (file)
@@ -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 (file)
index 0000000..ca9b900
--- /dev/null
@@ -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)
+}
index 721844085a4cb26c0f1ff54e67de6f169f711616..044719a382b5656e0202ee341fecdd23c8c84dd8 100644 (file)
@@ -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)
index f37fd870bf14fb3848849a29a6601baf6eb3ea5d..6be0f227a434ccd8f87d277f386f5d3cb28e8479 100644 (file)
@@ -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)
index 46fb08986285a8c70e8729dbcb4cb3a67038e874..afc765b7c58b95f56c9d05121ebd26d12e58cf39 100644 (file)
@@ -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);
index 8e916c23a42f1774953e5d849ab9c1695cb8b1fa..90addced09b7c8e777a6cdd84d35e36e0aea646e 100644 (file)
@@ -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);
index 7495425cf2ec7550f9fe4e87eaa3327e08e87854..c966e2a6129ac5821214a1b1177c9dc57ac534a2 100644 (file)
@@ -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)) {
index b54d505f14ef0e653c695d4bac94c7c7604bd97b..3594b12304c68c955efbefbfb8de08edb2f2fc1f 100644 (file)
@@ -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)) {
index 92a4cbeaea265828c40f530614194f05329b1834..e7e1a708cb1e1d1c9bf5388820c4268b773c0cf8 100644 (file)
@@ -169,6 +169,10 @@ static inline zend_bool sub_will_overflow(zend_long a, zend_long b) {
 }
 #endif
 
+
+#define DIM_OP_FOR_CONST_NUM_CHECK  \
+       (opline->op2_type == IS_CONST ? CRT_CONSTANT_EX(op_array, opline, opline->op2, ssa->rt_constants) : NULL)
+
 static void zend_ssa_check_scc_var(const zend_op_array *op_array, zend_ssa *ssa, int var, int *index, int *dfs, int *root, zend_worklist_stack *stack) /* {{{ */
 {
 #ifdef SYM_RANGE
@@ -2085,8 +2089,43 @@ uint32_t zend_array_element_type(uint32_t t1, int write, int insert)
        return tmp;
 }
 
+static inline uint32_t get_dim_array_key_type(uint32_t dim_type, zend_uchar dim_op_type, zval *dim_op) 
+{
+       uint32_t tmp = 0;
+
+       if (dim_op_type == IS_UNUSED) {
+               tmp |= MAY_BE_ARRAY_KEY_LONG;
+       } else {
+               if (dim_type & (MAY_BE_LONG|MAY_BE_FALSE|MAY_BE_TRUE|MAY_BE_RESOURCE|MAY_BE_DOUBLE)) {
+                       tmp |= MAY_BE_ARRAY_KEY_LONG;
+               }
+               if (dim_type & MAY_BE_STRING) {
+                       if (dim_op_type != IS_CONST) {
+                               tmp |= MAY_BE_ARRAY_KEY_STRING | MAY_BE_ARRAY_KEY_LONG;
+                       } else {
+                               zend_ulong hval;
+                               if (ZEND_HANDLE_NUMERIC(Z_STR_P(dim_op), hval)) {
+                                       tmp |= MAY_BE_ARRAY_KEY_LONG;
+                               } else {
+                                       tmp |= MAY_BE_ARRAY_KEY_STRING;
+                               }
+                       }
+               }
+               if (dim_type & (MAY_BE_UNDEF|MAY_BE_NULL)) {
+                       tmp |= MAY_BE_ARRAY_KEY_STRING;
+               }
+       }
+       
+       return tmp;
+}
+
 static uint32_t assign_dim_result_type(
-               uint32_t arr_type, uint32_t dim_type, uint32_t value_type, zend_uchar dim_op_type) {
+       uint32_t arr_type, 
+       uint32_t dim_type, 
+       uint32_t value_type, 
+       zend_uchar dim_op_type, 
+       zval *dim_op
+) {
        uint32_t tmp = arr_type & ~(MAY_BE_RC1|MAY_BE_RCN);
 
        if (arr_type & (MAY_BE_UNDEF|MAY_BE_NULL|MAY_BE_FALSE)) {
@@ -2104,23 +2143,7 @@ static uint32_t assign_dim_result_type(
                if (value_type & MAY_BE_UNDEF) {
                        tmp |= MAY_BE_ARRAY_OF_NULL;
                }
-               if (dim_op_type == IS_UNUSED) {
-                       tmp |= MAY_BE_ARRAY_KEY_LONG;
-               } else {
-                       if (dim_type & (MAY_BE_LONG|MAY_BE_FALSE|MAY_BE_TRUE|MAY_BE_RESOURCE|MAY_BE_DOUBLE)) {
-                               tmp |= MAY_BE_ARRAY_KEY_LONG;
-                       }
-                       if (dim_type & MAY_BE_STRING) {
-                               tmp |= MAY_BE_ARRAY_KEY_STRING;
-                               if (dim_op_type != IS_CONST) {
-                                       // FIXME: numeric string
-                                       tmp |= MAY_BE_ARRAY_KEY_LONG;
-                               }
-                       }
-                       if (dim_type & (MAY_BE_UNDEF|MAY_BE_NULL)) {
-                               tmp |= MAY_BE_ARRAY_KEY_STRING;
-                       }
-               }
+               tmp |= get_dim_array_key_type(dim_type, dim_op_type, dim_op);
        }
        return tmp;
 }
@@ -2496,7 +2519,8 @@ static int zend_update_type_info(const zend_op_array *op_array,
 
                        if (opline->extended_value == ZEND_ASSIGN_DIM) {
                                if (opline->op1_type == IS_CV) {
-                                       orig = assign_dim_result_type(orig, OP2_INFO(), tmp, opline->op2_type);
+                                       orig = assign_dim_result_type(orig, OP2_INFO(), tmp, opline->op2_type, DIM_OP_FOR_CONST_NUM_CHECK);
+                                       
                                        UPDATE_SSA_TYPE(orig, ssa_ops[i].op1_def);
                                        COPY_SSA_OBJ_TYPE(ssa_ops[i].op1_use, ssa_ops[i].op1_def);
                                }
@@ -2658,7 +2682,8 @@ static int zend_update_type_info(const zend_op_array *op_array,
                        break;
                case ZEND_ASSIGN_DIM:
                        if (opline->op1_type == IS_CV) {
-                               tmp = assign_dim_result_type(t1, t2, OP1_DATA_INFO(), opline->op2_type);
+                               tmp = assign_dim_result_type(t1, t2, OP1_DATA_INFO(), opline->op2_type, DIM_OP_FOR_CONST_NUM_CHECK);
+                               
                                UPDATE_SSA_TYPE(tmp, ssa_ops[i].op1_def);
                                COPY_SSA_OBJ_TYPE(ssa_ops[i].op1_use, ssa_ops[i].op1_def);
                        }
@@ -3057,23 +3082,8 @@ static int zend_update_type_info(const zend_op_array *op_array,
                                if (ssa_ops[i].result_use >= 0) {
                                        tmp |= ssa_var_info[ssa_ops[i].result_use].type;
                                }
-                               if (opline->op2_type == IS_UNUSED) {
-                                       tmp |= MAY_BE_ARRAY_KEY_LONG;
-                               } else {
-                                       if (t2 & (MAY_BE_LONG|MAY_BE_FALSE|MAY_BE_TRUE|MAY_BE_DOUBLE)) {
-                                               tmp |= MAY_BE_ARRAY_KEY_LONG;
-                                       }
-                                       if (t2 & (MAY_BE_STRING)) {
-                                               tmp |= MAY_BE_ARRAY_KEY_STRING;
-                                               if (opline->op2_type != IS_CONST) {
-                                                       // FIXME: numeric string
-                                                       tmp |= MAY_BE_ARRAY_KEY_LONG;
-                                               }
-                                       }
-                                       if (t2 & (MAY_BE_UNDEF | MAY_BE_NULL)) {
-                                               tmp |= MAY_BE_ARRAY_KEY_STRING;
-                                       }
-                               }
+                               tmp |= get_dim_array_key_type(t2, opline->op2_type, DIM_OP_FOR_CONST_NUM_CHECK);
+
                                UPDATE_SSA_TYPE(tmp, ssa_ops[i].result_def);
                        }
                        break;
@@ -3186,23 +3196,8 @@ static int zend_update_type_info(const zend_op_array *op_array,
                                        if (t1 & (MAY_BE_OBJECT|MAY_BE_RESOURCE)) {
                                                tmp |= t1 & (MAY_BE_RC1|MAY_BE_RCN);
                                        }
-                                       if (opline->op2_type == IS_UNUSED) {
-                                               tmp |= MAY_BE_ARRAY_KEY_LONG;
-                                       } else {
-                                               if (t2 & (MAY_BE_LONG|MAY_BE_FALSE|MAY_BE_TRUE|MAY_BE_RESOURCE|MAY_BE_DOUBLE)) {
-                                                       tmp |= MAY_BE_ARRAY_KEY_LONG;
-                                               }
-                                               if (t2 & MAY_BE_STRING) {
-                                                       tmp |= MAY_BE_ARRAY_KEY_STRING;
-                                                       if (opline->op2_type != IS_CONST) {
-                                                               // FIXME: numeric string
-                                                               tmp |= MAY_BE_ARRAY_KEY_LONG;
-                                                       }
-                                               }
-                                               if (t2 & (MAY_BE_UNDEF | MAY_BE_NULL)) {
-                                                       tmp |= MAY_BE_ARRAY_KEY_STRING;
-                                               }
-                                       }
+                                       tmp |= get_dim_array_key_type(t2, opline->op2_type, DIM_OP_FOR_CONST_NUM_CHECK);
+
                                } else if (opline->opcode == ZEND_FETCH_DIM_UNSET) {
                                        if (t1 & MAY_BE_ARRAY) {
                                                tmp |= MAY_BE_RC1;
index 0b4d7f82a0c60fa10820bbb16579967d7f1e38d2..bfc45e32ae6d48f3dcf0922245caa3cbd17d8016 100644 (file)
@@ -518,19 +518,7 @@ int zend_optimizer_update_op2_const(zend_op_array *op_array,
                                opline->op2.constant = zend_optimizer_add_literal(op_array, val);
                        }
                        break;
-               case ZEND_ISSET_ISEMPTY_DIM_OBJ:
                case ZEND_ADD_ARRAY_ELEMENT:
-               case ZEND_INIT_ARRAY:
-               case ZEND_ASSIGN_DIM:
-               case ZEND_UNSET_DIM:
-               case ZEND_FETCH_DIM_R:
-               case ZEND_FETCH_DIM_W:
-               case ZEND_FETCH_DIM_RW:
-               case ZEND_FETCH_DIM_IS:
-               case ZEND_FETCH_DIM_FUNC_ARG:
-               case ZEND_FETCH_DIM_UNSET:
-               case ZEND_FETCH_LIST_R:
-               case ZEND_FETCH_LIST_W:
                        if (Z_TYPE_P(val) == IS_STRING) {
                                zend_ulong index;
                                if (ZEND_HANDLE_NUMERIC(Z_STR_P(val), index)) {