aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authornsfisis <nsfisis@gmail.com>2024-05-05 12:27:17 +0900
committernsfisis <nsfisis@gmail.com>2024-05-05 14:12:32 +0900
commit27cd7cf8f816f1d1dd465c28a43fc0fcd25c48d6 (patch)
treef38f4eee869735a18c6df71058ed8ddc5ccbb635
parent2f533445e47f4a0f7c94677f5fda3683a4f1fee7 (diff)
downloadphp-waddiwasi-27cd7cf8f816f1d1dd465c28a43fc0fcd25c48d6.tar.gz
php-waddiwasi-27cd7cf8f816f1d1dd465c28a43fc0fcd25c48d6.tar.zst
php-waddiwasi-27cd7cf8f816f1d1dd465c28a43fc0fcd25c48d6.zip
feat: limit call stack size
-rw-r--r--src/Execution/Stack.php8
-rw-r--r--src/Execution/StackOverflowException.php19
-rw-r--r--tests/src/SpecTestsuites/Core/CallIndirectTest.php2
-rw-r--r--tests/src/SpecTestsuites/Core/CallTest.php2
-rw-r--r--tests/src/SpecTestsuites/Core/FacTest.php1
-rw-r--r--tests/src/SpecTestsuites/Core/SkipStackGuardPageTest.php10
-rw-r--r--tests/src/SpecTestsuites/SpecTestsuiteBase.php11
-rw-r--r--tools/json2phpunit.php1
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'],
],