Commit:    536260f2c52af7057a657af96d991acf27c0cc86
Author:    Nikita Popov <ni...@php.net>         Fri, 4 Oct 2013 13:13:46 +0200
Parents:   2e2bda3508444190cb9b707dffe328a263ec60a1
Branches:  PHP-5.5 master

Link:       
http://git.php.net/?p=php-src.git;a=commitdiff;h=536260f2c52af7057a657af96d991acf27c0cc86

Log:
Fix bug #65821: By-ref foreach on property access of string offset segfaults

This removes the now unnecessary ZEND_FETCH_ADD_LOCK on the
container of a property fetch of a by-reference foreach.

Bugs:
https://bugs.php.net/65821

Changed paths:
  M  NEWS
  M  Zend/zend_compile.c
  M  Zend/zend_vm_def.h
  M  Zend/zend_vm_execute.h

diff --git a/NEWS b/NEWS
index 1b1f9c4..796f82f 100644
--- a/NEWS
+++ b/NEWS
@@ -5,6 +5,8 @@ PHP                                                             
           NEWS
 - Core:
   . Fixed bug #64979 (Wrong behavior of static variables in closure 
generators).
     (Nikita)
+  . Fixed bug #65821 (By-ref foreach on property access of string offset
+    segfaults). (Nikita)
 
 - CLI server:
   . Fixed bug #65633 (built-in server treat some http headers as
diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c
index f250b2b..9008f23 100644
--- a/Zend/zend_compile.c
+++ b/Zend/zend_compile.c
@@ -1749,7 +1749,6 @@ void zend_do_begin_function_declaration(znode 
*function_token, znode *function_n
                zend_op dummy_opline;
 
                dummy_opline.result_type = IS_UNUSED;
-               dummy_opline.op1_type = IS_UNUSED;
 
                zend_stack_push(&CG(foreach_copy_stack), (void *) 
&dummy_opline, sizeof(zend_op));
        }
@@ -2662,7 +2661,7 @@ static int generate_free_switch_expr(const 
zend_switch_entry *switch_entry TSRML
        opline->opcode = (switch_entry->cond.op_type == IS_TMP_VAR) ? ZEND_FREE 
: ZEND_SWITCH_FREE;
        SET_NODE(opline->op1, &switch_entry->cond);
        SET_UNUSED(opline->op2);
-       opline->extended_value = 0;
+
        return 0;
 }
 /* }}} */
@@ -2672,7 +2671,7 @@ static int generate_free_foreach_copy(const zend_op 
*foreach_copy TSRMLS_DC) /*
        zend_op *opline;
 
        /* If we reach the separator then stop applying the stack */
