From 0a509a04f7dbb3186e83ad697b9ebb28df5f0bca Mon Sep 17 00:00:00 2001 From: yavon007 Date: Sat, 12 Sep 2026 14:56:17 +0800 Subject: [PATCH 1/3] fix(compiler): resolve function imports before dispatch and policy checks --- phpunit/code/function-import-policy.php | 3 ++ phpunit/code/function-import-resolution.php | 14 ++++++++++ phpunit/src/FunctionImportResolutionTest.php | 22 +++++++++++++++ phpunit/src/NanoCapabilityPolicyTest.php | 28 +++++++++++++++++++ .../namespace/function-import-resolution.phpt | 19 +++++++++++++ 5 files changed, 86 insertions(+) create mode 100644 phpunit/code/function-import-policy.php create mode 100644 phpunit/code/function-import-resolution.php create mode 100644 phpunit/src/FunctionImportResolutionTest.php create mode 100644 tests/compiler/namespace/function-import-resolution.phpt diff --git a/phpunit/code/function-import-policy.php b/phpunit/code/function-import-policy.php new file mode 100644 index 00000000..7fd09b24 --- /dev/null +++ b/phpunit/code/function-import-policy.php @@ -0,0 +1,3 @@ +addFiles([$source]); + $compiler->prepareFile($source); + $code = file_get_contents($compiler->convertFile($source)); + preg_match('/void php_aliasconsumer__exercise\(\) \{(.*?)\n\}/s', $code, $match); + self::assertCount(2, $match); + self::assertSame(5, substr_count($match[1], 'php_aliaslibrary__route(')); + self::assertSame(1, substr_count($match[1], 'php_route(')); + self::assertStringNotContainsString('php::call(', $match[1]); + } +} diff --git a/phpunit/src/NanoCapabilityPolicyTest.php b/phpunit/src/NanoCapabilityPolicyTest.php index 3659c5d2..7ac4ca4f 100644 --- a/phpunit/src/NanoCapabilityPolicyTest.php +++ b/phpunit/src/NanoCapabilityPolicyTest.php @@ -49,6 +49,34 @@ public function forgetBuildTimeFunction(string $name): void final class NanoCapabilityPolicyTest extends BaseTest { + public function testFunctionImportCannotBypassNanoPolicy(): void + { + $this->assertImportedFunctionRejected(false); + } + + public function testFunctionImportCannotBypassWasiPolicy(): void + { + $this->assertImportedFunctionRejected(true); + } + + private function assertImportedFunctionRejected(bool $wasi): void + { + global $translator; + $compiler = new NanoCapabilityPolicyCompiler(TYPEPHP_ROOT_PATH); + if ($wasi) { + $compiler->enableWasiForTest(); + } else { + $compiler->enableNanoForTest(); + } + $translator = $compiler; + $source = __DIR__ . '/../code/function-import-policy.php'; + $compiler->addFiles([$source]); + $compiler->prepareFile($source); + $this->expectException(TestError::class); + $this->expectExceptionMessage('Function `exec` is not supported'); + $compiler->convertFile($source); + } + public function testRejectsForbiddenDirectCallMissingFromBuildTimePhp(): void { global $translator; diff --git a/tests/compiler/namespace/function-import-resolution.phpt b/tests/compiler/namespace/function-import-resolution.phpt new file mode 100644 index 00000000..72c46596 --- /dev/null +++ b/tests/compiler/namespace/function-import-resolution.phpt @@ -0,0 +1,19 @@ +--TEST-- +Function imports are case-insensitive and take precedence over global functions +--FILE-- + Date: Sat, 12 Sep 2026 15:01:28 +0800 Subject: [PATCH 2/3] test: close PHP section in function import PHPT --- tests/compiler/namespace/function-import-resolution.phpt | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/compiler/namespace/function-import-resolution.phpt b/tests/compiler/namespace/function-import-resolution.phpt index 72c46596..1b5f3bc9 100644 --- a/tests/compiler/namespace/function-import-resolution.phpt +++ b/tests/compiler/namespace/function-import-resolution.phpt @@ -15,5 +15,6 @@ namespace AliasConsumer { } } namespace { function main(): void { \AliasConsumer\exercise(); } } +?> --EXPECT-- import:import:import:3:import:import:global From ee4c77cc1fa338cd0970f67c108070d1d61bc91b Mon Sep 17 00:00:00 2001 From: yavon007 Date: Mon, 14 Sep 2026 14:39:00 +0800 Subject: [PATCH 3/3] fix(compiler): resolve first-class function aliases --- phpunit/code/function-import-resolution.php | 17 +++++++++++++++-- phpunit/src/FunctionImportResolutionTest.php | 12 +++++++++++- .../namespace/function-import-resolution.phpt | 18 ++++++++++++++++-- 3 files changed, 42 insertions(+), 5 deletions(-) diff --git a/phpunit/code/function-import-resolution.php b/phpunit/code/function-import-resolution.php index a344cc2c..96e4ce44 100644 --- a/phpunit/code/function-import-resolution.php +++ b/phpunit/code/function-import-resolution.php @@ -1,14 +1,27 @@ getValue($compiler); + self::assertArrayHasKey('strlen', $literalStrings); + self::assertArrayHasKey('AliasLibrary\\callback_target', $literalStrings); + self::assertArrayNotHasKey('sIzE', $literalStrings); + self::assertArrayNotHasKey('cAlLbAcK_tArGeT', $literalStrings); } } diff --git a/tests/compiler/namespace/function-import-resolution.phpt b/tests/compiler/namespace/function-import-resolution.phpt index 1b5f3bc9..10b7d76e 100644 --- a/tests/compiler/namespace/function-import-resolution.phpt +++ b/tests/compiler/namespace/function-import-resolution.phpt @@ -2,19 +2,33 @@ Function imports are case-insensitive and take precedence over global functions --FILE-- --EXPECT-- import:import:import:3:import:import:global +4:import-callback:import:3