1
0
mirror of https://github.com/php/php-src.git synced 2026-03-24 00:02:20 +01:00

gen_stub: Intern the parameter name string for named arguments in internal attributes (#14595)

This is necessary because `zend_get_attribute_object()` will use the persistent
string with the parameter name as the index for a newly created non-persistent
HashTable, which is not legal.

As parameter names are expected to be short-ish, reasonably common terms and
need to sit around in memory anyways, we might as well make them an interned
string, circumstepping the issue without needing to duplicate the parameter
name into a non-persistent string.
This commit is contained in:
Tim Düsterhus
2024-06-19 08:06:50 +02:00
committed by GitHub
parent 0c3dd16fbd
commit a1ea464069
5 changed files with 107 additions and 2 deletions

View File

@@ -3124,7 +3124,7 @@ class AttributeInfo {
$code .= $value->initializeZval($zvalName);
$code .= "\tZVAL_COPY_VALUE(&attribute_{$escapedAttributeName}_{$nameSuffix}->args[$i].value, &$zvalName);\n";
if ($arg->name) {
$code .= "\tattribute_{$escapedAttributeName}_{$nameSuffix}->args[$i].name = zend_string_init(\"{$arg->name->name}\", sizeof(\"{$arg->name->name}\") - 1, 1);\n";
$code .= "\tattribute_{$escapedAttributeName}_{$nameSuffix}->args[$i].name = zend_string_init_interned(\"{$arg->name->name}\", sizeof(\"{$arg->name->name}\") - 1, 1);\n";
}
}
return $code;

View File

@@ -58,6 +58,7 @@ static zend_class_entry *zend_test_attribute;
static zend_class_entry *zend_test_repeatable_attribute;
static zend_class_entry *zend_test_parameter_attribute;
static zend_class_entry *zend_test_property_attribute;
static zend_class_entry *zend_test_attribute_with_arguments;
static zend_class_entry *zend_test_class_with_method_with_parameter_attribute;
static zend_class_entry *zend_test_child_class_with_method_with_parameter_attribute;
static zend_class_entry *zend_test_class_with_property_attribute;
@@ -575,6 +576,11 @@ static ZEND_FUNCTION(zend_test_parameter_with_attribute)
RETURN_LONG(1);
}
static ZEND_FUNCTION(zend_test_attribute_with_named_argument)
{
ZEND_PARSE_PARAMETERS_NONE();
}
#ifdef ZEND_CHECK_STACK_LIMIT
static ZEND_FUNCTION(zend_test_zend_call_stack_get)
{
@@ -989,6 +995,19 @@ static ZEND_METHOD(ZendTestPropertyAttribute, __construct)
ZVAL_STR_COPY(OBJ_PROP_NUM(Z_OBJ_P(ZEND_THIS), 0), parameter);
}
static ZEND_METHOD(ZendTestAttributeWithArguments, __construct)
{
zval *arg;
ZEND_PARSE_PARAMETERS_START(1, 1)
Z_PARAM_ZVAL(arg)
ZEND_PARSE_PARAMETERS_END();
zend_string *property_name = zend_string_init("arg", strlen("arg"), 0);
zend_update_property_ex(zend_test_attribute_with_arguments, Z_OBJ_P(ZEND_THIS), property_name, arg);
zend_string_release(property_name);
}
static ZEND_METHOD(ZendTestClassWithMethodWithParameterAttribute, no_override)
{
zend_string *parameter;
@@ -1217,6 +1236,9 @@ PHP_MINIT_FUNCTION(zend_test)
zend_test_property_attribute = register_class_ZendTestPropertyAttribute();
zend_mark_internal_attribute(zend_test_property_attribute);
zend_test_attribute_with_arguments = register_class_ZendTestAttributeWithArguments();
zend_mark_internal_attribute(zend_test_attribute_with_arguments);
zend_test_class_with_method_with_parameter_attribute = register_class_ZendTestClassWithMethodWithParameterAttribute();
zend_test_child_class_with_method_with_parameter_attribute = register_class_ZendTestChildClassWithMethodWithParameterAttribute(zend_test_class_with_method_with_parameter_attribute);

View File

@@ -104,6 +104,13 @@ namespace {
final class ZendTestAttribute {
}
#[Attribute(Attribute::TARGET_ALL)]
final class ZendTestAttributeWithArguments {
public readonly mixed $arg;
public function __construct(mixed $arg) {}
}
#[Attribute(Attribute::TARGET_ALL|Attribute::IS_REPEATABLE)]
final class ZendTestRepeatableAttribute {
}
@@ -243,6 +250,9 @@ namespace {
string $parameter
): int {}
#[ZendTestAttributeWithArguments(arg: "foo")]
function zend_test_attribute_with_named_argument(): void {}
function zend_get_current_func_name(): string {}
function zend_call_method(object|string $obj_or_class, string $method, mixed $arg1 = UNKNOWN, mixed $arg2 = UNKNOWN): mixed {}

View File

@@ -1,5 +1,5 @@
/* This is a generated file, edit the .stub.php file instead.
* Stub hash: 810a94e09724a27d46c99495593da999cfc46243 */
* Stub hash: b7e8a9c27def16e8691883bea7837def1f717ab8 */
ZEND_STATIC_ASSERT(PHP_VERSION_ID >= 80000, "test_arginfo.h only supports PHP version ID 80000 or newer, "
"but it is included on an older PHP version");
@@ -90,6 +90,8 @@ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_zend_test_parameter_with_attribu
ZEND_ARG_TYPE_INFO(0, parameter, IS_STRING, 0)
ZEND_END_ARG_INFO()
#define arginfo_zend_test_attribute_with_named_argument arginfo_zend_test_void_return
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_zend_get_current_func_name, 0, 0, IS_STRING, 0)
ZEND_END_ARG_INFO()
@@ -208,6 +210,10 @@ ZEND_END_ARG_INFO()
#define arginfo_class__ZendTestTrait_testMethod arginfo_zend_test_is_pcre_bundled
ZEND_BEGIN_ARG_INFO_EX(arginfo_class_ZendTestAttributeWithArguments___construct, 0, 0, 1)
ZEND_ARG_TYPE_INFO(0, arg, IS_MIXED, 0)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO_EX(arginfo_class_ZendTestParameterAttribute___construct, 0, 0, 1)
ZEND_ARG_TYPE_INFO(0, parameter, IS_STRING, 0)
ZEND_END_ARG_INFO()
@@ -262,6 +268,7 @@ static ZEND_FUNCTION(zend_weakmap_remove);
static ZEND_FUNCTION(zend_weakmap_dump);
static ZEND_FUNCTION(zend_get_unit_enum);
static ZEND_FUNCTION(zend_test_parameter_with_attribute);
static ZEND_FUNCTION(zend_test_attribute_with_named_argument);
static ZEND_FUNCTION(zend_get_current_func_name);
static ZEND_FUNCTION(zend_call_method);
static ZEND_FUNCTION(zend_object_init_with_constructor);
@@ -302,6 +309,7 @@ static ZEND_METHOD(_ZendTestMagicCall, __call);
static ZEND_METHOD(_ZendTestChildClass, returnsThrowable);
static ZEND_METHOD(ZendAttributeTest, testMethod);
static ZEND_METHOD(_ZendTestTrait, testMethod);
static ZEND_METHOD(ZendTestAttributeWithArguments, __construct);
static ZEND_METHOD(ZendTestParameterAttribute, __construct);
static ZEND_METHOD(ZendTestPropertyAttribute, __construct);
static ZEND_METHOD(ZendTestClassWithMethodWithParameterAttribute, no_override);
@@ -359,6 +367,7 @@ static const zend_function_entry ext_functions[] = {
ZEND_FE(zend_weakmap_dump, arginfo_zend_weakmap_dump)
ZEND_FE(zend_get_unit_enum, arginfo_zend_get_unit_enum)
ZEND_FE(zend_test_parameter_with_attribute, arginfo_zend_test_parameter_with_attribute)
ZEND_FE(zend_test_attribute_with_named_argument, arginfo_zend_test_attribute_with_named_argument)
ZEND_FE(zend_get_current_func_name, arginfo_zend_get_current_func_name)
ZEND_FE(zend_call_method, arginfo_zend_call_method)
ZEND_FE(zend_object_init_with_constructor, arginfo_zend_object_init_with_constructor)
@@ -466,6 +475,11 @@ static const zend_function_entry class_ZendTestAttribute_methods[] = {
ZEND_FE_END
};
static const zend_function_entry class_ZendTestAttributeWithArguments_methods[] = {
ZEND_ME(ZendTestAttributeWithArguments, __construct, arginfo_class_ZendTestAttributeWithArguments___construct, ZEND_ACC_PUBLIC)
ZEND_FE_END
};
static const zend_function_entry class_ZendTestRepeatableAttribute_methods[] = {
ZEND_FE_END
};
@@ -553,6 +567,15 @@ static void register_test_symbols(int module_number)
zend_string *attribute_ZendTestParameterAttribute_func_zend_test_parameter_with_attribute_arg0_0_arg0_str = zend_string_init("value1", strlen("value1"), 1);
ZVAL_STR(&attribute_ZendTestParameterAttribute_func_zend_test_parameter_with_attribute_arg0_0_arg0, attribute_ZendTestParameterAttribute_func_zend_test_parameter_with_attribute_arg0_0_arg0_str);
ZVAL_COPY_VALUE(&attribute_ZendTestParameterAttribute_func_zend_test_parameter_with_attribute_arg0_0->args[0].value, &attribute_ZendTestParameterAttribute_func_zend_test_parameter_with_attribute_arg0_0_arg0);
zend_string *attribute_name_ZendTestAttributeWithArguments_func_zend_test_attribute_with_named_argument_0 = zend_string_init_interned("ZendTestAttributeWithArguments", sizeof("ZendTestAttributeWithArguments") - 1, 1);
zend_attribute *attribute_ZendTestAttributeWithArguments_func_zend_test_attribute_with_named_argument_0 = zend_add_function_attribute(zend_hash_str_find_ptr(CG(function_table), "zend_test_attribute_with_named_argument", sizeof("zend_test_attribute_with_named_argument") - 1), attribute_name_ZendTestAttributeWithArguments_func_zend_test_attribute_with_named_argument_0, 1);
zend_string_release(attribute_name_ZendTestAttributeWithArguments_func_zend_test_attribute_with_named_argument_0);
zval attribute_ZendTestAttributeWithArguments_func_zend_test_attribute_with_named_argument_0_arg0;
zend_string *attribute_ZendTestAttributeWithArguments_func_zend_test_attribute_with_named_argument_0_arg0_str = zend_string_init("foo", strlen("foo"), 1);
ZVAL_STR(&attribute_ZendTestAttributeWithArguments_func_zend_test_attribute_with_named_argument_0_arg0, attribute_ZendTestAttributeWithArguments_func_zend_test_attribute_with_named_argument_0_arg0_str);
ZVAL_COPY_VALUE(&attribute_ZendTestAttributeWithArguments_func_zend_test_attribute_with_named_argument_0->args[0].value, &attribute_ZendTestAttributeWithArguments_func_zend_test_attribute_with_named_argument_0_arg0);
attribute_ZendTestAttributeWithArguments_func_zend_test_attribute_with_named_argument_0->args[0].name = zend_string_init_interned("arg", sizeof("arg") - 1, 1);
}
static zend_class_entry *register_class__ZendTestInterface(void)
@@ -802,6 +825,34 @@ static zend_class_entry *register_class_ZendTestAttribute(void)
return class_entry;
}
static zend_class_entry *register_class_ZendTestAttributeWithArguments(void)
{
zend_class_entry ce, *class_entry;
INIT_CLASS_ENTRY(ce, "ZendTestAttributeWithArguments", class_ZendTestAttributeWithArguments_methods);
class_entry = zend_register_internal_class_ex(&ce, NULL);
class_entry->ce_flags |= ZEND_ACC_FINAL;
zval property_arg_default_value;
ZVAL_UNDEF(&property_arg_default_value);
zend_string *property_arg_name = zend_string_init("arg", sizeof("arg") - 1, 1);
#if (PHP_VERSION_ID >= 80100)
zend_declare_typed_property(class_entry, property_arg_name, &property_arg_default_value, ZEND_ACC_PUBLIC|ZEND_ACC_READONLY, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_ANY));
#elif (PHP_VERSION_ID >= 80000)
zend_declare_typed_property(class_entry, property_arg_name, &property_arg_default_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_ANY));
#endif
zend_string_release(property_arg_name);
zend_string *attribute_name_Attribute_class_ZendTestAttributeWithArguments_0 = zend_string_init_interned("Attribute", sizeof("Attribute") - 1, 1);
zend_attribute *attribute_Attribute_class_ZendTestAttributeWithArguments_0 = zend_add_class_attribute(class_entry, attribute_name_Attribute_class_ZendTestAttributeWithArguments_0, 1);
zend_string_release(attribute_name_Attribute_class_ZendTestAttributeWithArguments_0);
zval attribute_Attribute_class_ZendTestAttributeWithArguments_0_arg0;
ZVAL_LONG(&attribute_Attribute_class_ZendTestAttributeWithArguments_0_arg0, ZEND_ATTRIBUTE_TARGET_ALL);
ZVAL_COPY_VALUE(&attribute_Attribute_class_ZendTestAttributeWithArguments_0->args[0].value, &attribute_Attribute_class_ZendTestAttributeWithArguments_0_arg0);
return class_entry;
}
static zend_class_entry *register_class_ZendTestRepeatableAttribute(void)
{
zend_class_entry ce, *class_entry;

View File

@@ -0,0 +1,22 @@
--TEST--
Verify that attributes for internal functions correctly support named arguments.
--EXTENSIONS--
zend_test
--FILE--
<?php
$reflection = new ReflectionFunction("zend_test_attribute_with_named_argument");
$attribute = $reflection->getAttributes()[0];
var_dump($attribute->getArguments());
var_dump($attribute->newInstance());
?>
--EXPECTF--
array(1) {
["arg"]=>
string(3) "foo"
}
object(ZendTestAttributeWithArguments)#3 (1) {
["arg"]=>
string(3) "foo"
}