From: Dmitry Stogov Date: Wed, 20 Apr 2011 12:59:18 +0000 (+0000) Subject: Fixed bug #54367 (Use of closure causes problem in ArrayAccess). X-Git-Tag: php-5.4.0alpha1~191^2~58 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=821d7169d9d575ceef71e69570b98519826ccb01;p=php Fixed bug #54367 (Use of closure causes problem in ArrayAccess). --- diff --git a/Zend/tests/bug54367.phpt b/Zend/tests/bug54367.phpt new file mode 100644 index 0000000000..1ca6ad4252 --- /dev/null +++ b/Zend/tests/bug54367.phpt @@ -0,0 +1,24 @@ +--TEST-- +Bug #54367 (Use of closure causes problem in ArrayAccess) +--FILE-- + +--EXPECT-- +string(1) "p" +string(3) "foo" diff --git a/Zend/zend_closures.c b/Zend/zend_closures.c index f7220bf907..3ea3eba783 100644 --- a/Zend/zend_closures.c +++ b/Zend/zend_closures.c @@ -407,6 +407,7 @@ ZEND_API void zend_create_closure(zval *res, zend_function *func, zend_class_ent closure = (zend_closure *)zend_object_store_get_object(res TSRMLS_CC); closure->func = *func; + closure->func.common.prototype = NULL; if (closure->func.type == ZEND_USER_FUNCTION) { if (closure->func.op_array.static_variables) { diff --git a/Zend/zend_vm_def.h b/Zend/zend_vm_def.h index 8de53845a5..8b8e3450b5 100644 --- a/Zend/zend_vm_def.h +++ b/Zend/zend_vm_def.h @@ -2370,14 +2370,20 @@ ZEND_VM_HANDLER(59, ZEND_INIT_FCALL_BY_NAME, ANY, CONST|TMP|VAR|CV) EX(object) = NULL; CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); - } else if (OP2_TYPE != IS_CONST && + } else if (OP2_TYPE != IS_CONST && OP2_TYPE != IS_TMP_VAR && EXPECTED(Z_TYPE_P(function_name) == IS_OBJECT) && Z_OBJ_HANDLER_P(function_name, get_closure) && Z_OBJ_HANDLER_P(function_name, get_closure)(function_name, &EX(called_scope), &EX(fbc), &EX(object) TSRMLS_CC) == SUCCESS) { if (EX(object)) { Z_ADDREF_P(EX(object)); } - FREE_OP2(); + if (OP2_TYPE == IS_VAR && OP2_FREE && + EX(fbc)->common.fn_flags & ZEND_ACC_CLOSURE) { + /* Delay closure destruction until its invocation */ + EX(fbc)->common.prototype = (zend_function*)function_name; + } else { + FREE_OP2(); + } CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } else { @@ -2431,6 +2437,10 @@ ZEND_VM_HELPER(zend_leave_helper, ANY, ANY) } } + if ((op_array->fn_flags & ZEND_ACC_CLOSURE) && op_array->prototype) { + zval_ptr_dtor((zval**)&op_array->prototype); + } + nested = EX(nested); zend_vm_stack_free(execute_data TSRMLS_CC); diff --git a/Zend/zend_vm_execute.h b/Zend/zend_vm_execute.h index ea83b6f441..001c5295e8 100644 --- a/Zend/zend_vm_execute.h +++ b/Zend/zend_vm_execute.h @@ -471,6 +471,10 @@ static int ZEND_FASTCALL zend_leave_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS) } } + if ((op_array->fn_flags & ZEND_ACC_CLOSURE) && op_array->prototype) { + zval_ptr_dtor((zval**)&op_array->prototype); + } + nested = EX(nested); zend_vm_stack_free(execute_data TSRMLS_CC); @@ -1224,14 +1228,20 @@ static int ZEND_FASTCALL ZEND_INIT_FCALL_BY_NAME_SPEC_CONST_HANDLER(ZEND_OPCODE EX(object) = NULL; CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); - } else if (IS_CONST != IS_CONST && + } else if (IS_CONST != IS_CONST && IS_CONST != IS_TMP_VAR && EXPECTED(Z_TYPE_P(function_name) == IS_OBJECT) && Z_OBJ_HANDLER_P(function_name, get_closure) && Z_OBJ_HANDLER_P(function_name, get_closure)(function_name, &EX(called_scope), &EX(fbc), &EX(object) TSRMLS_CC) == SUCCESS) { if (EX(object)) { Z_ADDREF_P(EX(object)); } + if (IS_CONST == IS_VAR && 0 && + EX(fbc)->common.fn_flags & ZEND_ACC_CLOSURE) { + /* Delay closure destruction until its invocation */ + EX(fbc)->common.prototype = (zend_function*)function_name; + } else { + } CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } else { @@ -1458,14 +1468,20 @@ static int ZEND_FASTCALL ZEND_INIT_FCALL_BY_NAME_SPEC_TMP_HANDLER(ZEND_OPCODE_H EX(object) = NULL; CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); - } else if (IS_TMP_VAR != IS_CONST && + } else if (IS_TMP_VAR != IS_CONST && IS_TMP_VAR != IS_TMP_VAR && EXPECTED(Z_TYPE_P(function_name) == IS_OBJECT) && Z_OBJ_HANDLER_P(function_name, get_closure) && Z_OBJ_HANDLER_P(function_name, get_closure)(function_name, &EX(called_scope), &EX(fbc), &EX(object) TSRMLS_CC) == SUCCESS) { if (EX(object)) { Z_ADDREF_P(EX(object)); } - zval_dtor(free_op2.var); + if (IS_TMP_VAR == IS_VAR && 1 && + EX(fbc)->common.fn_flags & ZEND_ACC_CLOSURE) { + /* Delay closure destruction until its invocation */ + EX(fbc)->common.prototype = (zend_function*)function_name; + } else { + zval_dtor(free_op2.var); + } CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } else { @@ -1554,14 +1570,20 @@ static int ZEND_FASTCALL ZEND_INIT_FCALL_BY_NAME_SPEC_VAR_HANDLER(ZEND_OPCODE_H EX(object) = NULL; CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); - } else if (IS_VAR != IS_CONST && + } else if (IS_VAR != IS_CONST && IS_VAR != IS_TMP_VAR && EXPECTED(Z_TYPE_P(function_name) == IS_OBJECT) && Z_OBJ_HANDLER_P(function_name, get_closure) && Z_OBJ_HANDLER_P(function_name, get_closure)(function_name, &EX(called_scope), &EX(fbc), &EX(object) TSRMLS_CC) == SUCCESS) { if (EX(object)) { Z_ADDREF_P(EX(object)); } - if (free_op2.var) {zval_ptr_dtor(&free_op2.var);}; + if (IS_VAR == IS_VAR && (free_op2.var != NULL) && + EX(fbc)->common.fn_flags & ZEND_ACC_CLOSURE) { + /* Delay closure destruction until its invocation */ + EX(fbc)->common.prototype = (zend_function*)function_name; + } else { + if (free_op2.var) {zval_ptr_dtor(&free_op2.var);}; + } CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } else { @@ -1683,14 +1705,20 @@ static int ZEND_FASTCALL ZEND_INIT_FCALL_BY_NAME_SPEC_CV_HANDLER(ZEND_OPCODE_HA EX(object) = NULL; CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); - } else if (IS_CV != IS_CONST && + } else if (IS_CV != IS_CONST && IS_CV != IS_TMP_VAR && EXPECTED(Z_TYPE_P(function_name) == IS_OBJECT) && Z_OBJ_HANDLER_P(function_name, get_closure) && Z_OBJ_HANDLER_P(function_name, get_closure)(function_name, &EX(called_scope), &EX(fbc), &EX(object) TSRMLS_CC) == SUCCESS) { if (EX(object)) { Z_ADDREF_P(EX(object)); } + if (IS_CV == IS_VAR && 0 && + EX(fbc)->common.fn_flags & ZEND_ACC_CLOSURE) { + /* Delay closure destruction until its invocation */ + EX(fbc)->common.prototype = (zend_function*)function_name; + } else { + } CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } else {