Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit 99f72fa

Browse files
Merge branch 'PHP-8.4'
* PHP-8.4: Fix infinite recursion on deprecated attribute evaluation
2 parents ab6e464 + 272f7f7 commit 99f72fa

File tree

8 files changed

+73
-9
lines changed

8 files changed

+73
-9
lines changed
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
--TEST--
2+
GH-17711: Infinite recursion through deprecated class constants self-referencing through deprecation message
3+
--FILE--
4+
<?php
5+
6+
class C {
7+
#[\Deprecated(self::C)]
8+
const C = TEST;
9+
}
10+
11+
const TEST = 'Message';
12+
var_dump(C::C);
13+
14+
class D {
15+
#[\Deprecated(Alias::C)]
16+
const C = 'test';
17+
}
18+
19+
class_alias('D', 'Alias');
20+
var_dump(D::C);
21+
22+
?>
23+
--EXPECTF--
24+
Deprecated: Constant C::C is deprecated, Message in %s on line %d
25+
string(7) "Message"
26+
27+
Deprecated: Constant D::C is deprecated, test in %s on line %d
28+
string(4) "test"

‎Zend/zend_API.c‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1439,7 +1439,7 @@ ZEND_API HashTable *zend_separate_class_constants_table(zend_class_entry *class_
14391439

14401440
ZEND_HASH_MAP_FOREACH_STR_KEY_PTR(&class_type->constants_table, key, c) {
14411441
if (c->ce == class_type) {
1442-
if (Z_TYPE(c->value) == IS_CONSTANT_AST) {
1442+
if (Z_TYPE(c->value) == IS_CONSTANT_AST|| (ZEND_CLASS_CONST_FLAGS(c) &ZEND_ACC_DEPRECATED)) {
14431443
new_c = zend_arena_alloc(&CG(arena), sizeof(zend_class_constant));
14441444
memcpy(new_c, c, sizeof(zend_class_constant));
14451445
c = new_c;

‎Zend/zend_compile.c‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8862,6 +8862,10 @@ static void zend_compile_class_const_decl(zend_ast *ast, uint32_t flags, zend_as
88628862

88638863
if (deprecated) {
88648864
ZEND_CLASS_CONST_FLAGS(c) |= ZEND_ACC_DEPRECATED;
8865+
/* For deprecated constants, we need to flag the zval for recursion
8866+
* detection. Make sure the zval is separated out of shm. */
8867+
ce->ce_flags |= ZEND_ACC_HAS_AST_CONSTANTS;
8868+
ce->ce_flags &= ~ZEND_ACC_CONSTANTS_UPDATED;
88658869
}
88668870
}
88678871
}

‎Zend/zend_constants.c‎

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -362,8 +362,10 @@ ZEND_API zval *zend_get_class_constant_ex(zend_string *class_name, zend_string *
362362
}
363363

364364
if (UNEXPECTED(ZEND_CLASS_CONST_FLAGS(c) & ZEND_ACC_DEPRECATED)) {
365-
if ((flags & ZEND_FETCH_CLASS_SILENT) == 0) {
365+
if ((flags & ZEND_FETCH_CLASS_SILENT) == 0 && !CONST_IS_RECURSIVE(c)) {
366+
CONST_PROTECT_RECURSION(c);
366367
zend_deprecated_class_constant(c, constant_name);
368+
CONST_UNPROTECT_RECURSION(c);
367369
if (EG(exception)) {
368370
goto failure;
369371
}

‎Zend/zend_constants.h‎

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,17 @@
2727
#define CONST_NO_FILE_CACHE (1<<1) /* Can't be saved in file cache */
2828
#define CONST_DEPRECATED (1<<2) /* Deprecated */
2929
#define CONST_OWNED (1<<3) /* constant should be destroyed together with class */
30+
#define CONST_RECURSIVE (1<<4) /* Recursion protection for constant evaluation */
31+
32+
#define CONST_IS_RECURSIVE(c) (Z_CONSTANT_FLAGS((c)->value) & CONST_RECURSIVE)
33+
#define CONST_PROTECT_RECURSION(c) \
34+
do { \
35+
Z_CONSTANT_FLAGS((c)->value) |= CONST_RECURSIVE; \
36+
} while (0)
37+
#define CONST_UNPROTECT_RECURSION(c) \
38+
do { \
39+
Z_CONSTANT_FLAGS((c)->value) &= ~CONST_RECURSIVE; \
40+
} while (0)
3041

3142
#define PHP_USER_CONSTANT 0x7fffff /* a constant defined in user space */
3243

‎Zend/zend_vm_def.h‎

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6103,8 +6103,10 @@ ZEND_VM_HANDLER(181, ZEND_FETCH_CLASS_CONSTANT, VAR|CONST|UNUSED|CLASS_FETCH, CO
61036103
}
61046104

61056105
bool is_constant_deprecated = ZEND_CLASS_CONST_FLAGS(c) & ZEND_ACC_DEPRECATED;
6106-
if (UNEXPECTED(is_constant_deprecated)) {
6106+
if (UNEXPECTED(is_constant_deprecated) && !CONST_IS_RECURSIVE(c)) {
6107+
CONST_PROTECT_RECURSION(c);
61076108
zend_deprecated_class_constant(c, constant_name);
6109+
CONST_UNPROTECT_RECURSION(c);
61086110

61096111
if (EG(exception)) {
61106112
ZVAL_UNDEF(EX_VAR(opline->result.var));

‎Zend/zend_vm_execute.h‎

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

‎ext/opcache/ZendAccelerator.c‎

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3864,6 +3864,11 @@ static bool preload_try_resolve_constants(zend_class_entry *ce)
38643864
ZEND_HASH_MAP_FOREACH_STR_KEY_PTR(&ce->constants_table, key, c) {
38653865
val = &c->value;
38663866
if (Z_TYPE_P(val) == IS_CONSTANT_AST) {
3867+
/* For deprecated constants, we need to flag the zval for recursion
3868+
* detection. Make sure the zval is separated out of shm. */
3869+
if (ZEND_CLASS_CONST_FLAGS(c) & ZEND_ACC_DEPRECATED) {
3870+
ok = false;
3871+
}
38673872
if (EXPECTED(zend_update_class_constant(c, key, c->ce) == SUCCESS)) {
38683873
was_changed = changed = true;
38693874
} else {

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /