Skip to content

Commit 4a18c89

Browse files
authored
Fix OSS-Fuzz #428053935 (#18969)
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.
1 parent db157e3 commit 4a18c89

File tree

7 files changed

+34
-16
lines changed

7 files changed

+34
-16
lines changed

‎UPGRADING.INTERNALS

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,8 @@ PHP 8.5 INTERNALS UPGRADE NOTES
4545
properties.
4646
. ZEND_IS_XDIGIT() macro was removed because it was unused and its name
4747
did not match its actual behavior.
48+
. zend_register_constant() now returns a pointer to the added constant
49+
on success and NULL on failure instead of SUCCESS/FAILURE.
4850

4951
========================
5052
2. Build system changes
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
--TEST--
2+
OSS-Fuzz #428053935
3+
--FILE--
4+
<?php
5+
namespace Foo; // Capital letter is important for the ns lookup
6+
#[Attr]
7+
const MyConst = '';
8+
9+
$rc = new \ReflectionConstant('Foo\\MyConst');
10+
var_dump($rc->getAttributes());
11+
?>
12+
--EXPECTF--
13+
array(1) {
14+
[0]=>
15+
object(ReflectionAttribute)#%d (1) {
16+
["name"]=>
17+
string(8) "Foo\Attr"
18+
}
19+
}

‎Zend/zend_builtin_functions.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -592,7 +592,7 @@ ZEND_FUNCTION(define)
592592
/* non persistent */
593593
ZEND_CONSTANT_SET_FLAGS(&c, 0, PHP_USER_CONSTANT);
594594
c.name = zend_string_copy(name);
595-
if (zend_register_constant(&c) == SUCCESS) {
595+
if (zend_register_constant(&c) != NULL) {
596596
RETURN_TRUE;
597597
} else {
598598
RETURN_FALSE;

‎Zend/zend_constants.c

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -505,11 +505,11 @@ static void* zend_hash_add_constant(HashTable *ht, zend_string *key, zend_consta
505505
return ret;
506506
}
507507

508-
ZEND_API zend_result zend_register_constant(zend_constant *c)
508+
ZEND_API zend_constant *zend_register_constant(zend_constant *c)
509509
{
510510
zend_string *lowercase_name = NULL;
511511
zend_string *name;
512-
zend_result ret = SUCCESS;
512+
zend_constant *ret = NULL;
513513
bool persistent = (ZEND_CONSTANT_FLAGS(c) & CONST_PERSISTENT) != 0;
514514

515515
#if 0
@@ -539,7 +539,7 @@ ZEND_API zend_result zend_register_constant(zend_constant *c)
539539
/* Check if the user is trying to define any special constant */
540540
if (zend_string_equals_literal(name, "__COMPILER_HALT_OFFSET__")
541541
|| (!persistent && zend_get_special_const(ZSTR_VAL(name), ZSTR_LEN(name)))
542-
|| zend_hash_add_constant(EG(zend_constants), name, c) == NULL
542+
|| (ret = zend_hash_add_constant(EG(zend_constants), name, c)) == NULL
543543
) {
544544
zend_error(E_WARNING, "Constant %s already defined", ZSTR_VAL(name));
545545
zend_string_release(c->name);
@@ -550,7 +550,6 @@ ZEND_API zend_result zend_register_constant(zend_constant *c)
550550
if (!persistent) {
551551
zval_ptr_dtor_nogc(&c->value);
552552
}
553-
ret = FAILURE;
554553
}
555554
if (lowercase_name) {
556555
zend_string_release(lowercase_name);

‎Zend/zend_constants.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,7 @@ ZEND_API void zend_register_long_constant(const char *name, size_t name_len, zen
9797
ZEND_API void zend_register_double_constant(const char *name, size_t name_len, double dval, int flags, int module_number);
9898
ZEND_API void zend_register_string_constant(const char *name, size_t name_len, const char *strval, int flags, int module_number);
9999
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);
100-
ZEND_API zend_result zend_register_constant(zend_constant *c);
100+
ZEND_API zend_constant *zend_register_constant(zend_constant *c);
101101
void zend_constant_add_attributes(zend_constant *c, HashTable *attributes);
102102
#ifdef ZTS
103103
void zend_copy_constants(HashTable *target, HashTable *source);

‎Zend/zend_vm_def.h

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8261,7 +8261,7 @@ ZEND_VM_HANDLER(143, ZEND_DECLARE_CONST, CONST, CONST)
82618261
ZEND_CONSTANT_SET_FLAGS(&c, 0, PHP_USER_CONSTANT);
82628262
c.name = zend_string_copy(Z_STR_P(name));
82638263

8264-
if (zend_register_constant(&c) == FAILURE) {
8264+
if (zend_register_constant(&c) == NULL) {
82658265
}
82668266

82678267
FREE_OP1();
@@ -8274,7 +8274,7 @@ ZEND_VM_HANDLER(210, ZEND_DECLARE_ATTRIBUTED_CONST, CONST, CONST)
82748274
USE_OPLINE
82758275
zval *name;
82768276
zval *val;
8277-
zend_constant c;
8277+
zend_constant c, *registered;
82788278

82798279
SAVE_OPLINE();
82808280
name = GET_OP1_ZVAL_PTR(BP_VAR_R);
@@ -8293,17 +8293,16 @@ ZEND_VM_HANDLER(210, ZEND_DECLARE_ATTRIBUTED_CONST, CONST, CONST)
82938293
ZEND_CONSTANT_SET_FLAGS(&c, 0, PHP_USER_CONSTANT);
82948294
c.name = zend_string_copy(Z_STR_P(name));
82958295

8296-
if (zend_register_constant(&c) == FAILURE) {
8296+
registered = zend_register_constant(&c);
8297+
if (registered == NULL) {
82978298
FREE_OP1();
82988299
FREE_OP2();
82998300
/* two opcodes used, second one is the data with attributes */
83008301
ZEND_VM_NEXT_OPCODE_EX(1, 2);
83018302
}
83028303

83038304
HashTable *attributes = Z_PTR_P(GET_OP_DATA_ZVAL_PTR(BP_VAR_R));
8304-
zend_constant *registered = zend_get_constant_ptr(c.name);
83058305
ZEND_ASSERT(attributes != NULL);
8306-
ZEND_ASSERT(registered != NULL);
83078306
zend_constant_add_attributes(registered, attributes);
83088307

83098308
FREE_OP1();

‎Zend/zend_vm_execute.h

Lines changed: 4 additions & 5 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)