]> granicus.if.org Git - php/commitdiff
Merge branch 'PHP-7.0' into PHP-7.1
authorXinchen Hui <laruence@gmail.com>
Fri, 10 Feb 2017 06:24:44 +0000 (14:24 +0800)
committerXinchen Hui <laruence@gmail.com>
Fri, 10 Feb 2017 06:25:29 +0000 (14:25 +0800)
* PHP-7.0:
  Fixed bug #74019 (Segfault with list)

1  2 
ext/opcache/Optimizer/zend_optimizer.c

index a30f18479a6120664669761fa6e6b362b7d7b099,7ae0e0612777242e61c0e54a7b0138f1d9071f46..fbcb3a2e16fb38c5e6b2318d7ec9babd8a5a8dc8
@@@ -451,18 -406,32 +451,33 @@@ int zend_optimizer_replace_by_const(zen
                                        break;
                                /* In most cases IS_TMP_VAR operand may be used only once.
                                 * The operands are usually destroyed by the opcode handler.
-                                * ZEND_CASE is an exception, that keeps operand unchanged,
-                                * and allows its reuse. The number of ZEND_CASE instructions
+                                * ZEND_CASE and ZEND_FETCH_LIST are exceptions, they keeps operand
+                                * unchanged, and allows its reuse. these instructions
                                 * usually terminated by ZEND_FREE that finally kills the value.
                                 */
-                               case ZEND_FREE:
-                               case ZEND_CASE: {
+                               case ZEND_FETCH_LIST: {
+                                       zend_op *m = opline;
+                                       do {
+                                               if (m->opcode == ZEND_FETCH_LIST &&
+                                                       ZEND_OP1_TYPE(m) == type &&
+                                                       ZEND_OP1(m).var == var) {
+                                                       zend_optimizer_update_op1_const(op_array, m, val);
+                                               }
+                                               m++;
+                                       } while (m->opcode != ZEND_FREE || ZEND_OP1_TYPE(m) != type || ZEND_OP1(m).var != var);
+                                       ZEND_ASSERT(m->opcode == ZEND_FREE && ZEND_OP1_TYPE(m) == type && ZEND_OP1(m).var == var);
+                                       MAKE_NOP(m);
++                                      zend_optimizer_remove_live_range(op_array, var);
+                                       return 1;
+                               }
+                               case ZEND_CASE:
+                               case ZEND_FREE: {
                                        zend_op *m, *n;
 -                                      int brk = op_array->last_brk_cont;
 +                                      int brk = op_array->last_live_range;
                                        zend_bool in_switch = 0;
                                        while (brk--) {
 -                                              if (op_array->brk_cont_array[brk].start <= (opline - op_array->opcodes) &&
 -                                                              op_array->brk_cont_array[brk].brk > (opline - op_array->opcodes)) {
 +                                              if (op_array->live_range[brk].start <= (uint32_t)(opline - op_array->opcodes) &&
 +                                                  op_array->live_range[brk].end > (uint32_t)(opline - op_array->opcodes)) {
                                                        in_switch = 1;
                                                        break;
                                                }