From 8ac91b705bc0a8a175653ffb8c665346b957cc93 Mon Sep 17 00:00:00 2001 From: "Christoph M. Becker" Date: Thu, 12 Nov 2020 13:45:08 +0100 Subject: [PATCH 1/3] Fix #74558: Can't rebind closure returned by Closure::fromCallable() We fix the error message. --- Zend/tests/closures/bug74558.phpt | 23 +++++++++++++++++++++++ Zend/zend_closures.c | 2 +- 2 files changed, 24 insertions(+), 1 deletion(-) create mode 100644 Zend/tests/closures/bug74558.phpt diff --git a/Zend/tests/closures/bug74558.phpt b/Zend/tests/closures/bug74558.phpt new file mode 100644 index 0000000000000..3f254f5b16fbe --- /dev/null +++ b/Zend/tests/closures/bug74558.phpt @@ -0,0 +1,23 @@ +--TEST-- +Bug #74558 (Can't rebind closure returned by Closure::fromCallable()) +--FILE-- +name = $name; + } +} + +function getName() { + return $this->name; +} + +$bob = new A("Bob"); + +$cl1 = Closure::fromCallable("getName"); +$cl1->bindTo($bob, A::class); +?> +--EXPECTF-- +Warning: Cannot rebind scope of closure in %s on line %d diff --git a/Zend/zend_closures.c b/Zend/zend_closures.c index 70dc469a481fb..c62fe27f1fc3f 100644 --- a/Zend/zend_closures.c +++ b/Zend/zend_closures.c @@ -104,7 +104,7 @@ 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()"); + zend_error(E_WARNING, "Cannot rebind scope of closure"); return 0; } From fb099a5814936f0aec1ddbf7ef6e3c1a586dde49 Mon Sep 17 00:00:00 2001 From: "Christoph M. Becker" Date: Thu, 12 Nov 2020 15:37:09 +0100 Subject: [PATCH 2/3] Improve error message We don't want to be too generic. --- Zend/zend_closures.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/Zend/zend_closures.c b/Zend/zend_closures.c index c62fe27f1fc3f..f60d83e256aac 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"); + 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; } From dcb64850a697344a93dfcf35bd7b746d171be37b Mon Sep 17 00:00:00 2001 From: "Christoph M. Becker" Date: Thu, 12 Nov 2020 15:37:51 +0100 Subject: [PATCH 3/3] Fix tests and remove newly introduced test --- Zend/tests/bug70630.phpt | 2 +- Zend/tests/bug70685.phpt | 2 +- Zend/tests/closure_061.phpt | 24 ++++++++++++------------ Zend/tests/closures/bug74558.phpt | 23 ----------------------- 4 files changed, 14 insertions(+), 37 deletions(-) delete mode 100644 Zend/tests/closures/bug74558.phpt diff --git a/Zend/tests/bug70630.phpt b/Zend/tests/bug70630.phpt index d78ee62c6aded..0e9e5449758f9 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 8ae97f1bf0cae..737b4469fdbe4 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 f01e3935704f9..41863fd0c0e69 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/tests/closures/bug74558.phpt b/Zend/tests/closures/bug74558.phpt deleted file mode 100644 index 3f254f5b16fbe..0000000000000 --- a/Zend/tests/closures/bug74558.phpt +++ /dev/null @@ -1,23 +0,0 @@ ---TEST-- -Bug #74558 (Can't rebind closure returned by Closure::fromCallable()) ---FILE-- -name = $name; - } -} - -function getName() { - return $this->name; -} - -$bob = new A("Bob"); - -$cl1 = Closure::fromCallable("getName"); -$cl1->bindTo($bob, A::class); -?> ---EXPECTF-- -Warning: Cannot rebind scope of closure in %s on line %d