mirror of
https://github.com/php/php-src.git
synced 2024-09-21 18:07:23 +00:00
Fixed bug #54367 (Use of closure causes problem in ArrayAccess).
This commit is contained in:
parent
1dd5690af2
commit
c157f4b4e6
1
NEWS
1
NEWS
@ -7,6 +7,7 @@ PHP NEWS
|
||||
. Fixed bug #54372 (Crash accessing global object itself returned from its
|
||||
__get() handle). (Dmitry)
|
||||
. Fixed bug #54358 (Closure, use and reference). (Dmitry)
|
||||
. Fixed bug #54367 (Use of closure causes problem in ArrayAccess). (Dmitry)
|
||||
. Fixed bug #54039 (use() of static variables in lambda functions can break
|
||||
staticness). (Dmitry)
|
||||
. Fixed bug #54262 (Crash when assigning value to a dimension in a non-array).
|
||||
|
24
Zend/tests/bug54367.phpt
Normal file
24
Zend/tests/bug54367.phpt
Normal file
@ -0,0 +1,24 @@
|
||||
--TEST--
|
||||
Bug #54367 (Use of closure causes problem in ArrayAccess)
|
||||
--FILE--
|
||||
<?php
|
||||
class MyObjet implements ArrayAccess
|
||||
{
|
||||
public function offsetSet($offset, $value) { }
|
||||
public function offsetExists($offset) { }
|
||||
public function offsetUnset($offset) { }
|
||||
|
||||
public function offsetGet ($offset)
|
||||
{
|
||||
return function ($var) use ($offset) { // here is the problem
|
||||
var_dump($offset, $var);
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
$a = new MyObjet();
|
||||
echo $a['p']('foo');
|
||||
?>
|
||||
--EXPECT--
|
||||
string(1) "p"
|
||||
string(3) "foo"
|
@ -373,6 +373,7 @@ ZEND_API void zend_create_closure(zval *res, zend_function *func TSRMLS_DC) /* {
|
||||
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) {
|
||||
|
@ -2087,14 +2087,20 @@ ZEND_VM_HANDLER(59, ZEND_INIT_FCALL_BY_NAME, ANY, CONST|TMP|VAR|CV)
|
||||
} else {
|
||||
function_name = GET_OP2_ZVAL_PTR(BP_VAR_R);
|
||||
|
||||
if (OP2_TYPE != IS_CONST &&
|
||||
if (OP2_TYPE != IS_CONST && OP2_TYPE != IS_TMP_VAR &&
|
||||
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();
|
||||
}
|
||||
ZEND_VM_NEXT_OPCODE();
|
||||
}
|
||||
|
||||
@ -2159,6 +2165,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);
|
||||
|
@ -163,6 +163,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);
|
||||
@ -750,14 +754,20 @@ static int ZEND_FASTCALL ZEND_INIT_FCALL_BY_NAME_SPEC_CONST_HANDLER(ZEND_OPCODE
|
||||
} else {
|
||||
function_name = &opline->op2.u.constant;
|
||||
|
||||
if (IS_CONST != IS_CONST &&
|
||||
if (IS_CONST != IS_CONST && IS_CONST != IS_TMP_VAR &&
|
||||
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 {
|
||||
|
||||
}
|
||||
ZEND_VM_NEXT_OPCODE();
|
||||
}
|
||||
|
||||
@ -944,14 +954,20 @@ static int ZEND_FASTCALL ZEND_INIT_FCALL_BY_NAME_SPEC_TMP_HANDLER(ZEND_OPCODE_H
|
||||
} else {
|
||||
function_name = _get_zval_ptr_tmp(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC);
|
||||
|
||||
if (IS_TMP_VAR != IS_CONST &&
|
||||
if (IS_TMP_VAR != IS_CONST && IS_TMP_VAR != IS_TMP_VAR &&
|
||||
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);
|
||||
}
|
||||
ZEND_VM_NEXT_OPCODE();
|
||||
}
|
||||
|
||||
@ -1045,14 +1061,20 @@ static int ZEND_FASTCALL ZEND_INIT_FCALL_BY_NAME_SPEC_VAR_HANDLER(ZEND_OPCODE_H
|
||||
} else {
|
||||
function_name = _get_zval_ptr_var(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC);
|
||||
|
||||
if (IS_VAR != IS_CONST &&
|
||||
if (IS_VAR != IS_CONST && IS_VAR != IS_TMP_VAR &&
|
||||
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);};
|
||||
}
|
||||
ZEND_VM_NEXT_OPCODE();
|
||||
}
|
||||
|
||||
@ -1169,14 +1191,20 @@ static int ZEND_FASTCALL ZEND_INIT_FCALL_BY_NAME_SPEC_CV_HANDLER(ZEND_OPCODE_HA
|
||||
} else {
|
||||
function_name = _get_zval_ptr_cv(&opline->op2, EX(Ts), BP_VAR_R TSRMLS_CC);
|
||||
|
||||
if (IS_CV != IS_CONST &&
|
||||
if (IS_CV != IS_CONST && IS_CV != IS_TMP_VAR &&
|
||||
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 {
|
||||
|
||||
}
|
||||
ZEND_VM_NEXT_OPCODE();
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user