From 75af8150f58fb55637ac12b33d469b27adef9d76 Mon Sep 17 00:00:00 2001 From: Nikita Popov Date: Tue, 29 Mar 2016 23:48:07 +0200 Subject: [PATCH] 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 --- Zend/tests/bug70685.phpt | 2 +- Zend/tests/closure_061.phpt | 4 ++-- Zend/zend_closures.c | 7 ++++--- 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; } -- 2.50.1