From 43026a5d04e089d0f3aa8a9db6d846fd363226c8 Mon Sep 17 00:00:00 2001 From: Ilija Tovilo Date: Tue, 19 Nov 2024 18:55:05 +0100 Subject: [PATCH] Avoid registering top functions with opcache_compile_file() Previously, this only worked for classes. It worked by preventing early binding, and then declaring the class at runtime. Instead of doing that, we now avoid calling zend_accel_load_script() completely, which prevents the functions from being added to the function table. Fixes GH-16668 --- Zend/zend_compile.c | 3 +-- ext/opcache/tests/gh16668/gh16668.inc | 9 +++++++++ ext/opcache/tests/gh16668/gh16668.phpt | 20 ++++++++++++++++++++ ext/opcache/zend_accelerator_module.c | 4 +--- ext/opcache/zend_accelerator_util_funcs.c | 6 ++++++ 5 files changed, 37 insertions(+), 5 deletions(-) create mode 100644 ext/opcache/tests/gh16668/gh16668.inc create mode 100644 ext/opcache/tests/gh16668/gh16668.phpt diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c index fb436bdc20eab..5d195c35520b8 100644 --- a/Zend/zend_compile.c +++ b/Zend/zend_compile.c @@ -9120,8 +9120,7 @@ static void zend_compile_class_decl(znode *result, zend_ast *ast, bool toplevel) } /* We currently don't early-bind classes that implement interfaces or use traits */ - if (!ce->num_interfaces && !ce->num_traits && !ce->num_hooked_prop_variance_checks - && !(CG(compiler_options) & ZEND_COMPILE_WITHOUT_EXECUTION)) { + if (!ce->num_interfaces && !ce->num_traits && !ce->num_hooked_prop_variance_checks) { if (toplevel) { if (extends_ast) { zend_class_entry *parent_ce = zend_lookup_class_ex( diff --git a/ext/opcache/tests/gh16668/gh16668.inc b/ext/opcache/tests/gh16668/gh16668.inc new file mode 100644 index 0000000000000..d2d86785161a6 --- /dev/null +++ b/ext/opcache/tests/gh16668/gh16668.inc @@ -0,0 +1,9 @@ + +--EXPECT-- +bool(false) +bool(true) +test() diff --git a/ext/opcache/zend_accelerator_module.c b/ext/opcache/zend_accelerator_module.c index 2ed8155eff773..e85470674a6e8 100644 --- a/ext/opcache/zend_accelerator_module.c +++ b/ext/opcache/zend_accelerator_module.c @@ -981,9 +981,7 @@ ZEND_FUNCTION(opcache_compile_file) CG(compiler_options) = orig_compiler_options; - if(op_array != NULL) { - destroy_op_array(op_array); - efree(op_array); + if (op_array == (void *) -1) { RETVAL_TRUE; } else { RETVAL_FALSE; diff --git a/ext/opcache/zend_accelerator_util_funcs.c b/ext/opcache/zend_accelerator_util_funcs.c index 716a6e4df0094..113de6764715a 100644 --- a/ext/opcache/zend_accelerator_util_funcs.c +++ b/ext/opcache/zend_accelerator_util_funcs.c @@ -373,6 +373,12 @@ static void zend_accel_do_delayed_early_binding( zend_op_array* zend_accel_load_script(zend_persistent_script *persistent_script, int from_shared_memory) { + if (CG(compiler_options) & ZEND_COMPILE_WITHOUT_EXECUTION) { + /* Not a pretty API, but we need to distinguish between successful and + * unsuccessful compilations. */ + return (void *) -1; + } + zend_op_array *op_array; op_array = (zend_op_array *) emalloc(sizeof(zend_op_array));