Revert "Remove name field from the zend_constant struct (#10954)"

This reverts commit f42992f580.

Closes GH-11604
This commit is contained in:
Ilija Tovilo 2023-07-06 09:55:11 +02:00
parent de60872cfd
commit 1a0ef2c1cc
No known key found for this signature in database
GPG Key ID: A4F5D403F118200A
16 changed files with 84 additions and 71 deletions

View File

@ -42,10 +42,6 @@ PHP 8.3 INTERNALS UPGRADE NOTES
* The order of members of zend_op_array, zend_ssa_var, zend_ssa_var_info,
zend_executor_globals and php_core_globals have changed to improve
struct packing which reduces their size.
* The name field have been removed from the zend_constant struct. Now,
constant names are only stored as keys of the global constants table.
That's why the `zend_register_constant()` function now expects the
constant name as its first parameter.
* Many calls to zend_assign_to_variable have been replaced with
zend_assign_to_variable_ex which allows delaying the releasing of the old
variable value. This avoids side-effects through destructors between the

View File

@ -517,7 +517,8 @@ ZEND_FUNCTION(define)
register_constant:
/* non persistent */
ZEND_CONSTANT_SET_FLAGS(&c, 0, PHP_USER_CONSTANT);
if (zend_register_constant(name, &c) == SUCCESS) {
c.name = zend_string_copy(name);
if (zend_register_constant(&c) == SUCCESS) {
RETURN_TRUE;
} else {
RETURN_FALSE;
@ -1485,7 +1486,6 @@ ZEND_FUNCTION(get_defined_constants)
zend_constant *val;
int module_number;
zval *modules, const_val;
zend_string *const_name;
char **module_names;
zend_module_entry *module;
int i = 1;
@ -1500,7 +1500,12 @@ ZEND_FUNCTION(get_defined_constants)
} ZEND_HASH_FOREACH_END();
module_names[i] = "user";
ZEND_HASH_MAP_FOREACH_STR_KEY_PTR(EG(zend_constants), const_name, val) {
ZEND_HASH_MAP_FOREACH_PTR(EG(zend_constants), val) {
if (!val->name) {
/* skip special constants */
continue;
}
if (ZEND_CONSTANT_MODULE_NUMBER(val) == PHP_USER_CONSTANT) {
module_number = i;
} else if (ZEND_CONSTANT_MODULE_NUMBER(val) > i) {
@ -1516,19 +1521,22 @@ ZEND_FUNCTION(get_defined_constants)
}
ZVAL_COPY_OR_DUP(&const_val, &val->value);
zend_hash_add_new(Z_ARRVAL(modules[module_number]), const_name, &const_val);
zend_hash_add_new(Z_ARRVAL(modules[module_number]), val->name, &const_val);
} ZEND_HASH_FOREACH_END();
efree(module_names);
efree(modules);
} else {
zend_constant *constant;
zend_string *const_name;
zval const_val;
ZEND_HASH_MAP_FOREACH_STR_KEY_PTR(EG(zend_constants), const_name, constant) {
ZEND_HASH_MAP_FOREACH_PTR(EG(zend_constants), constant) {
if (!constant->name) {
/* skip special constants */
continue;
}
ZVAL_COPY_OR_DUP(&const_val, &constant->value);
zend_hash_add_new(Z_ARRVAL_P(return_value), const_name, &const_val);
zend_hash_add_new(Z_ARRVAL_P(return_value), constant->name, &const_val);
} ZEND_HASH_FOREACH_END();
}
}

View File

@ -43,9 +43,15 @@ void free_zend_constant(zval *zv)
if (!(ZEND_CONSTANT_FLAGS(c) & CONST_PERSISTENT)) {
zval_ptr_dtor_nogc(&c->value);
if (c->name) {
zend_string_release_ex(c->name, 0);
}
efree(c);
} else {
zval_internal_ptr_dtor(&c->value);
if (c->name) {
zend_string_release_ex(c->name, 1);
}
free(c);
}
}
@ -61,6 +67,7 @@ static void copy_zend_constant(zval *zv)
memcpy(Z_PTR_P(zv), c, sizeof(zend_constant));
c = Z_PTR_P(zv);
c->name = zend_string_copy(c->name);
if (Z_TYPE(c->value) == IS_STRING) {
Z_STR(c->value) = zend_string_dup(Z_STR(c->value), 1);
}
@ -122,7 +129,8 @@ ZEND_API void zend_register_null_constant(const char *name, size_t name_len, int
ZVAL_NULL(&c.value);
ZEND_CONSTANT_SET_FLAGS(&c, flags, module_number);
zend_register_internal_constant(name, name_len, &c);
c.name = zend_string_init_interned(name, name_len, flags & CONST_PERSISTENT);
zend_register_constant(&c);
}
ZEND_API void zend_register_bool_constant(const char *name, size_t name_len, bool bval, int flags, int module_number)
@ -131,7 +139,8 @@ ZEND_API void zend_register_bool_constant(const char *name, size_t name_len, boo
ZVAL_BOOL(&c.value, bval);
ZEND_CONSTANT_SET_FLAGS(&c, flags, module_number);
zend_register_internal_constant(name, name_len, &c);
c.name = zend_string_init_interned(name, name_len, flags & CONST_PERSISTENT);
zend_register_constant(&c);
}
ZEND_API void zend_register_long_constant(const char *name, size_t name_len, zend_long lval, int flags, int module_number)
@ -140,7 +149,8 @@ ZEND_API void zend_register_long_constant(const char *name, size_t name_len, zen
ZVAL_LONG(&c.value, lval);
ZEND_CONSTANT_SET_FLAGS(&c, flags, module_number);
zend_register_internal_constant(name, name_len, &c);
c.name = zend_string_init_interned(name, name_len, flags & CONST_PERSISTENT);
zend_register_constant(&c);
}
@ -150,7 +160,8 @@ ZEND_API void zend_register_double_constant(const char *name, size_t name_len, d
ZVAL_DOUBLE(&c.value, dval);
ZEND_CONSTANT_SET_FLAGS(&c, flags, module_number);
zend_register_internal_constant(name, name_len, &c);
c.name = zend_string_init_interned(name, name_len, flags & CONST_PERSISTENT);
zend_register_constant(&c);
}
@ -160,7 +171,8 @@ ZEND_API void zend_register_stringl_constant(const char *name, size_t name_len,
ZVAL_STR(&c.value, zend_string_init_interned(strval, strlen, flags & CONST_PERSISTENT));
ZEND_CONSTANT_SET_FLAGS(&c, flags, module_number);
zend_register_internal_constant(name, name_len, &c);
c.name = zend_string_init_interned(name, name_len, flags & CONST_PERSISTENT);
zend_register_constant(&c);
}
@ -541,9 +553,10 @@ static void* zend_hash_add_constant(HashTable *ht, zend_string *key, zend_consta
return ret;
}
ZEND_API zend_result zend_register_constant(zend_string *name, zend_constant *c)
ZEND_API zend_result zend_register_constant(zend_constant *c)
{
zend_string *lowercase_name = NULL;
zend_string *name;
zend_result ret = SUCCESS;
bool persistent = (ZEND_CONSTANT_FLAGS(c) & CONST_PERSISTENT) != 0;
@ -551,12 +564,14 @@ ZEND_API zend_result zend_register_constant(zend_string *name, zend_constant *c)
printf("Registering constant for module %d\n", c->module_number);
#endif
const char *slash = strrchr(ZSTR_VAL(name), '\\');
const char *slash = strrchr(ZSTR_VAL(c->name), '\\');
if (slash) {
lowercase_name = zend_string_init(ZSTR_VAL(name), ZSTR_LEN(name), persistent);
zend_str_tolower(ZSTR_VAL(lowercase_name), slash - ZSTR_VAL(name));
lowercase_name = zend_string_init(ZSTR_VAL(c->name), ZSTR_LEN(c->name), persistent);
zend_str_tolower(ZSTR_VAL(lowercase_name), slash - ZSTR_VAL(c->name));
lowercase_name = zend_new_interned_string(lowercase_name);
name = lowercase_name;
} else {
name = c->name;
}
/* Check if the user is trying to define any special constant */
@ -565,6 +580,7 @@ ZEND_API zend_result zend_register_constant(zend_string *name, zend_constant *c)
|| zend_hash_add_constant(EG(zend_constants), name, c) == NULL
) {
zend_error(E_WARNING, "Constant %s already defined", ZSTR_VAL(name));
zend_string_release(c->name);
if (!persistent) {
zval_ptr_dtor_nogc(&c->value);
}
@ -575,13 +591,3 @@ ZEND_API zend_result zend_register_constant(zend_string *name, zend_constant *c)
}
return ret;
}
ZEND_API zend_result zend_register_internal_constant(const char *name, size_t name_len, zend_constant *c) {
zend_string *name_str = zend_string_init_interned(name, name_len, ZEND_CONSTANT_FLAGS(c) & CONST_PERSISTENT);
zend_result result = zend_register_constant(name_str, c);
zend_string_release(name_str);
return result;
}

