summaryrefslogtreecommitdiff
path: root/Zend
diff options
context:
space:
mode:
authorNikita Popov <nikic@php.net>2016-03-29 23:48:07 +0200
committerNikita Popov <nikic@php.net>2016-04-08 00:38:44 +0200
commit75af8150f58fb55637ac12b33d469b27adef9d76 (patch)
tree682e004586b35e5ecb368a6f29e082779d15cd42 /Zend
parentaed42496534fe54c5c0ce64fe0ca5c9d801d6161 (diff)
downloadphp-git-75af8150f58fb55637ac12b33d469b27adef9d76.tar.gz
Forbid binding methods to incompatible $this
This prohibits binding closures returned by ReflectionMethod::getClosure() to a $this, which is not an instance of the method scope. This restriction was already in place for internal methods, now it is extended to user methods. ML discussion: http://markmail.org/message/zepnhdyr3kij6di6
Diffstat (limited to 'Zend')
-rw-r--r--Zend/tests/bug70685.phpt2
-rw-r--r--Zend/tests/closure_061.phpt4
-rw-r--r--Zend/zend_closures.c7
3 files changed, 7 insertions, 6 deletions
diff --git a/Zend/tests/bug70685.phpt b/Zend/tests/bug70685.phpt
index 7a49ff1825..8ae97f1bf0 100644
--- a/Zend/tests/bug70685.phpt
+++ b/Zend/tests/bug70685.phpt
@@ -15,7 +15,7 @@ var_dump($c);
?>
--EXPECTF--
-Warning: Cannot bind internal method SplDoublyLinkedList::count() to object of class cls in %s on line %d
+Warning: Cannot bind method SplDoublyLinkedList::count() to object of class cls in %s on line %d
NULL
Warning: Cannot rebind scope of closure created by ReflectionFunctionAbstract::getClosure() in %s on line %d
diff --git a/Zend/tests/closure_061.phpt b/Zend/tests/closure_061.phpt
index 83ad16d2e1..1aa579a409 100644
--- a/Zend/tests/closure_061.phpt
+++ b/Zend/tests/closure_061.phpt
@@ -184,7 +184,7 @@ bindTo(new ClsChild, Cls::class):
Success!
bindTo(new ClsUnrelated, Cls::class):
-Success!
+Cannot bind method Cls::method() to object of class ClsUnrelated
bindTo(new Cls, null):
Cannot rebind scope of closure created by ReflectionFunctionAbstract::getClosure()
@@ -205,7 +205,7 @@ bindTo(new SplStack, SplDoublyLinkedList::class):
Success!
bindTo(new ClsUnrelated, SplDoublyLinkedList::class):
-Cannot bind internal method SplDoublyLinkedList::count() to object of class ClsUnrelated
+Cannot bind method SplDoublyLinkedList::count() to object of class ClsUnrelated
bindTo(null, null):
Cannot unbind $this of internal method
diff --git a/Zend/zend_closures.c b/Zend/zend_closures.c
index d52d0b5c25..fd0738f32f 100644
--- a/Zend/zend_closures.c
+++ b/Zend/zend_closures.c
@@ -77,16 +77,17 @@ static zend_bool zend_valid_closure_binding(
zend_closure *closure, zval *newthis, zend_class_entry *scope) /* {{{ */
{
zend_function *func = &closure->func;
+ zend_bool is_fake_closure = (func->common.fn_flags & ZEND_ACC_FAKE_CLOSURE) != 0;
if (newthis) {
if (func->common.fn_flags & ZEND_ACC_STATIC) {
zend_error(E_WARNING, "Cannot bind an instance to a static closure");
return 0;
}
- if (func->type == ZEND_INTERNAL_FUNCTION && func->common.scope &&
+ if (is_fake_closure && func->common.scope &&
!instanceof_function(Z_OBJCE_P(newthis), func->common.scope)) {
/* Binding incompatible $this to an internal method is not supported. */
- zend_error(E_WARNING, "Cannot bind internal method %s::%s() to object of class %s",
+ zend_error(E_WARNING, "Cannot bind method %s::%s() to object of class %s",
ZSTR_VAL(func->common.scope->name),
ZSTR_VAL(func->common.function_name),
ZSTR_VAL(Z_OBJCE_P(newthis)->name));
@@ -105,7 +106,7 @@ static zend_bool zend_valid_closure_binding(
return 0;
}
- if ((func->common.fn_flags & ZEND_ACC_FAKE_CLOSURE) && scope != func->common.scope) {
+ if (is_fake_closure && scope != func->common.scope) {
zend_error(E_WARNING, "Cannot rebind scope of closure created by ReflectionFunctionAbstract::getClosure()");
return 0;
}