Skip to content

Delay #[Attribute] arg validation until runtime #14105

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

Closed
wants to merge 1 commit into from

Conversation

iluuu1994
Copy link
Member

@iluuu1994 iluuu1994 commented May 1, 2024

Fixes GH-13970

We cannot validate at compile-time for multiple reasons:

  • Evaluating the argument naively with zend_get_attribute_value can lead to code execution at compile-time through the new expression, leading to possible reentrance of the compiler.
  • Even if the evaluation was possible, it would need to be restricted to the current file, because constant values coming from other files can change without affecting the current compilation unit. For this reason, validation would need to be repeated at runtime anyway.
  • Enums cannot be instantiated at compile-time (the actual bug report). This could be allowed here, because the value is immediately destroyed. But given the other issues, this won't be needed.

Instead, we just move it to runtime entirely. It's only needed for ReflectionAttribute::newInstance(), which is not particularly a hot path. The checks are also simple.

Copy link
Member

@nielsdos nielsdos left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I like the solution, thanks! I only found one very minor nit that isn't necessarily something that should be changed.
EDIT: not entirely sure about the rules of when adding public APIs is allowed though.

@TimWolla TimWolla self-requested a review May 1, 2024 19:46
@TimWolla
Copy link
Member

TimWolla commented May 1, 2024

I want to try this out myself (that's why I requested my review), but a quick note already: Don't forget to mention the issue in the commit message or PR for proper linking.

@iluuu1994
Copy link
Member Author

not entirely sure about the rules of when adding public APIs is allowed though.

I believe additions are ok in patches, but I will remove ZEND_API from the function.

Copy link
Member

@TimWolla TimWolla left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What I wanted to test: Whether the placement of internal attributes is still validated, as that could have a memory-safety impact depending on what exactly they do.

Consider adding these test cases:

<?php

#[\Attribute("test")]
function test() {

}

and

<?php

#[\SensitiveParameter]
function test() {

}

Copy link
Member Author

@iluuu1994 iluuu1994 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What I wanted to test: Whether the placement of internal attributes is still validated, as that could have a memory-safety impact depending on what exactly they do.

Placement of internal attributes are still checked at compile time. See:

php-src/Zend/zend_compile.c

Lines 6767 to 6774 in b6b9eab

if (!(target & (config->flags & ZEND_ATTRIBUTE_TARGET_ALL))) {
zend_string *location = zend_get_attribute_target_names(target);
zend_string *allowed = zend_get_attribute_target_names(config->flags);
zend_error_noreturn(E_ERROR, "Attribute \"%s\" cannot target %s (allowed targets: %s)",
ZSTR_VAL(attr->name), ZSTR_VAL(location), ZSTR_VAL(allowed)
);
}

That is, if you're not using a class alias. At that point, this guarantee goes out the window. However, from what I see, validator doesn't get a reference to the target anyway (which is very odd). validate_allow_dynamic_properties only works because it happens to only work for classes, and validator does get the scope.

@TimWolla
Copy link
Member

TimWolla commented May 2, 2024

Placement of internal attributes are still checked at compile time. See:

Yes, I could confirm this myself with the two test cases I mentioned.

@iluuu1994 iluuu1994 force-pushed the gh-13970 branch 2 times, most recently from e382ab9 to 7236e5a Compare May 4, 2024 16:23
Fixes phpGH-13970

We cannot validate at compile-time for multiple reasons:

* Evaluating the argument naively with zend_get_attribute_value can lead to code
  execution at compile time through the new expression, leading to possible
  reentrance of the compiler.
* Even if the evaluation was possible, it would need to be restricted to the
  current file, because constant values coming from other files can change
  without affecting the current compilation unit. For this reason, validation
  would need to be repeated at runtime anyway.
* Enums cannot be instantiated at compile-time (the actual bug report). This
  could be allowed here, because the value is immediately destroyed. But given
  the other issues, this won't be needed.

Instead, we just move it to runtime entirely. It's only needed for
ReflectionAttribute::newInstance(), which is not particularly a hot path. The
checks are also simple.
@iluuu1994 iluuu1994 closed this in f8d1864 May 6, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants