mirror of
https://github.com/php/php-src.git
synced 2025-08-15 21:48:51 +02:00
Merge branch 'PHP-8.2' into PHP-8.3
* PHP-8.2: Delay #[Attribute] arg validation until runtime
This commit is contained in:
commit
480d08a70a
10 changed files with 106 additions and 28 deletions
4
NEWS
4
NEWS
|
@ -6,6 +6,10 @@ PHP NEWS
|
|||
. Fixed buffer limit on Windows, replacing read call usage by _read.
|
||||
(David Carlier)
|
||||
|
||||
- Core:
|
||||
. Fixed bug GH-13970 (Incorrect validation of #[Attribute] flags type for
|
||||
non-compile-time expressions). (ilutov)
|
||||
|
||||
- DOM:
|
||||
. Fix crashes when entity declaration is removed while still having entity
|
||||
references. (nielsdos)
|
||||
|
|
|
@ -6,6 +6,15 @@ Attribute flags type is validated.
|
|||
#[Attribute("foo")]
|
||||
class A1 { }
|
||||
|
||||
#[A1]
|
||||
class Foo {}
|
||||
|
||||
try {
|
||||
(new ReflectionClass(Foo::class))->getAttributes()[0]->newInstance();
|
||||
} catch (Error $e) {
|
||||
echo $e->getMessage(), "\n";
|
||||
}
|
||||
|
||||
?>
|
||||
--EXPECTF--
|
||||
Fatal error: Attribute::__construct(): Argument #1 ($flags) must be of type int, string given in %s
|
||||
--EXPECT--
|
||||
Attribute::__construct(): Argument #1 ($flags) must be of type int, string given
|
||||
|
|
|
@ -6,6 +6,15 @@ Attribute flags value is validated.
|
|||
#[Attribute(-1)]
|
||||
class A1 { }
|
||||
|
||||
#[A1]
|
||||
class Foo { }
|
||||
|
||||
try {
|
||||
var_dump((new ReflectionClass(Foo::class))->getAttributes()[0]->newInstance());
|
||||
} catch (Error $e) {
|
||||
echo $e->getMessage(), "\n";
|
||||
}
|
||||
|
||||
?>
|
||||
--EXPECTF--
|
||||
Fatal error: Invalid attribute flags specified in %s
|
||||
--EXPECT--
|
||||
Invalid attribute flags specified
|
||||
|
|
|
@ -6,6 +6,15 @@ Attribute flags value is validated.
|
|||
#[Attribute(Foo::BAR)]
|
||||
class A1 { }
|
||||
|
||||
#[A1]
|
||||
class Bar { }
|
||||
|
||||
try {
|
||||
var_dump((new ReflectionClass(Bar::class))->getAttributes()[0]->newInstance());
|
||||
} catch (Error $e) {
|
||||
echo $e->getMessage(), "\n";
|
||||
}
|
||||
|
||||
?>
|
||||
--EXPECTF--
|
||||
Fatal error: Class "Foo" not found in %s on line %d
|
||||
--EXPECT--
|
||||
Class "Foo" not found
|
||||
|
|
|
@ -1,9 +1,19 @@
|
|||
--TEST--
|
||||
Validation for "Attribute" does not use a scope when evaluating constant ASTs
|
||||
Validation for "Attribute" uses the class scope when evaluating constant ASTs
|
||||
--FILE--
|
||||
<?php
|
||||
#[Attribute(parent::x)]
|
||||
class x extends y {}
|
||||
|
||||
class y {
|
||||
protected const x = Attribute::TARGET_CLASS;
|
||||
}
|
||||
|
||||
#[x]
|
||||
class z {}
|
||||
|
||||
var_dump((new ReflectionClass(z::class))->getAttributes()[0]->newInstance());
|
||||
?>
|
||||
--EXPECTF--
|
||||
Fatal error: Cannot access "parent" when no class scope is active in %s on line %d
|
||||
--EXPECT--
|
||||
object(x)#1 (0) {
|
||||
}
|
||||
|
|
|
@ -0,0 +1,12 @@
|
|||
--TEST--
|
||||
Attribute flags type is not validated at compile time.
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
#[Attribute("foo")]
|
||||
class A1 { }
|
||||
|
||||
?>
|
||||
===DONE===
|
||||
--EXPECT--
|
||||
===DONE===
|
|
@ -36,31 +36,39 @@ static zend_object_handlers attributes_object_handlers_sensitive_parameter_value
|
|||
static HashTable internal_attributes;
|
||||
|
||||
void validate_attribute(zend_attribute *attr, uint32_t target, zend_class_entry *scope)
|
||||
{
|
||||
}
|
||||
|
||||
uint32_t zend_attribute_attribute_get_flags(zend_attribute *attr, zend_class_entry *scope)
|
||||
{
|
||||
// TODO: More proper signature validation: Too many args, incorrect arg names.
|
||||
if (attr->argc > 0) {
|
||||
zval flags;
|
||||
|
||||
/* As this is run in the middle of compilation, fetch the attribute value without
|
||||
* specifying a scope. The class is not fully linked yet, and we may seen an
|
||||
* inconsistent state. */
|
||||
if (FAILURE == zend_get_attribute_value(&flags, attr, 0, NULL)) {
|
||||
return;
|
||||
if (FAILURE == zend_get_attribute_value(&flags, attr, 0, scope)) {
|
||||
ZEND_ASSERT(EG(exception));
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (Z_TYPE(flags) != IS_LONG) {
|
||||
zend_error_noreturn(E_ERROR,
|
||||
zend_throw_error(NULL,
|
||||
"Attribute::__construct(): Argument #1 ($flags) must be of type int, %s given",
|
||||
zend_zval_value_name(&flags)
|
||||
);
|
||||
zval_ptr_dtor(&flags);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (Z_LVAL(flags) & ~ZEND_ATTRIBUTE_FLAGS) {
|
||||
zend_error_noreturn(E_ERROR, "Invalid attribute flags specified");
|
||||
uint32_t flags_l = Z_LVAL(flags);
|
||||
if (flags_l & ~ZEND_ATTRIBUTE_FLAGS) {
|
||||
zend_throw_error(NULL, "Invalid attribute flags specified");
|
||||
return 0;
|
||||
}
|
||||
|
||||
zval_ptr_dtor(&flags);
|
||||
return flags_l;
|
||||
}
|
||||
|
||||
return ZEND_ATTRIBUTE_TARGET_ALL;
|
||||
}
|
||||
|
||||
static void validate_allow_dynamic_properties(
|
||||
|
|
|
@ -86,6 +86,8 @@ ZEND_API zend_attribute *zend_add_attribute(
|
|||
HashTable **attributes, zend_string *name, uint32_t argc,
|
||||
uint32_t flags, uint32_t offset, uint32_t lineno);
|
||||
|
||||
uint32_t zend_attribute_attribute_get_flags(zend_attribute *attr, zend_class_entry *scope);
|
||||
|
||||
END_EXTERN_C()
|
||||
|
||||
static zend_always_inline zend_attribute *zend_add_class_attribute(zend_class_entry *ce, zend_string *name, uint32_t argc)
|
||||
|
|
|
@ -6772,16 +6772,9 @@ ZEND_METHOD(ReflectionAttribute, newInstance)
|
|||
}
|
||||
|
||||
if (ce->type == ZEND_USER_CLASS) {
|
||||
uint32_t flags = ZEND_ATTRIBUTE_TARGET_ALL;
|
||||
|
||||
if (marker->argc > 0) {
|
||||
zval tmp;
|
||||
|
||||
if (FAILURE == zend_get_attribute_value(&tmp, marker, 0, ce)) {
|
||||
RETURN_THROWS();
|
||||
}
|
||||
|
||||
flags = (uint32_t) Z_LVAL(tmp);
|
||||
uint32_t flags = zend_attribute_attribute_get_flags(marker, ce);
|
||||
if (EG(exception)) {
|
||||
RETURN_THROWS();
|
||||
}
|
||||
|
||||
if (!(attr->target & flags)) {
|
||||
|
|
22
ext/zend_test/tests/gh13970.phpt
Normal file
22
ext/zend_test/tests/gh13970.phpt
Normal file
|
@ -0,0 +1,22 @@
|
|||
--TEST--
|
||||
GH-13970 (Incorrect validation of #[\Attribute]'s first parameter)
|
||||
--EXTENSIONS--
|
||||
zend_test
|
||||
--FILE--
|
||||
<?php
|
||||
#[Attribute(\ZendTestUnitEnum::Foo)]
|
||||
class Foo {}
|
||||
|
||||
#[Foo]
|
||||
function test() {}
|
||||
|
||||
$reflection = new ReflectionFunction('test');
|
||||
|
||||
try {
|
||||
var_dump($reflection->getAttributes()[0]->newInstance());
|
||||
} catch (Error $e) {
|
||||
echo $e->getMessage(), "\n";
|
||||
}
|
||||
?>
|
||||
--EXPECT--
|
||||
Attribute::__construct(): Argument #1 ($flags) must be of type int, ZendTestUnitEnum given
|
Loading…
Add table
Add a link
Reference in a new issue