summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNikita Popov <nikita.ppv@gmail.com>2019-10-29 15:06:28 +0100
committerNikita Popov <nikita.ppv@gmail.com>2019-10-29 15:06:52 +0100
commit33dd25d21c2dc4306c3b4d7ce50cf9d5186723ef (patch)
treea2102b220a5055882ef682dfd8acf4e72630d79c
parent8c2b3b056857a1d3c049f7adacf082a0941bfa62 (diff)
parentf9895b4bf5c6cdef0106f763cd95d95e98f039ae (diff)
downloadphp-git-33dd25d21c2dc4306c3b4d7ce50cf9d5186723ef.tar.gz
Merge branch 'PHP-7.2' into PHP-7.3
* PHP-7.2: Fixed bug #78689
-rw-r--r--NEWS2
-rw-r--r--Zend/tests/bug78689.phpt13
-rw-r--r--Zend/zend_closures.c9
3 files changed, 23 insertions, 1 deletions
diff --git a/NEWS b/NEWS
index c03d16720c..c31556dceb 100644
--- a/NEWS
+++ b/NEWS
@@ -8,6 +8,8 @@ PHP NEWS
Lundin)
. Fixed bug #78752 (Segfault if GC triggered while generator stack frame is
being destroyed). (Nikita)
+ . Fixed bug #78689 (Closure::fromCallable() doesn't handle
+ [Closure, '__invoke']). (Nikita)
- COM:
. Fixed bug #78694 (Appending to a variant array causes segfault). (cmb)
diff --git a/Zend/tests/bug78689.phpt b/Zend/tests/bug78689.phpt
new file mode 100644
index 0000000000..2273fd3532
--- /dev/null
+++ b/Zend/tests/bug78689.phpt
@@ -0,0 +1,13 @@
+--TEST--
+Bug #78689: Closure::fromCallable() doesn't handle [Closure, '__invoke']
+--FILE--
+<?php
+$a = [function () { echo "123\n"; }, '__invoke'];
+$a();
+
+$b = Closure::fromCallable($a);
+$b();
+?>
+--EXPECT--
+123
+123
diff --git a/Zend/zend_closures.c b/Zend/zend_closures.c
index fce69f12ff..96c3a5cc2d 100644
--- a/Zend/zend_closures.c
+++ b/Zend/zend_closures.c
@@ -268,8 +268,15 @@ static int zend_create_closure_from_callable(zval *return_value, zval *callable,
mptr = fcc.function_handler;
if (mptr->common.fn_flags & ZEND_ACC_CALL_VIA_TRAMPOLINE) {
- memset(&call, 0, sizeof(zend_internal_function));
+ /* For Closure::fromCallable([$closure, "__invoke"]) return $closure. */
+ if (fcc.object && fcc.object->ce == zend_ce_closure
+ && zend_string_equals_literal(mptr->common.function_name, "__invoke")) {
+ ZVAL_OBJ(return_value, fcc.object);
+ zend_free_trampoline(mptr);
+ return SUCCESS;
+ }
+ memset(&call, 0, sizeof(zend_internal_function));
call.type = ZEND_INTERNAL_FUNCTION;
call.fn_flags = mptr->common.fn_flags & ZEND_ACC_STATIC;
call.handler = zend_closure_call_magic;