-       if (foreach_copy->result_type == IS_UNUSED && foreach_copy->op1_type == 
IS_UNUSED) {
+       if (foreach_copy->result_type == IS_UNUSED) {
                return 1;
        }
 
@@ -2681,16 +2680,6 @@ static int generate_free_foreach_copy(const zend_op 
*foreach_copy TSRMLS_DC) /*
        opline->opcode = (foreach_copy->result_type == IS_TMP_VAR) ? ZEND_FREE 
: ZEND_SWITCH_FREE;
        COPY_NODE(opline->op1, foreach_copy->result);
        SET_UNUSED(opline->op2);
-       opline->extended_value = 1;
-
-       if (foreach_copy->op1_type != IS_UNUSED) {
-               opline = get_next_op(CG(active_op_array) TSRMLS_CC);
-
-               opline->opcode = (foreach_copy->op1_type == IS_TMP_VAR) ? 
ZEND_FREE : ZEND_SWITCH_FREE;
-               COPY_NODE(opline->op1, foreach_copy->op1);
-               SET_UNUSED(opline->op2);
-               opline->extended_value = 0;
-       }
 
        return 0;
 }
@@ -6227,7 +6216,6 @@ void zend_do_foreach_begin(znode *foreach_token, znode 
*open_brackets_token, zno
 {
        zend_op *opline;
        zend_bool is_variable;
-       zend_bool push_container = 0;
        zend_op dummy_opline;
 
        if (variable) {
@@ -6239,14 +6227,6 @@ void zend_do_foreach_begin(znode *foreach_token, znode 
*open_brackets_token, zno
                /* save the location of FETCH_W instruction(s) */
                open_brackets_token->u.op.opline_num = 
get_next_op_number(CG(active_op_array));
                zend_do_end_variable_parse(array, BP_VAR_W, 0 TSRMLS_CC);
-               if (CG(active_op_array)->last > 0 &&
-                   
CG(active_op_array)->opcodes[CG(active_op_array)->last-1].opcode == 
ZEND_FETCH_OBJ_W) {
-                       /* Only lock the container if we are fetching from a 
real container and not $this */
-                       if 
(CG(active_op_array)->opcodes[CG(active_op_array)->last-1].op1_type == IS_VAR) {
-                               
CG(active_op_array)->opcodes[CG(active_op_array)->last-1].extended_value |= 
ZEND_FETCH_ADD_LOCK;
-                               push_container = 1;
-                       }
-               }
        } else {
                is_variable = 0;
                open_brackets_token->u.op.opline_num = 
get_next_op_number(CG(active_op_array));
@@ -6266,11 +6246,6 @@ void zend_do_foreach_begin(znode *foreach_token, znode 
*open_brackets_token, zno
        opline->extended_value = is_variable ? ZEND_FE_RESET_VARIABLE : 0;
 
        COPY_NODE(dummy_opline.result, opline->result);
-       if (push_container) {
-               COPY_NODE(dummy_opline.op1, 
CG(active_op_array)->opcodes[CG(active_op_array)->last-2].op1);
-       } else {
-               dummy_opline.op1_type = IS_UNUSED;
-       }
        zend_stack_push(&CG(foreach_copy_stack), (void *) &dummy_opline, 
sizeof(zend_op));
 
        /* save the location of FE_FETCH */
@@ -6327,7 +6302,6 @@ void zend_do_foreach_cont(znode *foreach_token, const 
znode *open_brackets_token
                opline->extended_value |= ZEND_FE_FETCH_BYREF;
                
CG(active_op_array)->opcodes[foreach_token->u.op.opline_num].extended_value |= 
ZEND_FE_RESET_REFERENCE;
        } else {
-               zend_op *foreach_copy;
                zend_op *fetch = 
&CG(active_op_array)->opcodes[foreach_token->u.op.opline_num];
                zend_op *end = 
&CG(active_op_array)->opcodes[open_brackets_token->u.op.opline_num];
 
@@ -6344,9 +6318,6 @@ void zend_do_foreach_cont(znode *foreach_token, const 
znode *open_brackets_token
                                fetch->opcode -= 3; /* FETCH_W -> FETCH_R */
                        }
                }
-               /* prevent double SWITCH_FREE */
-               zend_stack_top(&CG(foreach_copy_stack), (void **) 
&foreach_copy);
-               foreach_copy->op1_type = IS_UNUSED;
        }
 
        GET_NODE(&value_node, opline->result);
diff --git a/Zend/zend_vm_def.h b/Zend/zend_vm_def.h
index ada20ca..201ae49 100644
--- a/Zend/zend_vm_def.h
+++ b/Zend/zend_vm_def.h
@@ -1392,11 +1392,6 @@ ZEND_VM_HANDLER(85, ZEND_FETCH_OBJ_W, VAR|UNUSED|CV, 
CONST|TMP|VAR|CV)
        SAVE_OPLINE();
        property = GET_OP2_ZVAL_PTR(BP_VAR_R);
 
-       if (OP1_TYPE == IS_VAR && (opline->extended_value & 
ZEND_FETCH_ADD_LOCK)) {
-               PZVAL_LOCK(*EX_T(opline->op1.var).var.ptr_ptr);
-               EX_T(opline->op1.var).var.ptr = 
*EX_T(opline->op1.var).var.ptr_ptr;
-       }
-
        if (IS_OP2_TMP_FREE()) {
                MAKE_REAL_ZVAL_PTR(property);
        }
diff --git a/Zend/zend_vm_execute.h b/Zend/zend_vm_execute.h
index 2ba6bfe..74a8c12 100644
--- a/Zend/zend_vm_execute.h
+++ b/Zend/zend_vm_execute.h
@@ -14997,11 +14997,6 @@ static int ZEND_FASTCALL  
ZEND_FETCH_OBJ_W_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HA
        SAVE_OPLINE();
        property = opline->op2.zv;
 
-       if (IS_VAR == IS_VAR && (opline->extended_value & ZEND_FETCH_ADD_LOCK)) 
{
-               PZVAL_LOCK(*EX_T(opline->op1.var).var.ptr_ptr);
-               EX_T(opline->op1.var).var.ptr = 
*EX_T(opline->op1.var).var.ptr_ptr;
-       }
-
        if (0) {
                MAKE_REAL_ZVAL_PTR(property);
        }
@@ -17353,11 +17348,6 @@ static int ZEND_FASTCALL  
ZEND_FETCH_OBJ_W_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HAND
        SAVE_OPLINE();
        property = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 
TSRMLS_CC);
 
