Fix delayed early bind if class already exists

We should not try to perform a delayed early bind if the class has
already been declared. This matches the behavior of an ordinary
early bind.
This commit is contained in:
Nikita Popov 2021-10-14 14:28:00 +02:00
parent 7193909e86
commit 89007f67d4
4 changed files with 29 additions and 10 deletions

View file

@ -0,0 +1,5 @@
<?php
if (class_exists(B::class)) {
return;
}
class B extends A {}

View file

@ -0,0 +1,11 @@
--TEST--
No early binding should occur if the class is already declared
--FILE--
<?php
class A {}
class B extends A {}
include __DIR__ . '/no_early_binding_if_already_declared.inc';
?>
===DONE===
--EXPECT--
===DONE===

View file

@ -25,4 +25,4 @@ unlink($file_c);
unlink($file_p);
?>
--EXPECTF--
Fatal error: Cannot declare class c, because the name is already in use in %sbug67215.c.php on line %d
Fatal error: Cannot declare class p, because the name is already in use in %sbug67215.p.php on line %d

View file

@ -320,19 +320,22 @@ static void zend_accel_do_delayed_early_binding(
CG(in_compilation) = 1;
for (uint32_t i = 0; i < persistent_script->num_early_bindings; i++) {
zend_early_binding *early_binding = &persistent_script->early_bindings[i];
zend_class_entry *ce = zend_hash_find_ex_ptr(EG(class_table), early_binding->lcname, 1);
if (!ce) {
zval *zv = zend_hash_find_known_hash(EG(class_table), early_binding->rtd_key);
if (zv) {
zend_class_entry *ce = Z_CE_P(zv);
zend_class_entry *orig_ce = Z_CE_P(zv);
zend_class_entry *parent_ce =
zend_hash_find_ex_ptr(EG(class_table), early_binding->lc_parent_name, 1);
if (parent_ce) {
ce = zend_try_early_bind(ce, parent_ce, early_binding->lcname, zv);
ce = zend_try_early_bind(orig_ce, parent_ce, early_binding->lcname, zv);
}
}
}
if (ce && early_binding->cache_slot != (uint32_t) -1) {
*(void**)((char*)run_time_cache + early_binding->cache_slot) = ce;
}
}
}
}
CG(compiled_filename) = orig_compiled_filename;
CG(in_compilation) = orig_in_compilation;
}