From 78773890f6b0d82b29e0b869f3f3b22174cea217 Mon Sep 17 00:00:00 2001 From: "Christoph M. Becker" Date: Thu, 12 Nov 2020 15:37:51 +0100 Subject: [PATCH] Fix #74558: Can't rebind closure returned by Closure::fromCallable() Failure to rebind such closures is not necessarily related to them being created by `ReflectionFunctionAbstract::getClosure()`, so we fix the error message. Closes GH-6424. --- NEWS | 3 +++ Zend/tests/bug70630.phpt | 2 +- Zend/tests/bug70685.phpt | 2 +- Zend/tests/closure_061.phpt | 24 ++++++++++++------------ Zend/zend_closures.c | 6 +++++- 5 files changed, 22 insertions(+), 15 deletions(-) diff --git a/NEWS b/NEWS index e3857955378..747a354855e 100644 --- a/NEWS +++ b/NEWS @@ -2,6 +2,9 @@ PHP NEWS ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| ?? ??? ????, PHP 7.4.14 +- Core: + . Fixed bug #74558 (Can't rebind closure returned by Closure::fromCallable()). + (cmb) 26 Nov 2020, PHP 7.4.13 diff --git a/Zend/tests/bug70630.phpt b/Zend/tests/bug70630.phpt index d78ee62c6ad..0e9e5449758 100644 --- a/Zend/tests/bug70630.phpt +++ b/Zend/tests/bug70630.phpt @@ -7,4 +7,4 @@ $x = (new ReflectionFunction("substr"))->getClosure(); $x->call(new a); ?> --EXPECTF-- -Warning: Cannot rebind scope of closure created by ReflectionFunctionAbstract::getClosure() in %s on line %d +Warning: Cannot rebind scope of closure created from function in %s on line %d diff --git a/Zend/tests/bug70685.phpt b/Zend/tests/bug70685.phpt index 8ae97f1bf0c..737b4469fdb 100644 --- a/Zend/tests/bug70685.phpt +++ b/Zend/tests/bug70685.phpt @@ -18,5 +18,5 @@ var_dump($c); 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 +Warning: Cannot rebind scope of closure created from method in %s on line %d NULL diff --git a/Zend/tests/closure_061.phpt b/Zend/tests/closure_061.phpt index f01e3935704..41863fd0c0e 100644 --- a/Zend/tests/closure_061.phpt +++ b/Zend/tests/closure_061.phpt @@ -118,10 +118,10 @@ bindTo(new Cls, null): Success! bindTo(new Cls, Cls::class): -Cannot rebind scope of closure created by ReflectionFunctionAbstract::getClosure() +Cannot rebind scope of closure created from function bindTo(null, Cls::class): -Cannot rebind scope of closure created by ReflectionFunctionAbstract::getClosure() +Cannot rebind scope of closure created from function bindTo(null, stdClass::class): Cannot bind closure to scope of internal class stdClass @@ -139,10 +139,10 @@ bindTo(new Cls, null): Success! bindTo(new Cls, Cls::class): -Cannot rebind scope of closure created by ReflectionFunctionAbstract::getClosure() +Cannot rebind scope of closure created from function bindTo(null, Cls::class): -Cannot rebind scope of closure created by ReflectionFunctionAbstract::getClosure() +Cannot rebind scope of closure created from function bindTo(null, stdClass::class): Cannot bind closure to scope of internal class stdClass @@ -163,13 +163,13 @@ bindTo(new Cls, Cls::class): Cannot bind an instance to a static closure bindTo(null, null): -Cannot rebind scope of closure created by ReflectionFunctionAbstract::getClosure() +Cannot rebind scope of closure created from method bindTo(null, ClsChild::class): -Cannot rebind scope of closure created by ReflectionFunctionAbstract::getClosure() +Cannot rebind scope of closure created from method bindTo(null, ClsUnrelated::class): -Cannot rebind scope of closure created by ReflectionFunctionAbstract::getClosure() +Cannot rebind scope of closure created from method (new Cls)->method() ------------------- @@ -189,13 +189,13 @@ bindTo(new ClsUnrelated, Cls::class): Cannot bind method Cls::method() to object of class ClsUnrelated bindTo(new Cls, null): -Cannot rebind scope of closure created by ReflectionFunctionAbstract::getClosure() +Cannot rebind scope of closure created from method bindTo(new Cls, ClsUnrelated::class): -Cannot rebind scope of closure created by ReflectionFunctionAbstract::getClosure() +Cannot rebind scope of closure created from method bindTo(new Cls, ClsChild::class): -Cannot rebind scope of closure created by ReflectionFunctionAbstract::getClosure() +Cannot rebind scope of closure created from method (new SplDoublyLinkedList)->count() ---------------------------------- @@ -216,10 +216,10 @@ bindTo(null, SplDoublyLinkedList::class): Cannot unbind $this of internal method bindTo(new SplDoublyLinkedList, null): -Cannot rebind scope of closure created by ReflectionFunctionAbstract::getClosure() +Cannot rebind scope of closure created from method bindTo(new SplDoublyLinkedList, ClsUnrelated::class): -Cannot rebind scope of closure created by ReflectionFunctionAbstract::getClosure() +Cannot rebind scope of closure created from method (function() {})() ----------------- diff --git a/Zend/zend_closures.c b/Zend/zend_closures.c index 70dc469a481..f60d83e256a 100644 --- a/Zend/zend_closures.c +++ b/Zend/zend_closures.c @@ -104,7 +104,11 @@ static zend_bool zend_valid_closure_binding( } if (is_fake_closure && scope != func->common.scope) { - zend_error(E_WARNING, "Cannot rebind scope of closure created by ReflectionFunctionAbstract::getClosure()"); + if (func->common.scope == NULL) { + zend_error(E_WARNING, "Cannot rebind scope of closure created from function"); + } else { + zend_error(E_WARNING, "Cannot rebind scope of closure created from method"); + } return 0; }