-       if (IS_VAR == IS_VAR && (opline->extended_value & ZEND_FETCH_ADD_LOCK)) 
{
-               PZVAL_LOCK(*EX_T(opline->op1.var).var.ptr_ptr);
-               EX_T(opline->op1.var).var.ptr = 
*EX_T(opline->op1.var).var.ptr_ptr;
-       }
-
        if (1) {
                MAKE_REAL_ZVAL_PTR(property);
        }
@@ -19616,11 +19606,6 @@ static int ZEND_FASTCALL  
ZEND_FETCH_OBJ_W_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HAND
        SAVE_OPLINE();
        property = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 
TSRMLS_CC);
 
-       if (IS_VAR == IS_VAR && (opline->extended_value & ZEND_FETCH_ADD_LOCK)) 
{
-               PZVAL_LOCK(*EX_T(opline->op1.var).var.ptr_ptr);
-               EX_T(opline->op1.var).var.ptr = 
*EX_T(opline->op1.var).var.ptr_ptr;
-       }
-
        if (0) {
                MAKE_REAL_ZVAL_PTR(property);
        }
@@ -23081,11 +23066,6 @@ static int ZEND_FASTCALL  
ZEND_FETCH_OBJ_W_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDL
        SAVE_OPLINE();
        property = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var 
TSRMLS_CC);
 
-       if (IS_VAR == IS_VAR && (opline->extended_value & ZEND_FETCH_ADD_LOCK)) 
{
-               PZVAL_LOCK(*EX_T(opline->op1.var).var.ptr_ptr);
-               EX_T(opline->op1.var).var.ptr = 
*EX_T(opline->op1.var).var.ptr_ptr;
-       }
-
        if (0) {
                MAKE_REAL_ZVAL_PTR(property);
        }
