|  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #78689 Closure::fromCallable() doesn't handle [Closure, '__invoke']
Submitted: 2019-10-18 12:06 UTC Modified: 2019-10-28 11:31 UTC
From: nicolas dot grekas+php at gmail dot com Assigned:
Status: Closed Package: Scripting Engine problem
PHP Version: 7.3.10 OS:
Private report: No CVE-ID: None
 [2019-10-18 12:06 UTC] nicolas dot grekas+php at gmail dot com
php > $a = [function () { echo 123; }, '__invoke'];
php > $a();
php > $b = Closure::fromCallable($a);
php > $b();
PHP Warning:  Invalid callback , no array or string given in php shell code on line 1
PHP Stack trace:
PHP   1. {main}() php shell code:0
PHP   2. Closure->__invoke() php shell code:1
php > 

The warning is wrong - Closure::fromCallable() could return $a actually :)


Add a Patch

Pull Requests

Add a Pull Request


AllCommentsChangesGit/SVN commitsRelated reports
 [2019-10-28 11:13 UTC]
-Status: Open +Status: Verified
 [2019-10-28 11:13 UTC]
This actually gives me a segfault on 7.2:

==24448== Jump to the invalid address stated on the next line
==24448==    at 0x600000001: ???
==24448==    by 0x9FE0E9: zend_call_function (zend_execute_API.c:820)
==24448==    by 0xA52718: zend_closure_call_magic (zend_closures.c:252)
==24448==    by 0xA538BB: zend_closure_internal_handler (zend_closures.c:632)
==24448==    by 0xA7E0C8: ZEND_DO_FCALL_SPEC_RETVAL_UNUSED_HANDLER (zend_vm_execute.h:911)
==24448==    by 0xB03C47: execute_ex (zend_vm_execute.h:59781)
==24448==    by 0xB09005: zend_execute (zend_vm_execute.h:63792)
==24448==    by 0xA186A1: zend_execute_scripts (zend.c:1498)
==24448==    by 0x97BDB3: php_execute_script (main.c:2599)
==24448==    by 0xB0BCAD: do_cli (php_cli.c:1011)
==24448==    by 0xB0CE6B: main (php_cli.c:1403)
==24448==  Address 0x600000001 is not stack'd, malloc'd or (recently) free'd
 [2019-10-28 11:22 UTC]
-Status: Verified +Status: Analyzed
 [2019-10-28 11:22 UTC]
It looks like there's a hardcoded assumption that any trampoline function passed to Closure::fromCallable() must be a __call/__callStatic trampoline, while here it's an __invoke() call-via-handler.
 [2019-10-28 11:31 UTC] nicolas dot grekas+php at gmail dot com
Note that we could take this as an opportunity to introduce a new type of callables:

given [$closure, 'method'], this would be resolved as $closure()->method() when called.

We use this style in Symfony where we need lazy-callables.
 [2019-10-29 14:09 UTC]
Automatic comment on behalf of
Log: Fixed bug #78689
 [2019-10-29 14:09 UTC]
-Status: Analyzed +Status: Closed
PHP Copyright © 2001-2023 The PHP Group
All rights reserved.
Last updated: Sat Sep 23 16:01:24 2023 UTC