]> granicus.if.org Git - php/commitdiff
Fix leak in foreach ($o->mthd()->arr)
authorZeev Suraski <zeev@php.net>
Wed, 25 Feb 2004 17:23:50 +0000 (17:23 +0000)
committerZeev Suraski <zeev@php.net>
Wed, 25 Feb 2004 17:23:50 +0000 (17:23 +0000)
Zend/zend_compile.c
Zend/zend_execute.c

index 559d1775818400d2f6647b1310be1e805fb022e7..3f627563deff815016bdea86ce837d56438a1a53 100644 (file)
@@ -1481,7 +1481,7 @@ static int generate_free_foreach_copy(znode *foreach_copy TSRMLS_DC)
 {
        zend_op *opline;
        
-       if (foreach_copy->op_type!=IS_VAR && foreach_copy->op_type!=IS_TMP_VAR) {
+       if (foreach_copy->op_type != IS_VAR && foreach_copy->op_type != IS_TMP_VAR) {
                return 1;
        }
 
@@ -3267,6 +3267,7 @@ void zend_do_foreach_begin(znode *foreach_token, znode *array, znode *open_brack
 {
        zend_op *opline;
        zend_bool is_variable;
+       zend_bool push_container = 0;
 
        if (variable) {
                if (zend_is_function_or_method_call(array)) {
@@ -3278,6 +3279,7 @@ void zend_do_foreach_begin(znode *foreach_token, znode *array, znode *open_brack
                if (CG(active_op_array)->opcodes[CG(active_op_array)->last-1].opcode == ZEND_FETCH_OBJ_W) {
                        /* FIXME:  This will cause a leak, we have to unlock at the end of foreach() */
                        CG(active_op_array)->opcodes[CG(active_op_array)->last-1].extended_value |= ZEND_FETCH_ADD_LOCK;
+                       push_container = 1;
                }
        } else {
                is_variable = 0;
@@ -3295,7 +3297,15 @@ void zend_do_foreach_begin(znode *foreach_token, znode *array, znode *open_brack
        *open_brackets_token = opline->result;
 
        zend_stack_push(&CG(foreach_copy_stack), (void *) &opline->result, sizeof(znode));
+       if (push_container) {
+               zend_stack_push(&CG(foreach_copy_stack), (void *) &CG(active_op_array)->opcodes[CG(active_op_array)->last-2].op1, sizeof(znode));
+       } else {
+               znode tmp;
 
+               tmp.op_type = IS_UNUSED;
+               zend_stack_push(&CG(foreach_copy_stack), (void *) &tmp, sizeof(znode));
+       }
+       
        /* save the location of the beginning of the loop (array fetching) */
        opline->op2.u.opline_num = foreach_token->u.opline_num = get_next_op_number(CG(active_op_array));
 
@@ -3381,6 +3391,7 @@ void zend_do_foreach_cont(znode *value, znode *key, znode *as_token, znode *fore
 
 void zend_do_foreach_end(znode *foreach_token, znode *open_brackets_token TSRMLS_DC)
 {
+       znode *container_ptr;
        zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
 
        opline->opcode = ZEND_JMP;
@@ -3392,8 +3403,11 @@ void zend_do_foreach_end(znode *foreach_token, znode *open_brackets_token TSRMLS
 
        do_end_loop(foreach_token->u.opline_num TSRMLS_CC);
 
-       generate_free_foreach_copy(open_brackets_token TSRMLS_CC);
+       zend_stack_top(&CG(foreach_copy_stack), &container_ptr);
+       generate_free_foreach_copy(container_ptr TSRMLS_CC);
+       zend_stack_del_top(&CG(foreach_copy_stack));
 
+       generate_free_foreach_copy(open_brackets_token TSRMLS_CC);
        zend_stack_del_top(&CG(foreach_copy_stack));
 
        DEC_BPC(CG(active_op_array));
index d6f263b1d20654123ec134d5a276a3464b2f6edb..f0fc74db6f7aa4cabda61ffc12e2023987574616 100644 (file)
@@ -2042,6 +2042,7 @@ int zend_fetch_obj_w_handler(ZEND_OPCODE_HANDLER_ARGS)
 {
        if (opline->extended_value == ZEND_FETCH_ADD_LOCK) {
                PZVAL_LOCK(*EX_T(opline->op1.u.var).var.ptr_ptr);
+               EX_T(opline->op1.u.var).var.ptr = *EX_T(opline->op1.u.var).var.ptr_ptr;
        }
        zend_fetch_property_address(&opline->result, &opline->op1, &opline->op2, EX(Ts), BP_VAR_W TSRMLS_CC);
        NEXT_OPCODE();