From 62e921f82438eabc6bfc9ac558a0104608709564 Mon Sep 17 00:00:00 2001 From: Zeev Suraski Date: Wed, 25 Feb 2004 17:23:50 +0000 Subject: [PATCH] Fix leak in foreach ($o->mthd()->arr) --- Zend/zend_compile.c | 18 ++++++++++++++++-- Zend/zend_execute.c | 1 + 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c index 559d177581..3f627563de 100644 --- a/Zend/zend_compile.c +++ b/Zend/zend_compile.c @@ -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)); diff --git a/Zend/zend_execute.c b/Zend/zend_execute.c index d6f263b1d2..f0fc74db6f 100644 --- a/Zend/zend_execute.c +++ b/Zend/zend_execute.c @@ -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(); -- 2.40.0