@@ -24867,11 +24847,6 @@ static int ZEND_FASTCALL  
ZEND_FETCH_OBJ_W_SPEC_UNUSED_CONST_HANDLER(ZEND_OPCODE
        SAVE_OPLINE();
        property = opline->op2.zv;
 
-       if (IS_UNUSED == IS_VAR && (opline->extended_value & 
ZEND_FETCH_ADD_LOCK)) {
-               PZVAL_LOCK(*EX_T(opline->op1.var).var.ptr_ptr);
-               EX_T(opline->op1.var).var.ptr = 
*EX_T(opline->op1.var).var.ptr_ptr;
-       }
-
        if (0) {
                MAKE_REAL_ZVAL_PTR(property);
        }
@@ -26285,11 +26260,6 @@ static int ZEND_FASTCALL  
ZEND_FETCH_OBJ_W_SPEC_UNUSED_TMP_HANDLER(ZEND_OPCODE_H
        SAVE_OPLINE();
        property = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 
TSRMLS_CC);
 
-       if (IS_UNUSED == IS_VAR && (opline->extended_value & 
ZEND_FETCH_ADD_LOCK)) {
-               PZVAL_LOCK(*EX_T(opline->op1.var).var.ptr_ptr);
-               EX_T(opline->op1.var).var.ptr = 
*EX_T(opline->op1.var).var.ptr_ptr;
-       }
-
        if (1) {
                MAKE_REAL_ZVAL_PTR(property);
        }
@@ -27606,11 +27576,6 @@ static int ZEND_FASTCALL  
ZEND_FETCH_OBJ_W_SPEC_UNUSED_VAR_HANDLER(ZEND_OPCODE_H
        SAVE_OPLINE();
        property = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 
TSRMLS_CC);
 
-       if (IS_UNUSED == IS_VAR && (opline->extended_value & 
ZEND_FETCH_ADD_LOCK)) {
-               PZVAL_LOCK(*EX_T(opline->op1.var).var.ptr_ptr);
-               EX_T(opline->op1.var).var.ptr = 
*EX_T(opline->op1.var).var.ptr_ptr;
-       }
-
        if (0) {
                MAKE_REAL_ZVAL_PTR(property);
        }
@@ -29349,11 +29314,6 @@ static int ZEND_FASTCALL  
ZEND_FETCH_OBJ_W_SPEC_UNUSED_CV_HANDLER(ZEND_OPCODE_HA
        SAVE_OPLINE();
        property = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var 
TSRMLS_CC);
 
-       if (IS_UNUSED == IS_VAR && (opline->extended_value & 
ZEND_FETCH_ADD_LOCK)) {
-               PZVAL_LOCK(*EX_T(opline->op1.var).var.ptr_ptr);
-               EX_T(opline->op1.var).var.ptr = 
*EX_T(opline->op1.var).var.ptr_ptr;
-       }
-
        if (0) {
                MAKE_REAL_ZVAL_PTR(property);
        }
@@ -32493,11 +32453,6 @@ static int ZEND_FASTCALL  
ZEND_FETCH_OBJ_W_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HAN
        SAVE_OPLINE();
        property = opline->op2.zv;
 
-       if (IS_CV == IS_VAR && (opline->extended_value & ZEND_FETCH_ADD_LOCK)) {
-               PZVAL_LOCK(*EX_T(opline->op1.var).var.ptr_ptr);
-               EX_T(opline->op1.var).var.ptr = 
*EX_T(opline->op1.var).var.ptr_ptr;
-       }
-
        if (0) {
                MAKE_REAL_ZVAL_PTR(property);
        }
@@ -34614,11 +34569,6 @@ static int ZEND_FASTCALL  
ZEND_FETCH_OBJ_W_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HANDL
        SAVE_OPLINE();
        property = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 
TSRMLS_CC);
 
-       if (IS_CV == IS_VAR && (opline->extended_value & ZEND_FETCH_ADD_LOCK)) {
-               PZVAL_LOCK(*EX_T(opline->op1.var).var.ptr_ptr);
-               EX_T(opline->op1.var).var.ptr = 
*EX_T(opline->op1.var).var.ptr_ptr;
-       }
-
        if (1) {
                MAKE_REAL_ZVAL_PTR(property);
        }
@@ -36739,11 +36689,6 @@ static int ZEND_FASTCALL  
ZEND_FETCH_OBJ_W_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDL
        SAVE_OPLINE();
        property = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 
TSRMLS_CC);
 
-       if (IS_CV == IS_VAR && (opline->extended_value & ZEND_FETCH_ADD_LOCK)) {
-               PZVAL_LOCK(*EX_T(opline->op1.var).var.ptr_ptr);
-               EX_T(opline->op1.var).var.ptr = 
*EX_T(opline->op1.var).var.ptr_ptr;
-       }
-
        if (0) {
                MAKE_REAL_ZVAL_PTR(property);
        }
@@ -39917,11 +39862,6 @@ static int ZEND_FASTCALL  
ZEND_FETCH_OBJ_W_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLE
        SAVE_OPLINE();
        property = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var 
TSRMLS_CC);
 
-       if (IS_CV == IS_VAR && (opline->extended_value & ZEND_FETCH_ADD_LOCK)) {
-               PZVAL_LOCK(*EX_T(opline->op1.var).var.ptr_ptr);
-               EX_T(opline->op1.var).var.ptr = 
*EX_T(opline->op1.var).var.ptr_ptr;
-       }
-
        if (0) {
                MAKE_REAL_ZVAL_PTR(property);
        }
-- 
PHP CVS Mailing List (http://www.php.net/)
To unsubscribe, visit: http://www.php.net/unsub.php

Reply via email to