Skip to content

Commit 32c1f37

Browse files
committed
Fixed bug #78926: Handle class table reallocation on failed link
When we change back the bucket key on a class linking failure, make sure to reload the bucket pointer, as the class table may have been reallocated in the meantime. Also remove a bogus bucket key change in anon class registration: We don't actually rename the class in this case anymore, the RTD key is already the final name.
1 parent 3d90b77 commit 32c1f37

File tree

5 files changed

+29
-2
lines changed

5 files changed

+29
-2
lines changed

NEWS

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ PHP NEWS
1313
. Fixed bug #78898 (call_user_func(['parent', ...]) fails while other
1414
succeed). (Nikita)
1515
. Fixed bug #78904 (Uninitialized property triggers __get()). (Nikita)
16+
. Fixed bug #78926 (Segmentation fault on Symfony cache:clear). (Nikita)
1617

1718
- GD:
1819
. Fixed bug #78849 (GD build broken with -D SIGNED_COMPARE_SLOW). (cmb)

Zend/tests/bug78926.phpt

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
--TEST--
2+
Bug #78926: Segmentation fault on Symfony cache:clear
3+
--FILE--
4+
<?php
5+
6+
spl_autoload_register(function($class) {
7+
for ($i = 0; $i < 100; $i++) {
8+
eval("class C$i {}");
9+
}
10+
});
11+
12+
try {
13+
class B extends A {}
14+
} catch (Error $e) {
15+
echo $e->getMessage(), "\n";
16+
}
17+
var_dump(class_exists('B', false));
18+
19+
?>
20+
--EXPECT--
21+
Class 'A' not found
22+
bool(false)

Zend/zend_compile.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1082,6 +1082,8 @@ ZEND_API int do_bind_class(zval *lcname, zend_string *lc_parent_name) /* {{{ */
10821082
}
10831083

10841084
if (zend_do_link_class(ce, lc_parent_name) == FAILURE) {
1085+
/* Reload bucket pointer, the hash table may have been reallocated */
1086+
zv = zend_hash_find(EG(class_table), Z_STR_P(lcname));
10851087
zend_hash_set_bucket_key(EG(class_table), (Bucket *) zv, Z_STR_P(rtd_key));
10861088
return FAILURE;
10871089
}

Zend/zend_vm_def.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7284,6 +7284,8 @@ ZEND_VM_HANDLER(145, ZEND_DECLARE_CLASS_DELAYED, CONST, CONST)
72847284
zend_error_noreturn(E_COMPILE_ERROR, "Cannot declare %s %s, because the name is already in use", zend_get_object_type(ce), ZSTR_VAL(ce->name));
72857285
} else {
72867286
if (zend_do_link_class(ce, Z_STR_P(RT_CONSTANT(opline, opline->op2))) == FAILURE) {
7287+
/* Reload bucket pointer, the hash table may have been reallocated */
7288+
zv = zend_hash_find(EG(class_table), Z_STR_P(lcname));
72877289
zend_hash_set_bucket_key(EG(class_table), (Bucket *) zv, Z_STR_P(lcname + 1));
72887290
HANDLE_EXCEPTION();
72897291
}
@@ -7309,7 +7311,6 @@ ZEND_VM_HANDLER(146, ZEND_DECLARE_ANON_CLASS, ANY, ANY, CACHE_SLOT)
73097311
if (!(ce->ce_flags & ZEND_ACC_LINKED)) {
73107312
SAVE_OPLINE();
73117313
if (zend_do_link_class(ce, (OP2_TYPE == IS_CONST) ? Z_STR_P(RT_CONSTANT(opline, opline->op2)) : NULL) == FAILURE) {
7312-
zend_hash_set_bucket_key(EG(class_table), (Bucket *) zv, rtd_key);
73137314
HANDLE_EXCEPTION();
73147315
}
73157316
}

Zend/zend_vm_execute.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2451,7 +2451,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DECLARE_ANON_CLASS_SPEC_HANDLE
24512451
if (!(ce->ce_flags & ZEND_ACC_LINKED)) {
24522452
SAVE_OPLINE();
24532453
if (zend_do_link_class(ce, (opline->op2_type == IS_CONST) ? Z_STR_P(RT_CONSTANT(opline, opline->op2)) : NULL) == FAILURE) {
2454-
zend_hash_set_bucket_key(EG(class_table), (Bucket *) zv, rtd_key);
24552454
HANDLE_EXCEPTION();
24562455
}
24572456
}
@@ -6395,6 +6394,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DECLARE_CLASS_DELAYED_SPEC_CON
63956394
zend_error_noreturn(E_COMPILE_ERROR, "Cannot declare %s %s, because the name is already in use", zend_get_object_type(ce), ZSTR_VAL(ce->name));
63966395
} else {
63976396
if (zend_do_link_class(ce, Z_STR_P(RT_CONSTANT(opline, opline->op2))) == FAILURE) {
6397+
/* Reload bucket pointer, the hash table may have been reallocated */
6398+
zv = zend_hash_find(EG(class_table), Z_STR_P(lcname));
63986399
zend_hash_set_bucket_key(EG(class_table), (Bucket *) zv, Z_STR_P(lcname + 1));
63996400
HANDLE_EXCEPTION();
64006401
}

0 commit comments

Comments
 (0)