View File

@ -32,6 +32,7 @@
typedef struct _zend_constant {
zval value;
zend_string *name;
} zend_constant;
#define ZEND_CONSTANT_FLAGS(c) \
@ -83,8 +84,7 @@ ZEND_API void zend_register_long_constant(const char *name, size_t name_len, zen
ZEND_API void zend_register_double_constant(const char *name, size_t name_len, double dval, int flags, int module_number);
ZEND_API void zend_register_string_constant(const char *name, size_t name_len, const char *strval, int flags, int module_number);
ZEND_API void zend_register_stringl_constant(const char *name, size_t name_len, const char *strval, size_t strlen, int flags, int module_number);
ZEND_API zend_result zend_register_internal_constant(const char *name, size_t name_len, zend_constant *c);
ZEND_API zend_result zend_register_constant(zend_string *name, zend_constant *c);
ZEND_API zend_result zend_register_constant(zend_constant *c);
#ifdef ZTS
void zend_copy_constants(HashTable *target, HashTable *source);
#endif

View File

@ -5008,7 +5008,7 @@ static zend_always_inline zend_result _zend_quick_get_constant(
if (!check_defined_only) {
ZVAL_COPY_OR_DUP(EX_VAR(opline->result.var), &c->value);
if (ZEND_CONSTANT_FLAGS(c) & CONST_DEPRECATED) {
zend_error(E_DEPRECATED, "Constant %s is deprecated", ZSTR_VAL(Z_STR_P(key)));
zend_error(E_DEPRECATED, "Constant %s is deprecated", ZSTR_VAL(c->name));
return SUCCESS;
}
}

View File

@ -294,6 +294,9 @@ ZEND_API void zend_shutdown_executor_values(bool fast_shutdown)
break;
}
zval_ptr_dtor_nogc(&c->value);
if (c->name) {
zend_string_release_ex(c->name, 0);
}
efree(c);
zend_string_release_ex(key, 0);
} ZEND_HASH_MAP_FOREACH_END_DEL();

