diff --git a/Zend/Optimizer/zend_cfg.c b/Zend/Optimizer/zend_cfg.c index a0d08b67aa70..5c8a4c0a96c3 100644 --- a/Zend/Optimizer/zend_cfg.c +++ b/Zend/Optimizer/zend_cfg.c @@ -335,9 +335,13 @@ ZEND_API void zend_build_cfg(zend_arena **arena, const zend_op_array *op_array, flags |= ZEND_FUNC_HAS_CALLS; break; case ZEND_INIT_FCALL: + case ZEND_INIT_FCALL_BY_NAME: case ZEND_INIT_NS_FCALL_BY_NAME: zv = CRT_CONSTANT(opline->op2); - if (opline->opcode == ZEND_INIT_NS_FCALL_BY_NAME) { + if (opline->opcode == ZEND_INIT_FCALL_BY_NAME) { + /* The second literal is the lowercased name */ + zv += 1; + } else if (opline->opcode == ZEND_INIT_NS_FCALL_BY_NAME) { /* The third literal is the lowercased unqualified name */ zv += 2; } diff --git a/Zend/Optimizer/zend_optimizer.c b/Zend/Optimizer/zend_optimizer.c index 77af67fe6d73..9f8a77bee34c 100644 --- a/Zend/Optimizer/zend_optimizer.c +++ b/Zend/Optimizer/zend_optimizer.c @@ -817,7 +817,7 @@ static bool zend_optimizer_ignore_function(zval *fbc_zv, zend_string *filename) zend_function *fbc = Z_PTR_P(fbc_zv); if (fbc->type == ZEND_INTERNAL_FUNCTION) { - return false; + return fbc->internal_function.module->type == MODULE_TEMPORARY; } else if (fbc->type == ZEND_USER_FUNCTION) { if (fbc->op_array.fn_flags & ZEND_ACC_PRELOADED) { if (CG(compiler_options) & ZEND_COMPILE_WITH_FILE_CACHE) { diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c index 7e7e602f5895..fe8939f9c721 100644 --- a/Zend/zend_compile.c +++ b/Zend/zend_compile.c @@ -4234,7 +4234,9 @@ static bool zend_compile_ignore_class(zend_class_entry *ce, zend_string *filenam static bool zend_compile_ignore_function(zend_function *fbc, zend_string *filename) { if (fbc->type == ZEND_INTERNAL_FUNCTION) { - return CG(compiler_options) & ZEND_COMPILE_IGNORE_INTERNAL_FUNCTIONS; + return (CG(compiler_options) & ZEND_COMPILE_IGNORE_INTERNAL_FUNCTIONS) + || ((CG(compiler_options) & ZEND_COMPILE_IGNORE_OTHER_FILES) + && fbc->internal_function.module->type == MODULE_TEMPORARY); } else { return (CG(compiler_options) & ZEND_COMPILE_IGNORE_USER_FUNCTIONS) || ((CG(compiler_options) & ZEND_COMPILE_IGNORE_OTHER_FILES) diff --git a/ext/dl_test/tests/frameless_temporary_opcache.phpt b/ext/dl_test/tests/frameless_temporary_opcache.phpt index 547ee71d2145..994f0c3b0086 100644 --- a/ext/dl_test/tests/frameless_temporary_opcache.phpt +++ b/ext/dl_test/tests/frameless_temporary_opcache.phpt @@ -14,6 +14,6 @@ dl(PHP_OS_FAMILY === 'Windows' ? 'php_dl_test.dll' : 'dl_test.so'); include __DIR__ . '/frameless_temporary.inc'; ?> --EXPECTF-- -%A0001 INIT_FCALL 1 %d string("dl_test_frameless") +%A0001 INIT_FCALL_BY_NAME 1 string("dl_test_frameless") %Aint(7) dl_test_frameless(): Argument #1 ($value) must be of type int, string given diff --git a/ext/opcache/tests/gh25296.phpt b/ext/opcache/tests/gh25296.phpt new file mode 100644 index 000000000000..0d4ecf019b92 --- /dev/null +++ b/ext/opcache/tests/gh25296.phpt @@ -0,0 +1,105 @@ +--TEST-- +GH-25296 (Segfault or wrong function called with dl() and opcache.file_cache) +--EXTENSIONS-- +opcache +--SKIPIF-- + +--FILE-- +getMessage(), "\n"; +}); +if ($argv[1] === 'shifted') { + function a() {} + function b() {} +} +if ($argv[1] === 'user') { + function dl_test_test2(string $str): string { + return "User $str"; + } +} elseif ($argv[1] !== 'missing') { + dl('dl_test'); +} +include __DIR__ . '/call.php'; +PHP); + +function write_script(string $script, int $version): void { + file_put_contents($script, << ['pipe', 'w'], 2 => ['redirect', 1]], $pipes); + echo stream_get_contents($pipes[1]); + proc_close($proc); +} + +write_script($call, 1); +run($cache, $main, 'shifted'); + +write_script($call, 2); +echo "--- Function at another position ---\n"; +run($cache, $main, 'dl'); + +echo "--- Function not loaded ---\n"; +run($cache, $main, 'missing'); + +echo "--- User function of the same name ---\n"; +run($cache, $main, 'user'); +?> +--CLEAN-- +isDir() ? rmdir($file->getPathname()) : unlink($file->getPathname()); + } + rmdir($cache); +} +?> +--EXPECT-- +v1 +Hello hi +--- Function at another position --- +v1 +Hello hi +--- Function not loaded --- +v1 +Error: Call to undefined function dl_test_test2() +--- User function of the same name --- +v1 +User hi