diff options
| author | nsfisis <nsfisis@gmail.com> | 2024-05-05 12:27:17 +0900 |
|---|---|---|
| committer | nsfisis <nsfisis@gmail.com> | 2024-05-05 14:12:32 +0900 |
| commit | 27cd7cf8f816f1d1dd465c28a43fc0fcd25c48d6 (patch) | |
| tree | f38f4eee869735a18c6df71058ed8ddc5ccbb635 | |
| parent | 2f533445e47f4a0f7c94677f5fda3683a4f1fee7 (diff) | |
| download | php-waddiwasi-27cd7cf8f816f1d1dd465c28a43fc0fcd25c48d6.tar.gz php-waddiwasi-27cd7cf8f816f1d1dd465c28a43fc0fcd25c48d6.tar.zst php-waddiwasi-27cd7cf8f816f1d1dd465c28a43fc0fcd25c48d6.zip | |
feat: limit call stack size
| -rw-r--r-- | src/Execution/Stack.php | 8 | ||||
| -rw-r--r-- | src/Execution/StackOverflowException.php | 19 | ||||
| -rw-r--r-- | tests/src/SpecTestsuites/Core/CallIndirectTest.php | 2 | ||||
| -rw-r--r-- | tests/src/SpecTestsuites/Core/CallTest.php | 2 | ||||
| -rw-r--r-- | tests/src/SpecTestsuites/Core/FacTest.php | 1 | ||||
| -rw-r--r-- | tests/src/SpecTestsuites/Core/SkipStackGuardPageTest.php | 10 | ||||
| -rw-r--r-- | tests/src/SpecTestsuites/SpecTestsuiteBase.php | 11 | ||||
| -rw-r--r-- | tools/json2phpunit.php | 1 |
8 files changed, 53 insertions, 1 deletions
diff --git a/src/Execution/Stack.php b/src/Execution/Stack.php index 424f8c6..6d2a2aa 100644 --- a/src/Execution/Stack.php +++ b/src/Execution/Stack.php @@ -30,6 +30,9 @@ final class Stack public function pushFrame(Frame $frame): void { + if ($this->getCallStackLimit() <= count($this->frames)) { + throw new StackOverflowException(); + } $this->push($frame); $this->frames[] = $frame; $this->currentFrame = $frame; @@ -179,6 +182,11 @@ final class Stack return $this->currentFrame; } + public function getCallStackLimit(): int + { + return 1024; + } + private function push(int|float|Ref|Frame|Label $entry): void { $this->entries[] = $entry; diff --git a/src/Execution/StackOverflowException.php b/src/Execution/StackOverflowException.php new file mode 100644 index 0000000..92991e2 --- /dev/null +++ b/src/Execution/StackOverflowException.php @@ -0,0 +1,19 @@ +<?php + +declare(strict_types=1); + +namespace Nsfisis\Waddiwasi\Execution; + +use RuntimeException; +use Throwable; + +final class StackOverflowException extends RuntimeException +{ + public function __construct( + string $message = 'Stack overflow', + int $code = 0, + Throwable $previous = null, + ) { + parent::__construct($message, $code, $previous); + } +} diff --git a/tests/src/SpecTestsuites/Core/CallIndirectTest.php b/tests/src/SpecTestsuites/Core/CallIndirectTest.php index c99bd23..6dd311a 100644 --- a/tests/src/SpecTestsuites/Core/CallIndirectTest.php +++ b/tests/src/SpecTestsuites/Core/CallIndirectTest.php @@ -1068,6 +1068,7 @@ final class CallIndirectTest extends SpecTestsuiteBase public function testAssertExhaustion96(): void { $this->runAssertExhaustionCommand( + module: null, action: ['type' => 'invoke', 'field' => 'runaway', 'args' => []], text: 'call stack exhausted', line: 585, @@ -1078,6 +1079,7 @@ final class CallIndirectTest extends SpecTestsuiteBase public function testAssertExhaustion97(): void { $this->runAssertExhaustionCommand( + module: null, action: ['type' => 'invoke', 'field' => 'mutual-runaway', 'args' => []], text: 'call stack exhausted', line: 586, diff --git a/tests/src/SpecTestsuites/Core/CallTest.php b/tests/src/SpecTestsuites/Core/CallTest.php index e60f8bc..c245572 100644 --- a/tests/src/SpecTestsuites/Core/CallTest.php +++ b/tests/src/SpecTestsuites/Core/CallTest.php @@ -474,6 +474,7 @@ final class CallTest extends SpecTestsuiteBase public function testAssertExhaustion42(): void { $this->runAssertExhaustionCommand( + module: null, action: ['type' => 'invoke', 'field' => 'runaway', 'args' => []], text: 'call stack exhausted', line: 337, @@ -484,6 +485,7 @@ final class CallTest extends SpecTestsuiteBase public function testAssertExhaustion43(): void { $this->runAssertExhaustionCommand( + module: null, action: ['type' => 'invoke', 'field' => 'mutual-runaway', 'args' => []], text: 'call stack exhausted', line: 338, diff --git a/tests/src/SpecTestsuites/Core/FacTest.php b/tests/src/SpecTestsuites/Core/FacTest.php index 319bc55..a388d73 100644 --- a/tests/src/SpecTestsuites/Core/FacTest.php +++ b/tests/src/SpecTestsuites/Core/FacTest.php @@ -89,6 +89,7 @@ final class FacTest extends SpecTestsuiteBase public function testAssertExhaustion7(): void { $this->runAssertExhaustionCommand( + module: null, action: ['type' => 'invoke', 'field' => 'fac-rec', 'args' => [['type' => 'i64', 'value' => '1073741824']]], text: 'call stack exhausted', line: 109, diff --git a/tests/src/SpecTestsuites/Core/SkipStackGuardPageTest.php b/tests/src/SpecTestsuites/Core/SkipStackGuardPageTest.php index 246b92c..889a817 100644 --- a/tests/src/SpecTestsuites/Core/SkipStackGuardPageTest.php +++ b/tests/src/SpecTestsuites/Core/SkipStackGuardPageTest.php @@ -23,6 +23,7 @@ final class SkipStackGuardPageTest extends SpecTestsuiteBase public function testAssertExhaustion1(): void { $this->runAssertExhaustionCommand( + module: null, action: ['type' => 'invoke', 'field' => 'test-guard-page-skip', 'args' => [['type' => 'i32', 'value' => '0']]], text: 'call stack exhausted', line: 2275, @@ -33,6 +34,7 @@ final class SkipStackGuardPageTest extends SpecTestsuiteBase public function testAssertExhaustion2(): void { $this->runAssertExhaustionCommand( + module: null, action: ['type' => 'invoke', 'field' => 'test-guard-page-skip', 'args' => [['type' => 'i32', 'value' => '100']]], text: 'call stack exhausted', line: 2276, @@ -43,6 +45,7 @@ final class SkipStackGuardPageTest extends SpecTestsuiteBase public function testAssertExhaustion3(): void { $this->runAssertExhaustionCommand( + module: null, action: ['type' => 'invoke', 'field' => 'test-guard-page-skip', 'args' => [['type' => 'i32', 'value' => '200']]], text: 'call stack exhausted', line: 2277, @@ -53,6 +56,7 @@ final class SkipStackGuardPageTest extends SpecTestsuiteBase public function testAssertExhaustion4(): void { $this->runAssertExhaustionCommand( + module: null, action: ['type' => 'invoke', 'field' => 'test-guard-page-skip', 'args' => [['type' => 'i32', 'value' => '300']]], text: 'call stack exhausted', line: 2278, @@ -63,6 +67,7 @@ final class SkipStackGuardPageTest extends SpecTestsuiteBase public function testAssertExhaustion5(): void { $this->runAssertExhaustionCommand( + module: null, action: ['type' => 'invoke', 'field' => 'test-guard-page-skip', 'args' => [['type' => 'i32', 'value' => '400']]], text: 'call stack exhausted', line: 2279, @@ -73,6 +78,7 @@ final class SkipStackGuardPageTest extends SpecTestsuiteBase public function testAssertExhaustion6(): void { $this->runAssertExhaustionCommand( + module: null, action: ['type' => 'invoke', 'field' => 'test-guard-page-skip', 'args' => [['type' => 'i32', 'value' => '500']]], text: 'call stack exhausted', line: 2280, @@ -83,6 +89,7 @@ final class SkipStackGuardPageTest extends SpecTestsuiteBase public function testAssertExhaustion7(): void { $this->runAssertExhaustionCommand( + module: null, action: ['type' => 'invoke', 'field' => 'test-guard-page-skip', 'args' => [['type' => 'i32', 'value' => '600']]], text: 'call stack exhausted', line: 2281, @@ -93,6 +100,7 @@ final class SkipStackGuardPageTest extends SpecTestsuiteBase public function testAssertExhaustion8(): void { $this->runAssertExhaustionCommand( + module: null, action: ['type' => 'invoke', 'field' => 'test-guard-page-skip', 'args' => [['type' => 'i32', 'value' => '700']]], text: 'call stack exhausted', line: 2282, @@ -103,6 +111,7 @@ final class SkipStackGuardPageTest extends SpecTestsuiteBase public function testAssertExhaustion9(): void { $this->runAssertExhaustionCommand( + module: null, action: ['type' => 'invoke', 'field' => 'test-guard-page-skip', 'args' => [['type' => 'i32', 'value' => '800']]], text: 'call stack exhausted', line: 2283, @@ -113,6 +122,7 @@ final class SkipStackGuardPageTest extends SpecTestsuiteBase public function testAssertExhaustion10(): void { $this->runAssertExhaustionCommand( + module: null, action: ['type' => 'invoke', 'field' => 'test-guard-page-skip', 'args' => [['type' => 'i32', 'value' => '900']]], text: 'call stack exhausted', line: 2284, diff --git a/tests/src/SpecTestsuites/SpecTestsuiteBase.php b/tests/src/SpecTestsuites/SpecTestsuiteBase.php index cd5da89..eca3b5c 100644 --- a/tests/src/SpecTestsuites/SpecTestsuiteBase.php +++ b/tests/src/SpecTestsuites/SpecTestsuiteBase.php @@ -9,6 +9,7 @@ use Nsfisis\Waddiwasi\BinaryFormat\InvalidBinaryFormatException; use Nsfisis\Waddiwasi\Execution\Ref; use Nsfisis\Waddiwasi\Execution\Refs\RefExtern; use Nsfisis\Waddiwasi\Execution\Runtime; +use Nsfisis\Waddiwasi\Execution\StackOverflowException; use Nsfisis\Waddiwasi\Execution\Store; use Nsfisis\Waddiwasi\Execution\TrapException; use Nsfisis\Waddiwasi\Execution\TrapKind; @@ -95,11 +96,19 @@ abstract class SpecTestsuiteBase extends TestCase } protected function runAssertExhaustionCommand( + ?string $module, array $action, string $text, int $line, ): void { - $this->assertTrue(false, "assert_exhaustion"); + $exception = null; + try { + $this->doAction($module, $action); + } catch (StackOverflowException $e) { + $exception = $e; + } + $this->assertNotNull($exception, "at $line"); + // @todo Check $text? } protected function runAssertUninstantiableCommand( diff --git a/tools/json2phpunit.php b/tools/json2phpunit.php index f2078e4..025c613 100644 --- a/tools/json2phpunit.php +++ b/tools/json2phpunit.php @@ -174,6 +174,7 @@ function buildAssertExhaustionCommandTest(array $command): array return [ 'method' => 'runAssertExhaustionCommand', 'args' => [ + 'module' => $command['module'] ?? null, 'action' => $command['action'], 'text' => $command['text'], ], |