View File

@ -8150,8 +8150,9 @@ ZEND_VM_HANDLER(143, ZEND_DECLARE_CONST, CONST, CONST)
}
/* non persistent, case sensitive */
ZEND_CONSTANT_SET_FLAGS(&c, 0, PHP_USER_CONSTANT);
c.name = zend_string_copy(Z_STR_P(name));
if (zend_register_constant(Z_STR_P(name), &c) == FAILURE) {
if (zend_register_constant(&c) == FAILURE) {
}
FREE_OP1();

View File

@ -7626,8 +7626,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DECLARE_CONST_SPEC_CONST_CONST
}
/* non persistent, case sensitive */
ZEND_CONSTANT_SET_FLAGS(&c, 0, PHP_USER_CONSTANT);
c.name = zend_string_copy(Z_STR_P(name));
if (zend_register_constant(Z_STR_P(name), &c) == FAILURE) {
if (zend_register_constant(&c) == FAILURE) {
}

View File

@ -197,7 +197,7 @@ PHP_COM_DOTNET_API zend_result php_com_import_typelib(ITypeLib *TL, int mode, in
if (pTKind == TKIND_ENUM) {
ITypeLib_GetTypeInfo(TL, i, &TypeInfo);
for (j = 0; ; j++) {
zend_string *const_name, *name;
zend_string *const_name;
if (FAILED(ITypeInfo_GetVarDesc(TypeInfo, j, &pVarDesc))) {
break;
@ -228,13 +228,12 @@ PHP_COM_DOTNET_API zend_result php_com_import_typelib(ITypeLib *TL, int mode, in
ZVAL_LONG(&c.value, Z_LVAL(value));
if (mode & CONST_PERSISTENT) {
/* duplicate string in a persistent manner */
name = zend_string_dup(const_name, /* persistent */ true);
c.name = zend_string_dup(const_name, /* persistent */ true);
zend_string_release_ex(const_name, /* persistent */ false);
} else {
name = const_name;
c.name = const_name;
}
zend_register_constant(name, &c);
zend_string_release(name);
zend_register_constant(&c);
}
ITypeInfo_ReleaseVarDesc(TypeInfo, pVarDesc);
}

View File

@ -735,6 +735,9 @@ static void accel_copy_permanent_strings(zend_new_interned_string_func_t new_int
p->key = new_interned_string(p->key);
}
c = (zend_constant*)Z_PTR(p->val);
if (c->name) {
c->name = new_interned_string(c->name);
}
if (Z_TYPE(c->value) == IS_STRING) {
ZVAL_STR(&c->value, new_interned_string(Z_STR(c->value)));
}

View File

@ -282,7 +282,7 @@ static zend_always_inline zend_constant* _zend_quick_get_constant(
if (!check_defined_only) {
if (ZEND_CONSTANT_FLAGS(c) & CONST_DEPRECATED) {
zend_error(E_DEPRECATED, "Constant %s is deprecated", ZSTR_VAL(Z_STR_P(key)));
zend_error(E_DEPRECATED, "Constant %s is deprecated", ZSTR_VAL(c->name));
if (EG(exception)) {
return NULL;
}

View File

@ -1045,13 +1045,11 @@ static void _extension_string(smart_str *str, zend_module_entry *module, char *i
{
smart_str str_constants = {0};
zend_constant *constant;
zend_string *name;
int num_constants = 0;
ZEND_HASH_MAP_FOREACH_STR_KEY_PTR(EG(zend_constants), name, constant) {
ZEND_HASH_MAP_FOREACH_PTR(EG(zend_constants), constant) {
if (ZEND_CONSTANT_MODULE_NUMBER(constant) == module->module_number) {
_const_string(&str_constants, ZSTR_VAL(name), &constant->value, indent);
_const_string(&str_constants, ZSTR_VAL(constant->name), &constant->value, indent);
num_constants++;
}
} ZEND_HASH_FOREACH_END();
@ -6037,7 +6035,6 @@ ZEND_METHOD(ReflectionExtension, getConstants)
reflection_object *intern;
zend_module_entry *module;
zend_constant *constant;
zend_string *name;
if (zend_parse_parameters_none() == FAILURE) {
RETURN_THROWS();
@ -6045,11 +6042,11 @@ ZEND_METHOD(ReflectionExtension, getConstants)
GET_REFLECTION_OBJECT_PTR(module);
array_init(return_value);
ZEND_HASH_MAP_FOREACH_STR_KEY_PTR(EG(zend_constants), name, constant) {
ZEND_HASH_MAP_FOREACH_PTR(EG(zend_constants), constant) {
if (module->module_number == ZEND_CONSTANT_MODULE_NUMBER(constant)) {
zval const_val;
ZVAL_COPY_OR_DUP(&const_val, &constant->value);
zend_hash_update(Z_ARRVAL_P(return_value), name, &const_val);
zend_hash_update(Z_ARRVAL_P(return_value), constant->name, &const_val);
}
} ZEND_HASH_FOREACH_END();
}

View File

@ -18,12 +18,12 @@ array(4) {
int(42)
["ZEND_CONSTANT_A"]=>
string(6) "global"
["zendtestns2\ZEND_CONSTANT_A"]=>
["ZendTestNS2\ZEND_CONSTANT_A"]=>
string(10) "namespaced"
["zendtestns2\zendsubns\ZEND_CONSTANT_A"]=>
["ZendTestNS2\ZendSubNS\ZEND_CONSTANT_A"]=>
string(10) "namespaced"
}
array(1) {
["ns1\ns2\Const1"]=>
["NS1\ns2\Const1"]=>
string(6) "value1"
}

View File

@ -558,13 +558,16 @@ static void cli_register_file_handles(void)
php_stream_to_zval(s_err, &ec.value);
Z_CONSTANT_FLAGS(ic.value) = 0;
zend_register_internal_constant("STDIN", sizeof("STDIN")-1, &ic);
ic.name = zend_string_init_interned("STDIN", sizeof("STDIN")-1, 0);
zend_register_constant(&ic);
Z_CONSTANT_FLAGS(oc.value) = 0;
zend_register_internal_constant("STDOUT", sizeof("STDOUT")-1, &oc);
oc.name = zend_string_init_interned("STDOUT", sizeof("STDOUT")-1, 0);
zend_register_constant(&oc);
Z_CONSTANT_FLAGS(ec.value) = 0;
zend_register_internal_constant("STDERR", sizeof("STDERR")-1, &ec);
ec.name = zend_string_init_interned("STDERR", sizeof("STDERR")-1, 0);
zend_register_constant(&ec);
}
static const char *param_mode_conflict = "Either execute direct code, process stdin or use a file.\n";

View File

@ -912,24 +912,21 @@ void phpdbg_register_file_handles(void) /* {{{ */
ic.value = zin;
Z_CONSTANT_FLAGS(ic.value) = 0;
zend_string *stdin_name = zend_string_init(ZEND_STRL("STDIN"), 0);
zend_hash_del(EG(zend_constants), stdin_name);
zend_register_constant(stdin_name, &ic);
zend_string_release(stdin_name);
ic.name = zend_string_init(ZEND_STRL("STDIN"), 0);
zend_hash_del(EG(zend_constants), ic.name);
zend_register_constant(&ic);
oc.value = zout;
Z_CONSTANT_FLAGS(oc.value) = 0;
zend_string *stdout_name = zend_string_init(ZEND_STRL("STDOUT"), 0);
zend_hash_del(EG(zend_constants), stdout_name);
zend_register_constant(stdout_name, &oc);
zend_string_release(stdout_name);
oc.name = zend_string_init(ZEND_STRL("STDOUT"), 0);
zend_hash_del(EG(zend_constants), oc.name);
zend_register_constant(&oc);
ec.value = zerr;
Z_CONSTANT_FLAGS(ec.value) = 0;
zend_string *stderr_name = zend_string_init(ZEND_STRL("STDERR"), 0);
zend_hash_del(EG(zend_constants), stderr_name);
zend_register_constant(stderr_name, &ec);
zend_string_release(stderr_name);
ec.name = zend_string_init(ZEND_STRL("STDERR"), 0);
zend_hash_del(EG(zend_constants), ec.name);
zend_register_constant(&ec);
}
/* }}} */

View File

@ -100,15 +100,14 @@ PHPDBG_INFO(constants) /* {{{ */
{
HashTable consts;
zend_constant *data;
zend_string *name;
zend_hash_init(&consts, 8, NULL, NULL, 0);
if (EG(zend_constants)) {
phpdbg_try_access {
ZEND_HASH_MAP_FOREACH_STR_KEY_PTR(EG(zend_constants), name, data) {
ZEND_HASH_MAP_FOREACH_PTR(EG(zend_constants), data) {
if (ZEND_CONSTANT_MODULE_NUMBER(data) == PHP_USER_CONSTANT) {
zend_hash_update_ptr(&consts, name, data);
zend_hash_update_ptr(&consts, data->name, data);
}
} ZEND_HASH_FOREACH_END();
} phpdbg_catch_access {
@ -120,14 +119,14 @@ PHPDBG_INFO(constants) /* {{{ */
if (zend_hash_num_elements(&consts)) {
phpdbg_out("Address Refs Type Constant\n");
ZEND_HASH_MAP_FOREACH_STR_KEY_PTR(&consts, name, data) {
ZEND_HASH_MAP_FOREACH_PTR(&consts, data) {
#define VARIABLEINFO(msg, ...) \
phpdbg_writeln( \
"%-18p %-7d %-9s %.*s" msg, &data->value, \
Z_REFCOUNTED(data->value) ? Z_REFCOUNT(data->value) : 1, \
zend_get_type_by_const(Z_TYPE(data->value)), \
(int) ZSTR_LEN(name), ZSTR_VAL(name), ##__VA_ARGS__)
(int) ZSTR_LEN(data->name), ZSTR_VAL(data->name), ##__VA_ARGS__)
switch (Z_TYPE(data->value)) {
case IS_STRING: