Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

SIGABRT/SIGTRAP when using closures in attributes in PHP 8.5 #17096

Open
alexandre-daubois opened this issue Dec 9, 2024 · 4 comments · May be fixed by #17120
Open

SIGABRT/SIGTRAP when using closures in attributes in PHP 8.5 #17096

alexandre-daubois opened this issue Dec 9, 2024 · 4 comments · May be fixed by #17120

Comments

@alexandre-daubois
Copy link
Contributor

alexandre-daubois commented Dec 9, 2024

Description

While playing with closures in attributes thanks to the last accepted RFC, the following code:

<?php

namespace App\Controller;

use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Attribute\Route;
use Symfony\Component\Security\Core\Authorization\IsGrantedPayload;
use Symfony\Component\Security\Http\Attribute\IsGranted;

class HomeController extends AbstractController
{
    #[Route(path: '/')]
    #[IsGranted(callable: static function (mixed $payload) {
        return $payload->authorizationChecker->isGranted('ROLE_ADMIN');
    })]
    public function home(): Response
    {
        return new Response('test');
    }
}

Resulted in this output (debug enabled during PHP compilation):

[PHP-FPM    ] Assertion failed: (0), function zend_ast_export_ex, file zend_ast.c, line 2636.
[PHP-FPM    ] Dec  9 16:31:19 |WARNING| FPM    [pool www] child 12292 exited on signal 6 (SIGABRT) after 10.539209 seconds from start

When debug is disabled, a SIGTRAP is thrown and PHP crashes immediately. The built-in server is used (php-src/sapi/cli/php -S localhost:8002 -t public/), Symfony CLI server behave the same. It crashes as soon as you go on /.

A plain Symfony project can be created, then create a controller with the above code snippet. The callable argument doesn't have to even exist in Symfony's IsGranted attribute (that's the feature I'm playing with). Even with a brand new Symfony install, this crashes.

This is the most minimal snippet I could do to reproduce this. If you need any other information to help you debug/setup the reproducer, I'd be happy to help.

PHP Version

PHP 8.5.0-dev

Operating System

macOS 15.1.1

@TimWolla
Copy link
Member

(gdb) bt
#0  __pthread_kill_implementation (no_tid=0, signo=6, threadid=<optimized out>)
    at ./nptl/pthread_kill.c:44
#1  __pthread_kill_internal (signo=6, threadid=<optimized out>) at ./nptl/pthread_kill.c:78
#2  __GI___pthread_kill (threadid=<optimized out>, signo=signo@entry=6)
    at ./nptl/pthread_kill.c:89
#3  0x00007ffff784526e in __GI_raise (sig=sig@entry=6) at ../sysdeps/posix/raise.c:26
#4  0x00007ffff78288ff in __GI_abort () at ./stdlib/abort.c:79
#5  0x00007ffff782881b in __assert_fail_base (
    fmt=0x7ffff79d01e8 "%s%s%s:%u: %s%sAssertion `%s' failed.\n%n", 
    assertion=assertion@entry=0x55555b2cc0c0 <str> "0", 
    file=file@entry=0x55555a48667f "php-src/Zend/zend_ast.c", 
    line=line@entry=2636, 
    function=function@entry=0x55555b2cca80 <__PRETTY_FUNCTION__.zend_ast_export_ex> "void zend_ast_export_ex(smart_str *, zend_ast *, int, int)") at ./assert/assert.c:94
#6  0x00007ffff783b507 in __assert_fail (assertion=0x55555b2cc0c0 <str> "0", 
    file=0x55555a48667f "php-src/Zend/zend_ast.c", line=2636, 
    function=0x55555b2cca80 <__PRETTY_FUNCTION__.zend_ast_export_ex> "void zend_ast_export_ex(smart_str *, zend_ast *, int, int)") at ./assert/assert.c:103
#7  0x000055555958a6c4 in zend_ast_export_ex (str=0x7ffff32cfaa0, ast=0x7ffff236c6c8, 
    priority=0, indent=0) at php-src/Zend/zend_ast.c:2636
#8  0x00005555595799b5 in zend_ast_export (prefix=0x55555b19f740 <str> "", 
    ast=0x7ffff236c6c8, suffix=0x55555b19f740 <str> "")
    at php-src/Zend/zend_ast.c:2696
#9  0x000055555849ba97 in format_default_value (str=0x7ffff32cfa60, value=0x7ffff18ead48)
    at php-src/ext/reflection/php_reflection.c:686
#10 0x000055555849a635 in zim_ReflectionAttribute___toString (execute_data=0x7ffff2209a90, 
    return_value=0x7ffff32cfa20)
    at php-src/ext/reflection/php_reflection.c:7009
#11 0x00005555597ba137 in zend_call_function (fci=0x7ffff345fc40, fci_cache=0x7ffff345fca0)
    at php-src/Zend/zend_execute_API.c:1012
#12 0x00005555597be188 in zend_call_known_function (fn=0x50e0000e1ee0, 
    object=0x7ffff0e666a8, called_scope=0x516000044480, retval_ptr=0x7ffff32cfa20, 
    param_count=0, params=0x0, named_params=0x0)
    at php-src/Zend/zend_execute_API.c:1093
#13 0x000055555a1f579f in zend_call_known_instance_method (fn=0x50e0000e1ee0, 
    object=0x7ffff0e666a8, retval_ptr=0x7ffff32cfa20, param_count=0, params=0x0)
    at Zend/zend_API.h:860
#14 0x000055555a1b80cc in zend_call_known_instance_method_with_0_params (
    fn=0x50e0000e1ee0, object=0x7ffff0e666a8, retval_ptr=0x7ffff32cfa20)
    at Zend/zend_API.h:866
#15 0x000055555a1f228d in zend_std_cast_object_tostring (readobj=0x7ffff0e666a8, 
    writeobj=0x7ffff32cf9e0, type=6)
    at php-src/Zend/zend_object_handlers.c:2336
#16 0x000055555a24cdde in __zval_get_string_func (op=0x7ffff1004c70, try=false)
    at php-src/Zend/zend_operators.c:1032
#17 0x000055555a24c2f7 in zval_get_string_func (op=0x7ffff1004c70)
    at php-src/Zend/zend_operators.c:1053
#18 0x0000555559e9b783 in zval_get_string (op=0x7ffff1004c70) at Zend/zend_operators.h:327
#19 0x0000555559a73e6f in ZEND_CAST_SPEC_CV_HANDLER (execute_data=0x7ffff1004c00)

@TimWolla
Copy link
Member

TimWolla commented Dec 10, 2024

Simple reproducer:

<?php

#[Attr(static function () {

})]
function foo() {

}

$r = new ReflectionFunction('foo');
$r->getAttributes()[0]->__toString();

@TimWolla
Copy link
Member

@alexandre-daubois A fix is available in PR #17120. Can you try it with Symfony / your Symfony use case?

@alexandre-daubois
Copy link
Contributor Author

Just tested with your PR and it does. Thank you Tim!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants