From 89007f67d4583e70f966ff5b38832fb5dc9ed766 Mon Sep 17 00:00:00 2001 From: Nikita Popov Date: Thu, 14 Oct 2021 14:28:00 +0200 Subject: [PATCH] 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. --- .../no_early_binding_if_already_declared.inc | 5 +++++ .../no_early_binding_if_already_declared.phpt | 11 ++++++++++ ext/opcache/tests/bug67215.phpt | 2 +- ext/opcache/zend_accelerator_util_funcs.c | 21 +++++++++++-------- 4 files changed, 29 insertions(+), 10 deletions(-) create mode 100644 Zend/tests/no_early_binding_if_already_declared.inc create mode 100644 Zend/tests/no_early_binding_if_already_declared.phpt diff --git a/Zend/tests/no_early_binding_if_already_declared.inc b/Zend/tests/no_early_binding_if_already_declared.inc new file mode 100644 index 0000000000000..e2feae12b084c --- /dev/null +++ b/Zend/tests/no_early_binding_if_already_declared.inc @@ -0,0 +1,5 @@ + +===DONE=== +--EXPECT-- +===DONE=== diff --git a/ext/opcache/tests/bug67215.phpt b/ext/opcache/tests/bug67215.phpt index d9bb18e8abf36..133efaf435b1d 100644 --- a/ext/opcache/tests/bug67215.phpt +++ b/ext/opcache/tests/bug67215.phpt @@ -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 diff --git a/ext/opcache/zend_accelerator_util_funcs.c b/ext/opcache/zend_accelerator_util_funcs.c index 16d82a6dd6009..002ea3e5d22b5 100644 --- a/ext/opcache/zend_accelerator_util_funcs.c +++ b/ext/opcache/zend_accelerator_util_funcs.c @@ -320,18 +320,21 @@ 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]; - 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 *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); - if (ce && early_binding->cache_slot != (uint32_t) -1) { - *(void**)((char*)run_time_cache + early_binding->cache_slot) = ce; + 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 *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(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;