Registering the constant may happen under another name due to
lowercasing. This will cause the lookup to the constant to fail.
Instead of looking it up, just change the Zend API to return a pointer
instead.
This commit is contained in:
Niels Dossche 2025-06-30 09:09:55 +02:00 committed by GitHub
parent db157e3168
commit 4a18c895ca
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
7 changed files with 34 additions and 16 deletions

View file

@ -45,6 +45,8 @@ PHP 8.5 INTERNALS UPGRADE NOTES
properties. properties.
. ZEND_IS_XDIGIT() macro was removed because it was unused and its name . ZEND_IS_XDIGIT() macro was removed because it was unused and its name
did not match its actual behavior. did not match its actual behavior.
. zend_register_constant() now returns a pointer to the added constant
on success and NULL on failure instead of SUCCESS/FAILURE.
======================== ========================
2. Build system changes 2. Build system changes

View file

@ -0,0 +1,19 @@
--TEST--
OSS-Fuzz #428053935
--FILE--
<?php
namespace Foo; // Capital letter is important for the ns lookup
#[Attr]
const MyConst = '';
$rc = new \ReflectionConstant('Foo\\MyConst');
var_dump($rc->getAttributes());
?>
--EXPECTF--
array(1) {
[0]=>
object(ReflectionAttribute)#%d (1) {
["name"]=>
string(8) "Foo\Attr"
}
}

View file

