Fixed bug while dealing with ADD_ARRAY_ELEMENT against an existing const array
authorXinchen Hui <laruence@gmail.com>
Sun, 7 Jan 2018 06:17:47 +0000 (14:17 +0800)
committerXinchen Hui <laruence@gmail.com>
Sun, 7 Jan 2018 06:17:47 +0000 (14:17 +0800)
ext/opcache/Optimizer/sccp.c
ext/opcache/tests/opt/sccp_025.phpt [new file with mode: 0644]

index 8b5f88cffe239a0875732511502bee9f373f5485..cbfc6de6484918c831bdac96876f81643a02e334 100644 (file)
@@ -97,30 +97,33 @@ typedef struct _sccp_ctx {
 #define IS_PARTIAL_ARRAY(zv) (Z_TYPE_P(zv) == PARTIAL_ARRAY)
 #define IS_PARTIAL_OBJECT(zv) (Z_TYPE_P(zv) == PARTIAL_OBJECT)
 
+#define MAKE_PARTIAL_ARRAY(zv) (Z_TYPE_INFO_P(zv) = PARTIAL_ARRAY | (IS_TYPE_REFCOUNTED << Z_TYPE_FLAGS_SHIFT))
+#define MAKE_PARTIAL_OBJECT(zv) (Z_TYPE_INFO_P(zv) = PARTIAL_OBJECT | (IS_TYPE_REFCOUNTED << Z_TYPE_FLAGS_SHIFT))
+
 #define MAKE_TOP(zv) (Z_TYPE_INFO_P(zv) = TOP)
 #define MAKE_BOT(zv) (Z_TYPE_INFO_P(zv) = BOT)
 
 static void empty_partial_array(zval *zv)
 {
-       Z_TYPE_INFO_P(zv) = PARTIAL_ARRAY | (IS_TYPE_REFCOUNTED << Z_TYPE_FLAGS_SHIFT);
+       MAKE_PARTIAL_ARRAY(zv);
        Z_ARR_P(zv) = zend_new_array(8);
 }
 
 static void dup_partial_array(zval *dst, zval *src)
 {
-       Z_TYPE_INFO_P(dst) = PARTIAL_ARRAY | (IS_TYPE_REFCOUNTED << Z_TYPE_FLAGS_SHIFT);
+       MAKE_PARTIAL_ARRAY(dst);
        Z_ARR_P(dst) = zend_array_dup(Z_ARR_P(src));
 }
 
 static void empty_partial_object(zval *zv)
 {
-       Z_TYPE_INFO_P(zv) = PARTIAL_OBJECT | (IS_TYPE_REFCOUNTED << Z_TYPE_FLAGS_SHIFT);
+       MAKE_PARTIAL_OBJECT(zv);
        Z_ARR_P(zv) = zend_new_array(8);
 }
 
 static void dup_partial_object(zval *dst, zval *src)
 {
-       Z_TYPE_INFO_P(dst) = PARTIAL_OBJECT | (IS_TYPE_REFCOUNTED << Z_TYPE_FLAGS_SHIFT);
+       MAKE_PARTIAL_OBJECT(dst);
        Z_ARR_P(dst) = zend_array_dup(Z_ARR_P(src));
 }
 
@@ -1245,7 +1248,7 @@ static void sccp_visit_instr(scdf_ctx *scdf, zend_op *opline, zend_ssa_op *ssa_o
                                        if (!result) {
                                                empty_partial_array(&zv);
                                        } else {
-                                               Z_TYPE_INFO_P(result) = PARTIAL_ARRAY | (IS_TYPE_REFCOUNTED << Z_TYPE_FLAGS_SHIFT);
+                                               MAKE_PARTIAL_ARRAY(result);
                                                ZVAL_COPY_VALUE(&zv, result);
                                                ZVAL_NULL(result);
                                        }
@@ -1268,10 +1271,8 @@ static void sccp_visit_instr(scdf_ctx *scdf, zend_op *opline, zend_ssa_op *ssa_o
                                if (result) {
                                        ZVAL_COPY_VALUE(&zv, result);
                                        ZVAL_NULL(result);
-                               } else if (op1 && !IS_PARTIAL_ARRAY(op1)) {
-                                       array_init(&zv);
                                } else {
-                                       empty_partial_array(&zv);
+                                       array_init(&zv);
                                }
 
                                if (op1) {
@@ -1279,6 +1280,9 @@ static void sccp_visit_instr(scdf_ctx *scdf, zend_op *opline, zend_ssa_op *ssa_o
                                                /* We can't add NEXT element into partial array (skip it) */
                                                SET_RESULT(result, &zv);
                                        } else if (ct_eval_add_array_elem(&zv, op1, op2) == SUCCESS) {
+                                               if (IS_PARTIAL_ARRAY(op1)) {
+                                                       MAKE_PARTIAL_ARRAY(&zv);
+                                               }
                                                SET_RESULT(result, &zv);
                                        } else {
                                                SET_RESULT_BOT(result);
diff --git a/ext/opcache/tests/opt/sccp_025.phpt b/ext/opcache/tests/opt/sccp_025.phpt
new file mode 100644 (file)
index 0000000..0209733
--- /dev/null
@@ -0,0 +1,55 @@
+--TEST--
+SCCP 025: ADD_ARRAY_ELEMENT against an existing const array
+--INI--
+opcache.enable=1
+opcache.enable_cli=1
+opcache.optimization_level=-1
+opcache.opt_debug_level=0
+--SKIPIF--
+<?php require_once('skipif.inc'); ?>
+--FILE--
+<?php
+function test($phpEx)
+{
+       $expected_data_sets = array(
+               1 => array(
+                       'id'  => 1,
+               ),
+               6 => array(
+                       'viewtopic' => strval("phpBB/viewtopic.$phpEx"),
+
+               ),
+       );
+
+       $test_cases = array(
+               array(
+                       'expected' => array(6),
+               ),
+       );
+
+       foreach ($test_cases as $case => $case_data)
+       {
+               foreach ($case_data['expected'] as $data_set => $expected)
+               {
+                       $test_cases[$case]['expected'][$data_set] = $expected_data_sets[$expected];
+               }
+       }
+
+       return $test_cases;
+}
+var_dump(test("xxx"));
+?>
+--EXPECTF--
+array(1) {
+  [0]=>
+  array(1) {
+    ["expected"]=>
+    array(1) {
+      [0]=>
+      array(1) {
+        ["viewtopic"]=>
+        string(19) "phpBB/viewtopic.xxx"
+      }
+    }
+  }
+}