Skip to content

Incorrect validation of #[\Attribute]’s first parameter #13970

Closed

Description

@TimWolla

Description

The following code:

<?php
#[Attribute(Random\IntervalBoundary::ClosedOpen)]
class Foo {

}

#[Foo]
function test1() {

}

$reflection = new ReflectionFunction('test1');
var_dump($reflection->getAttributes()[0]->newInstance());
?>

Resulted in this output:

Fatal error: Uncaught Error: Attribute "Foo" cannot target function (allowed targets: ) in php-src/test.php:13
Stack trace:
#0 php-src/test.php(13): ReflectionAttribute->newInstance()
#1 {main}
  thrown in php-src/test.php on line 13
[Mon Apr 15 15:49:24 2024]  Script:  'php-src/test.php'
php-src/Zend/zend_objects.c(189) :  Freeing 0x000073dc9105c780 (56 bytes), script=php-src/test.php
=== Total 1 memory leaks detected ===

But I expected this output instead:

  1. No memory leak.
  2. Something related to the argument not being a correct integer.

PHP Version

git master

Operating System

Ubuntu 23.10

Activity

  1. TimWolla commented on Apr 15, 2024

    @TimWolla
    MemberAuthor

    Found while working on #11293.

  2. ndossche commented on Apr 15, 2024

    @ndossche
    Member

    This turns out to be a regression, regressed in #8373.
    In particular, we'll fail in zend_get_attribute_value that was called from validate_attribute to read the target.
    That's because of this check:

    php-src/Zend/zend_ast.c

    Lines 807 to 811 in d407266

    // Preloading will attempt to resolve constants but objects can't be stored in shm
    // Aborting here to store the const AST instead
    if (CG(in_compilation)) {
    return FAILURE;
    }

    Note that we are in compilation, so the check will be true and we'll fail to resolve the enum.
    If I change that check to if (CG(compiler_options) & ZEND_COMPILE_PRELOAD) { it works, but I guess that'll break in preloading... I'll check.
    EDIT: of course it does
    EDIT 2: checking both compiler_options and in_compilation, like so if (CG(in_compilation) && CG(compiler_options) & ZEND_COMPILE_PRELOAD) { makes all ext/opcache tests pass, now checking preloading...
    EDIT 3: as expected, doesn't work, probably the check should happen at a difference place?

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

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions