From 0dabd2fadfa14c4947808e245cef7bb5729f3faf Mon Sep 17 00:00:00 2001 From: Ilija Tovilo Date: Sun, 9 Jun 2024 02:34:50 +0200 Subject: [PATCH 1/2] Flip scope lookup order for ns function calls --- Zend/tests/bug74164.phpt | 5 +-- .../call_user_func_strict_arginfo_check.phpt | 3 +- Zend/tests/frameless_jmp_004.phpt | 3 +- Zend/tests/namespaces/ns_013.phpt | 2 +- Zend/zend_compile.c | 32 ++++++++++++++----- .../tests/ReflectionFiber_notrace_2.phpt | 7 ++-- .../tests/observer_call_user_func_03.phpt | 5 +-- .../tests/observer_call_user_func_04.phpt | 5 +-- sapi/phpdbg/tests/print_001.phpt | 6 ++-- 9 files changed, 44 insertions(+), 24 deletions(-) diff --git a/Zend/tests/bug74164.phpt b/Zend/tests/bug74164.phpt index ef56f10225fd2..a9d189b4b9be5 100644 --- a/Zend/tests/bug74164.phpt +++ b/Zend/tests/bug74164.phpt @@ -9,12 +9,13 @@ set_error_handler(function ($type, $msg) { throw new \Exception($msg); }); -call_user_func(function (array &$ref) {var_dump("xxx");}, 'not_an_array_variable'); +$fn = 'call_user_func'; +$fn(function (array &$ref) {var_dump("xxx");}, 'not_an_array_variable'); ?> --EXPECTF-- Fatal error: Uncaught Exception: {closure:%s:%d}(): Argument #1 ($ref) must be passed by reference, value given in %s:%d Stack trace: -#0 [internal function]: {closure:%s:%d}(2, '%s', '%s', 9) +#0 [internal function]: {closure:%s:%d}(2, '%s', '%s', 10) #1 %sbug74164.php(%d): call_user_func(%s) #2 {main} thrown in %sbug74164.php on line %d diff --git a/Zend/tests/call_user_functions/call_user_func_strict_arginfo_check.phpt b/Zend/tests/call_user_functions/call_user_func_strict_arginfo_check.phpt index 1f21ee989dd5a..4032998a35361 100644 --- a/Zend/tests/call_user_functions/call_user_func_strict_arginfo_check.phpt +++ b/Zend/tests/call_user_functions/call_user_func_strict_arginfo_check.phpt @@ -7,7 +7,8 @@ declare(strict_types=1); namespace Foo; // strlen() will be called with strict_types=0, so this is legal. -var_dump(call_user_func('strlen', false)); +$fn = 'call_user_func'; +var_dump($fn('strlen', false)); ?> --EXPECT-- diff --git a/Zend/tests/frameless_jmp_004.phpt b/Zend/tests/frameless_jmp_004.phpt index 2597754641ed8..6de0d5dbda520 100644 --- a/Zend/tests/frameless_jmp_004.phpt +++ b/Zend/tests/frameless_jmp_004.phpt @@ -13,5 +13,4 @@ declare_local_class_exists(); var_dump(CLASS_EXISTS('Foo')); ?> --EXPECT-- -string(16) "Foo\class_exists" -bool(true) +bool(false) diff --git a/Zend/tests/namespaces/ns_013.phpt b/Zend/tests/namespaces/ns_013.phpt index f268fe2f96254..d498481bf7449 100644 --- a/Zend/tests/namespaces/ns_013.phpt +++ b/Zend/tests/namespaces/ns_013.phpt @@ -11,4 +11,4 @@ function strlen($x) { echo strlen("Hello"),"\n"; ?> --EXPECT-- -test\ns1\strlen +5 diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c index 203201bcc12b5..95edebfff878b 100644 --- a/Zend/zend_compile.c +++ b/Zend/zend_compile.c @@ -634,17 +634,17 @@ static int zend_add_ns_func_name_literal(zend_string *name) /* {{{ */ /* Original name */ int ret = zend_add_literal_string(&name); - /* Lowercased name */ - zend_string *lc_name = zend_string_tolower(name); - zend_add_literal_string(&lc_name); - /* Lowercased unqualified name */ if (zend_get_unqualified_name(name, &unqualified_name, &unqualified_name_len)) { - lc_name = zend_string_alloc(unqualified_name_len, 0); + zend_string *lc_name = zend_string_alloc(unqualified_name_len, 0); zend_str_tolower_copy(ZSTR_VAL(lc_name), unqualified_name, unqualified_name_len); zend_add_literal_string(&lc_name); } + /* Lowercased name */ + zend_string *lc_name = zend_string_tolower(name); + zend_add_literal_string(&lc_name); + return ret; } /* }}} */ @@ -1069,9 +1069,11 @@ static zend_string *zend_prefix_with_ns(zend_string *name) { } } +static bool zend_compile_ignore_function(const zend_function *fbc, const zend_string *filename); + static zend_string *zend_resolve_non_class_name( zend_string *name, uint32_t type, bool *is_fully_qualified, - bool case_sensitive, const HashTable *current_import_sub + bool case_sensitive, bool function ) { const char *compound; *is_fully_qualified = false; @@ -1092,6 +1094,7 @@ static zend_string *zend_resolve_non_class_name( return zend_prefix_with_ns(name); } + HashTable *current_import_sub = function ? FC(imports_function) : FC(imports_const); if (current_import_sub) { /* If an unqualified name is a function/const alias, replace it. */ zend_string *import_name; @@ -1123,6 +1126,19 @@ static zend_string *zend_resolve_non_class_name( } } + if (!compound && function) { + zend_string *lcname = zend_string_tolower(name); + zval *fbc_zv = zend_hash_find(CG(function_table), lcname); + if (fbc_zv + && CG(active_op_array) + && !zend_compile_ignore_function(Z_PTR_P(fbc_zv), CG(active_op_array)->filename)) { + *is_fully_qualified = true; + zend_string_release(lcname); + return zend_string_copy(name); + } + zend_string_release(lcname); + } + return zend_prefix_with_ns(name); } /* }}} */ @@ -1130,13 +1146,13 @@ static zend_string *zend_resolve_non_class_name( static zend_string *zend_resolve_function_name(zend_string *name, uint32_t type, bool *is_fully_qualified) { return zend_resolve_non_class_name( - name, type, is_fully_qualified, false, FC(imports_function)); + name, type, is_fully_qualified, false, /* function */ true); } static zend_string *zend_resolve_const_name(zend_string *name, uint32_t type, bool *is_fully_qualified) { return zend_resolve_non_class_name( - name, type, is_fully_qualified, true, FC(imports_const)); + name, type, is_fully_qualified, true, /* function */ false); } static zend_string *zend_resolve_class_name(zend_string *name, uint32_t type) /* {{{ */ diff --git a/ext/reflection/tests/ReflectionFiber_notrace_2.phpt b/ext/reflection/tests/ReflectionFiber_notrace_2.phpt index bd9078fc33c85..215b2c786deeb 100644 --- a/ext/reflection/tests/ReflectionFiber_notrace_2.phpt +++ b/ext/reflection/tests/ReflectionFiber_notrace_2.phpt @@ -5,7 +5,8 @@ ReflectionFiber should not segfault when inspecting fibers where the previous st namespace test; -$f = new \Fiber(fn() => call_user_func(["Fiber", "suspend"])); +$fn = 'call_user_func'; +$f = new \Fiber(fn() => $fn(["Fiber", "suspend"])); $f->start(); $reflection = new \ReflectionFiber($f); @@ -17,7 +18,7 @@ var_dump($reflection->getTrace()); ?> --EXPECTF-- string(%d) "%sReflectionFiber_notrace_2.php" -int(5) +int(6) array(3) { [0]=> array(4) { @@ -36,7 +37,7 @@ array(3) { ["file"]=> string(%d) "%sReflectionFiber_notrace_2.php" ["line"]=> - int(5) + int(6) ["function"]=> string(14) "call_user_func" ["args"]=> diff --git a/ext/zend_test/tests/observer_call_user_func_03.phpt b/ext/zend_test/tests/observer_call_user_func_03.phpt index 5e1932bc57039..e86dc5a243410 100644 --- a/ext/zend_test/tests/observer_call_user_func_03.phpt +++ b/ext/zend_test/tests/observer_call_user_func_03.phpt @@ -22,8 +22,9 @@ namespace Test { echo 'my_function called' . PHP_EOL; } - call_user_func('Test\\MyClass::myMethod'); - call_user_func('Test\\my_function'); + $fn = 'call_user_func'; + $fn('Test\\MyClass::myMethod'); + $fn('Test\\my_function'); } ?> --EXPECTF-- diff --git a/ext/zend_test/tests/observer_call_user_func_04.phpt b/ext/zend_test/tests/observer_call_user_func_04.phpt index 679a82407ce05..52bf417bcbe86 100644 --- a/ext/zend_test/tests/observer_call_user_func_04.phpt +++ b/ext/zend_test/tests/observer_call_user_func_04.phpt @@ -22,8 +22,9 @@ namespace Test { echo 'my_function ' . $msg . PHP_EOL; } - call_user_func_array('Test\\MyClass::myMethod', ['called']); - call_user_func_array('Test\\my_function', ['called']); + $fn = 'call_user_func_array'; + $fn('Test\\MyClass::myMethod', ['called']); + $fn('Test\\my_function', ['called']); } ?> --EXPECTF-- diff --git a/sapi/phpdbg/tests/print_001.phpt b/sapi/phpdbg/tests/print_001.phpt index ae1b7991973bd..c7b8699366da3 100644 --- a/sapi/phpdbg/tests/print_001.phpt +++ b/sapi/phpdbg/tests/print_001.phpt @@ -29,9 +29,9 @@ Foo\Bar::Foo: ; (lines=5, args=1, vars=1, tmps=%d) ; %s:5-7 L0005 0000 CV0($bar) = RECV 1 -L0006 0001 INIT_NS_FCALL_BY_NAME 1 string("Foo\\var_dump") -L0006 0002 SEND_VAR_EX CV0($bar) 1 -L0006 0003 DO_FCALL +L0006 0001 INIT_FCALL %d %d string("var_dump") +L0006 0002 SEND_VAR CV0($bar) 1 +L0006 0003 DO_ICALL L0007 0004 RETURN null Foo\Bar::baz: From e05adabc08be186e8558be62f80c45fc32b50d01 Mon Sep 17 00:00:00 2001 From: Ilija Tovilo Date: Sun, 9 Jun 2024 13:19:06 +0200 Subject: [PATCH 2/2] wp-cli shadows parse_url(), disable for now --- .github/workflows/real-time-benchmark.yml | 2 +- benchmark/benchmark.php | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/real-time-benchmark.yml b/.github/workflows/real-time-benchmark.yml index 9276539841e72..9451bee30a039 100644 --- a/.github/workflows/real-time-benchmark.yml +++ b/.github/workflows/real-time-benchmark.yml @@ -263,7 +263,7 @@ jobs: cp ./php-version-benchmarks/config/test/1_laravel.ini.dist ./php-version-benchmarks/config/test/1_laravel.ini cp ./php-version-benchmarks/config/test/2_symfony_main.ini.dist ./php-version-benchmarks/config/test/2_symfony_main.ini - cp ./php-version-benchmarks/config/test/4_wordpress.ini.dist ./php-version-benchmarks/config/test/4_wordpress.ini + #cp ./php-version-benchmarks/config/test/4_wordpress.ini.dist ./php-version-benchmarks/config/test/4_wordpress.ini cp ./php-version-benchmarks/config/test/5_bench.php.ini.dist ./php-version-benchmarks/config/test/5_bench.php.ini if [ "${{ env.RUN_MICRO_BENCH }}" -eq "1" ]; then diff --git a/benchmark/benchmark.php b/benchmark/benchmark.php index 0c2ac4c6010a4..12a12ff76121f 100644 --- a/benchmark/benchmark.php +++ b/benchmark/benchmark.php @@ -31,8 +31,8 @@ function main() { $data['Zend/bench.php JIT'] = runBench(true); $data['Symfony Demo 2.2.3'] = runSymfonyDemo(false); $data['Symfony Demo 2.2.3 JIT'] = runSymfonyDemo(true); - $data['Wordpress 6.2'] = runWordpress(false); - $data['Wordpress 6.2 JIT'] = runWordpress(true); + // $data['Wordpress 6.2'] = runWordpress(false); + // $data['Wordpress 6.2 JIT'] = runWordpress(true); $result = json_encode($data, JSON_PRETTY_PRINT) . "\n"; fwrite(STDOUT, $result);