com php-src: Fix static closure error in call_user_func o pcode: Zend/tests/call_user_func_closure_from_sta tic_method.phpt Zend/zend_vm_def.h
Zend/zend_vm _execute.h
| From: | Nikita Popov | Date: | Fri, 08 May 2015 13:17:15 +0000 |
| Subject: | com php-src: Fix static closure error in call_user_func o pcode: Zend/tests/call_user_func_closure_from_sta tic_method.phpt Zend/zend_vm_def.h Zend/zend_vm _execute.h |
||
| Groups: | php.cvs | ||
| Request: | Send a blank email to php-cvs+get-86654@lists.php.net to get a copy of this message | ||
Commit: 8f9f21e8d24c1b48dc271330e38f2931086c0c94
Author: Nikita Popov <nikic@php.net> Fri, 8 May 2015 15:05:59 +0200
Parents: 9d4465e480675dd5e1aa464c4cf2a0c9d646a65a
Branches: master
Link: http://git.php.net/?p=php-src.git;a=commitdiff;h=8f9f21e8d24c1b48dc271330e38f2931086c0c94
Log:
Fix static closure error in call_user_func opcode
I'm assuming this is the only error that is_callable() can generate
with retval=1.
This problem manifested after making closures in static methods
not implicitly static, but would also occur when binding any non-static
closure to a scope without a $this.
Changed paths:
A Zend/tests/call_user_func_closure_from_static_method.phpt
M Zend/zend_vm_def.h
M Zend/zend_vm_execute.h
Diff:
diff --git a/Zend/tests/call_user_func_closure_from_static_method.phpt
b/Zend/tests/call_user_func_closure_from_static_method.phpt
new file mode 100644
index 0000000..b427b85
--- /dev/null
+++ b/Zend/tests/call_user_func_closure_from_static_method.phpt
@@ -0,0 +1,22 @@
+--TEST--
+call_user_func() on non-static closure without $this inside a static method
+--FILE--
+<?php
+
+class A {
+ public static function exec(callable $c) {
+ return call_user_func($c);
+ }
+
+ public static function doSomething() {
+ return self::exec(function(){
+ return "okay";
+ });
+ }
+}
+
+var_dump(A::doSomething());
+
+?>
+--EXPECT--
+string(4) "okay"
diff --git a/Zend/zend_vm_def.h b/Zend/zend_vm_def.h
index 95022ac..7d324fe 100644
--- a/Zend/zend_vm_def.h
+++ b/Zend/zend_vm_def.h
@@ -3314,9 +3314,6 @@ ZEND_VM_HANDLER(118, ZEND_INIT_USER_CALL, CONST, CONST|TMPVAR|CV)
SAVE_OPLINE();
function_name = GET_OP2_ZVAL_PTR(BP_VAR_R);
if (zend_is_callable_ex(function_name, NULL, 0, NULL, &fcc, &error)) {
- if (error) {
- efree(error);
- }
func = fcc.function_handler;
if (func->common.fn_flags & ZEND_ACC_CLOSURE) {
/* Delay closure destruction until its invocation */
@@ -3332,20 +3329,13 @@ ZEND_VM_HANDLER(118, ZEND_INIT_USER_CALL, CONST, CONST|TMPVAR|CV)
if (object) {
call_info |= ZEND_CALL_RELEASE_THIS;
GC_REFCOUNT(object)++; /* For $this pointer */
- } else if (func->common.scope &&
- !(func->common.fn_flags & ZEND_ACC_STATIC)) {
- if (func->common.fn_flags & ZEND_ACC_ALLOW_STATIC) {
- zend_error(E_DEPRECATED,
+ }
+ if (error) {
+ efree(error);
+ /* This is the only soft error is_callable() can generate */
+ zend_error(E_DEPRECATED,
"Non-static method %s::%s() should not be called statically",
func->common.scope->name->val, func->common.function_name->val);
- } else {
- zend_error(
- E_EXCEPTION | E_ERROR,
- "Non-static method %s::%s() cannot be called statically",
- func->common.scope->name->val, func->common.function_name->val);
- FREE_OP2();
- HANDLE_EXCEPTION();
- }
}
} else {
zend_internal_type_error(EX_USES_STRICT_TYPES(), "%s() expects parameter 1 to be a valid
callback, %s", Z_STRVAL_P(EX_CONSTANT(opline->op1)), error);
diff --git a/Zend/zend_vm_execute.h b/Zend/zend_vm_execute.h
index f4bdf0d..7abf0f9 100644
--- a/Zend/zend_vm_execute.h
+++ b/Zend/zend_vm_execute.h
@@ -5649,9 +5649,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL
ZEND_INIT_USER_CALL_SPEC_CONST_CONS
SAVE_OPLINE();
function_name = EX_CONSTANT(opline->op2);
if (zend_is_callable_ex(function_name, NULL, 0, NULL, &fcc, &error)) {
- if (error) {
- efree(error);
- }
func = fcc.function_handler;
if (func->common.fn_flags & ZEND_ACC_CLOSURE) {
/* Delay closure destruction until its invocation */
@@ -5667,20 +5664,13 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL
ZEND_INIT_USER_CALL_SPEC_CONST_CONS
if (object) {
call_info |= ZEND_CALL_RELEASE_THIS;
GC_REFCOUNT(object)++; /* For $this pointer */
- } else if (func->common.scope &&
- !(func->common.fn_flags & ZEND_ACC_STATIC)) {
- if (func->common.fn_flags & ZEND_ACC_ALLOW_STATIC) {
- zend_error(E_DEPRECATED,
+ }
+ if (error) {
+ efree(error);
+ /* This is the only soft error is_callable() can generate */
+ zend_error(E_DEPRECATED,
"Non-static method %s::%s() should not be called statically",
func->common.scope->name->val, func->common.function_name->val);
- } else {
- zend_error(
- E_EXCEPTION | E_ERROR,
- "Non-static method %s::%s() cannot be called statically",
- func->common.scope->name->val, func->common.function_name->val);
-
- HANDLE_EXCEPTION();
- }
}
} else {
zend_internal_type_error(EX_USES_STRICT_TYPES(), "%s() expects parameter 1 to be a valid
callback, %s", Z_STRVAL_P(EX_CONSTANT(opline->op1)), error);
@@ -9296,9 +9286,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL
ZEND_INIT_USER_CALL_SPEC_CONST_CV_H
SAVE_OPLINE();
function_name = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var);
if (zend_is_callable_ex(function_name, NULL, 0, NULL, &fcc, &error)) {
- if (error) {
- efree(error);
- }
func = fcc.function_handler;
if (func->common.fn_flags & ZEND_ACC_CLOSURE) {
/* Delay closure destruction until its invocation */
@@ -9314,20 +9301,13 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL
ZEND_INIT_USER_CALL_SPEC_CONST_CV_H
if (object) {
call_info |= ZEND_CALL_RELEASE_THIS;
GC_REFCOUNT(object)++; /* For $this pointer */
- } else if (func->common.scope &&
- !(func->common.fn_flags & ZEND_ACC_STATIC)) {
- if (func->common.fn_flags & ZEND_ACC_ALLOW_STATIC) {
- zend_error(E_DEPRECATED,
+ }
+ if (error) {
+ efree(error);
+ /* This is the only soft error is_callable() can generate */
+ zend_error(E_DEPRECATED,
"Non-static method %s::%s() should not be called statically",
func->common.scope->name->val, func->common.function_name->val);
- } else {
- zend_error(
- E_EXCEPTION | E_ERROR,
- "Non-static method %s::%s() cannot be called statically",
- func->common.scope->name->val, func->common.function_name->val);
-
- HANDLE_EXCEPTION();
- }
}
} else {
zend_internal_type_error(EX_USES_STRICT_TYPES(), "%s() expects parameter 1 to be a valid
callback, %s", Z_STRVAL_P(EX_CONSTANT(opline->op1)), error);
@@ -11032,9 +11012,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL
ZEND_INIT_USER_CALL_SPEC_CONST_TMPV
SAVE_OPLINE();
function_name = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2);
if (zend_is_callable_ex(function_name, NULL, 0, NULL, &fcc, &error)) {
- if (error) {
- efree(error);
- }
func = fcc.function_handler;
if (func->common.fn_flags & ZEND_ACC_CLOSURE) {
/* Delay closure destruction until its invocation */
@@ -11050,20 +11027,13 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL
ZEND_INIT_USER_CALL_SPEC_CONST_TMPV
if (object) {
call_info |= ZEND_CALL_RELEASE_THIS;
GC_REFCOUNT(object)++; /* For $this pointer */
- } else if (func->common.scope &&
- !(func->common.fn_flags & ZEND_ACC_STATIC)) {
- if (func->common.fn_flags & ZEND_ACC_ALLOW_STATIC) {
- zend_error(E_DEPRECATED,
+ }
+ if (error) {
+ efree(error);
+ /* This is the only soft error is_callable() can generate */
+ zend_error(E_DEPRECATED,
"Non-static method %s::%s() should not be called statically",
func->common.scope->name->val, func->common.function_name->val);
- } else {
- zend_error(
- E_EXCEPTION | E_ERROR,
- "Non-static method %s::%s() cannot be called statically",
- func->common.scope->name->val, func->common.function_name->val);
- zval_ptr_dtor_nogc(free_op2);
- HANDLE_EXCEPTION();
- }
}
} else {
zend_internal_type_error(EX_USES_STRICT_TYPES(), "%s() expects parameter 1 to be a valid
callback, %s", Z_STRVAL_P(EX_CONSTANT(opline->op1)), error);