Skip to content

Commit 43026a5

Browse files
committed
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
1 parent 9b3af02 commit 43026a5

File tree

5 files changed

+37
-5
lines changed

5 files changed

+37
-5
lines changed

Zend/zend_compile.c

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9120,8 +9120,7 @@ static void zend_compile_class_decl(znode *result, zend_ast *ast, bool toplevel)
91209120
}
91219121

91229122
/* We currently don't early-bind classes that implement interfaces or use traits */
9123-
if (!ce->num_interfaces && !ce->num_traits && !ce->num_hooked_prop_variance_checks
9124-
&& !(CG(compiler_options) & ZEND_COMPILE_WITHOUT_EXECUTION)) {
9123+
if (!ce->num_interfaces && !ce->num_traits && !ce->num_hooked_prop_variance_checks) {
91259124
if (toplevel) {
91269125
if (extends_ast) {
91279126
zend_class_entry *parent_ce = zend_lookup_class_ex(
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
<?php
2+
3+
function test() {
4+
echo __FUNCTION__, "()\n";
5+
}
6+
7+
function a() {}
8+
function b() {}
9+
function c() {}
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
--TEST--
2+
GH-16668: opcache_compile_file() mistakenly declares top functions
3+
--INI--
4+
opcache.enable=1
5+
opcache.enable_cli=1
6+
--EXTENSIONS--
7+
opcache
8+
--FILE--
9+
<?php
10+
opcache_compile_file(__DIR__ . '/gh16668.inc');
11+
opcache_compile_file(__DIR__ . '/gh16668.inc');
12+
var_dump(function_exists('test'));
13+
require __DIR__ . '/gh16668.inc';
14+
var_dump(function_exists('test'));
15+
test();
16+
?>
17+
--EXPECT--
18+
bool(false)
19+
bool(true)
20+
test()

ext/opcache/zend_accelerator_module.c

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -981,9 +981,7 @@ ZEND_FUNCTION(opcache_compile_file)
981981

982982
CG(compiler_options) = orig_compiler_options;
983983

984-
if(op_array != NULL) {
985-
destroy_op_array(op_array);
986-
efree(op_array);
984+
if (op_array == (void *) -1) {
987985
RETVAL_TRUE;
988986
} else {
989987
RETVAL_FALSE;

ext/opcache/zend_accelerator_util_funcs.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -373,6 +373,12 @@ static void zend_accel_do_delayed_early_binding(
373373

374374
zend_op_array* zend_accel_load_script(zend_persistent_script *persistent_script, int from_shared_memory)
375375
{
376+
if (CG(compiler_options) & ZEND_COMPILE_WITHOUT_EXECUTION) {
377+
/* Not a pretty API, but we need to distinguish between successful and
378+
* unsuccessful compilations. */
379+
return (void *) -1;
380+
}
381+
376382
zend_op_array *op_array;
377383

378384
op_array = (zend_op_array *) emalloc(sizeof(zend_op_array));

0 commit comments

Comments
 (0)