@ -592,7 +592,7 @@ register_constant:
/* non persistent */ /* non persistent */
ZEND_CONSTANT_SET_FLAGS(&c, 0, PHP_USER_CONSTANT); ZEND_CONSTANT_SET_FLAGS(&c, 0, PHP_USER_CONSTANT);
c.name = zend_string_copy(name); c.name = zend_string_copy(name);
if (zend_register_constant(&c) == SUCCESS) { if (zend_register_constant(&c) != NULL) {
RETURN_TRUE; RETURN_TRUE;
} else { } else {
RETURN_FALSE; RETURN_FALSE;

View file

@ -505,11 +505,11 @@ static void* zend_hash_add_constant(HashTable *ht, zend_string *key, zend_consta
return ret; return ret;
} }
ZEND_API zend_result zend_register_constant(zend_constant *c) ZEND_API zend_constant *zend_register_constant(zend_constant *c)
{ {
zend_string *lowercase_name = NULL; zend_string *lowercase_name = NULL;
zend_string *name; zend_string *name;
zend_result ret = SUCCESS; zend_constant *ret = NULL;
bool persistent = (ZEND_CONSTANT_FLAGS(c) & CONST_PERSISTENT) != 0; bool persistent = (ZEND_CONSTANT_FLAGS(c) & CONST_PERSISTENT) != 0;
#if 0 #if 0
@ -539,7 +539,7 @@ ZEND_API zend_result zend_register_constant(zend_constant *c)
/* Check if the user is trying to define any special constant */ /* Check if the user is trying to define any special constant */
if (zend_string_equals_literal(name, "__COMPILER_HALT_OFFSET__") if (zend_string_equals_literal(name, "__COMPILER_HALT_OFFSET__")
|| (!persistent && zend_get_special_const(ZSTR_VAL(name), ZSTR_LEN(name))) || (!persistent && zend_get_special_const(ZSTR_VAL(name), ZSTR_LEN(name)))
|| zend_hash_add_constant(EG(zend_constants), name, c) == NULL || (ret = zend_hash_add_constant(EG(zend_constants), name, c)) == NULL
) { ) {
zend_error(E_WARNING, "Constant %s already defined", ZSTR_VAL(name)); zend_error(E_WARNING, "Constant %s already defined", ZSTR_VAL(name));
zend_string_release(c->name); zend_string_release(c->name);
@ -550,7 +550,6 @@ ZEND_API zend_result zend_register_constant(zend_constant *c)
if (!persistent) { if (!persistent) {
zval_ptr_dtor_nogc(&c->value); zval_ptr_dtor_nogc(&c->value);
} }
ret = FAILURE;
} }
if (lowercase_name) { if (lowercase_name) {
zend_string_release(lowercase_name); zend_string_release(lowercase_name);

View file

@ -97,7 +97,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_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_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 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_constant(zend_constant *c); ZEND_API zend_constant *zend_register_constant(zend_constant *c);
void zend_constant_add_attributes(zend_constant *c, HashTable *attributes); void zend_constant_add_attributes(zend_constant *c, HashTable *attributes);
#ifdef ZTS #ifdef ZTS
void zend_copy_constants(HashTable *target, HashTable *source); void zend_copy_constants(HashTable *target, HashTable *source);

View file

@ -8261,7 +8261,7 @@ ZEND_VM_HANDLER(143, ZEND_DECLARE_CONST, CONST, CONST)
ZEND_CONSTANT_SET_FLAGS(&c, 0, PHP_USER_CONSTANT); ZEND_CONSTANT_SET_FLAGS(&c, 0, PHP_USER_CONSTANT);
c.name = zend_string_copy(Z_STR_P(name)); c.name = zend_string_copy(Z_STR_P(name));
if (zend_register_constant(&c) == FAILURE) { if (zend_register_constant(&c) == NULL) {
} }
FREE_OP1(); FREE_OP1();
@ -8274,7 +8274,7 @@ ZEND_VM_HANDLER(210, ZEND_DECLARE_ATTRIBUTED_CONST, CONST, CONST)
USE_OPLINE USE_OPLINE
zval *name; zval *name;
zval *val; zval *val;
zend_constant c; zend_constant c, *registered;
SAVE_OPLINE(); SAVE_OPLINE();
name = GET_OP1_ZVAL_PTR(BP_VAR_R); name = GET_OP1_ZVAL_PTR(BP_VAR_R);
@ -8293,7 +8293,8 @@ ZEND_VM_HANDLER(210, ZEND_DECLARE_ATTRIBUTED_CONST, CONST, CONST)
ZEND_CONSTANT_SET_FLAGS(&c, 0, PHP_USER_CONSTANT); ZEND_CONSTANT_SET_FLAGS(&c, 0, PHP_USER_CONSTANT);
c.name = zend_string_copy(Z_STR_P(name)); c.name = zend_string_copy(Z_STR_P(name));
if (zend_register_constant(&c) == FAILURE) { registered = zend_register_constant(&c);
if (registered == NULL) {
FREE_OP1(); FREE_OP1();
FREE_OP2(); FREE_OP2();
/* two opcodes used, second one is the data with attributes */ /* two opcodes used, second one is the data with attributes */
@ -8301,9 +8302,7 @@ ZEND_VM_HANDLER(210, ZEND_DECLARE_ATTRIBUTED_CONST, CONST, CONST)
} }
HashTable *attributes = Z_PTR_P(GET_OP_DATA_ZVAL_PTR(BP_VAR_R)); HashTable *attributes = Z_PTR_P(GET_OP_DATA_ZVAL_PTR(BP_VAR_R));
zend_constant *registered = zend_get_constant_ptr(c.name);
ZEND_ASSERT(attributes != NULL); ZEND_ASSERT(attributes != NULL);
ZEND_ASSERT(registered != NULL);
zend_constant_add_attributes(registered, attributes); zend_constant_add_attributes(registered, attributes);
FREE_OP1(); FREE_OP1();

View file

@ -8043,7 +8043,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DECLARE_CONST_SPEC_CONST_CONST
ZEND_CONSTANT_SET_FLAGS(&c, 0, PHP_USER_CONSTANT); ZEND_CONSTANT_SET_FLAGS(&c, 0, PHP_USER_CONSTANT);
c.name = zend_string_copy(Z_STR_P(name)); c.name = zend_string_copy(Z_STR_P(name));
if (zend_register_constant(&c) == FAILURE) { if (zend_register_constant(&c) == NULL) {
} }
@ -8055,7 +8055,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DECLARE_ATTRIBUTED_CONST_SPEC_
USE_OPLINE USE_OPLINE
zval *name; zval *name;
zval *val; zval *val;
zend_constant c; zend_constant c, *registered;
SAVE_OPLINE(); SAVE_OPLINE();
name = RT_CONSTANT(opline, opline->op1); name = RT_CONSTANT(opline, opline->op1);
@ -8074,7 +8074,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DECLARE_ATTRIBUTED_CONST_SPEC_
ZEND_CONSTANT_SET_FLAGS(&c, 0, PHP_USER_CONSTANT); ZEND_CONSTANT_SET_FLAGS(&c, 0, PHP_USER_CONSTANT);
c.name = zend_string_copy(Z_STR_P(name)); c.name = zend_string_copy(Z_STR_P(name));
if (zend_register_constant(&c) == FAILURE) { registered = zend_register_constant(&c);
if (registered == NULL) {
/* two opcodes used, second one is the data with attributes */ /* two opcodes used, second one is the data with attributes */
@ -8082,9 +8083,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DECLARE_ATTRIBUTED_CONST_SPEC_
} }
HashTable *attributes = Z_PTR_P(get_op_data_zval_ptr_r((opline+1)->op1_type, (opline+1)->op1)); HashTable *attributes = Z_PTR_P(get_op_data_zval_ptr_r((opline+1)->op1_type, (opline+1)->op1));
zend_constant *registered = zend_get_constant_ptr(c.name);
ZEND_ASSERT(attributes != NULL); ZEND_ASSERT(attributes != NULL);
ZEND_ASSERT(registered != NULL);
zend_constant_add_attributes(registered, attributes); zend_constant_add_attributes(registered, attributes);