diff options
| author | nsfisis <nsfisis@gmail.com> | 2024-05-18 14:28:46 +0900 |
|---|---|---|
| committer | nsfisis <nsfisis@gmail.com> | 2024-05-18 14:28:46 +0900 |
| commit | 829f6e531525fa82c5fa948e6bb96bb6469685a2 (patch) | |
| tree | 2e1456e441910eb363c74dc0c81555070f883fbb | |
| parent | b5455751929d7f9a3581e27eb0adcf7ef9d01a0c (diff) | |
| download | php-waddiwasi-829f6e531525fa82c5fa948e6bb96bb6469685a2.tar.gz php-waddiwasi-829f6e531525fa82c5fa948e6bb96bb6469685a2.tar.zst php-waddiwasi-829f6e531525fa82c5fa948e6bb96bb6469685a2.zip | |
fix: memory address should be treated as unsigned integer
| -rw-r--r-- | src/Execution/Runtime.php | 42 | ||||
| -rw-r--r-- | tests/src/SpecTestsuites/SpecTestsuiteBase.php | 72 |
2 files changed, 40 insertions, 74 deletions
diff --git a/src/Execution/Runtime.php b/src/Execution/Runtime.php index 90d05e6..bf010c9 100644 --- a/src/Execution/Runtime.php +++ b/src/Execution/Runtime.php @@ -1955,7 +1955,7 @@ final class Runtime $f = $this->stack->currentFrame(); $a = $f->module->memAddrs[0]; $mem = $this->store->mems[$a]; - $i = $this->stack->popInt(); + $i = self::wasmI32ToPhpInt($this->stack->popInt()); $ea = $i + $offset; $c = $mem->loadI32_s32($ea); if ($c === null) { @@ -1970,7 +1970,7 @@ final class Runtime $f = $this->stack->currentFrame(); $a = $f->module->memAddrs[0]; $mem = $this->store->mems[$a]; - $i = $this->stack->popInt(); + $i = self::wasmI32ToPhpInt($this->stack->popInt()); $ea = $i + $offset; $c = $mem->loadI32_s16($ea); if ($c === null) { @@ -1985,7 +1985,7 @@ final class Runtime $f = $this->stack->currentFrame(); $a = $f->module->memAddrs[0]; $mem = $this->store->mems[$a]; - $i = $this->stack->popInt(); + $i = self::wasmI32ToPhpInt($this->stack->popInt()); $ea = $i + $offset; $c = $mem->loadI32_u16($ea); if ($c === null) { @@ -2000,7 +2000,7 @@ final class Runtime $f = $this->stack->currentFrame(); $a = $f->module->memAddrs[0]; $mem = $this->store->mems[$a]; - $i = $this->stack->popInt(); + $i = self::wasmI32ToPhpInt($this->stack->popInt()); $ea = $i + $offset; $c = $mem->loadI32_s8($ea); if ($c === null) { @@ -2015,7 +2015,7 @@ final class Runtime $f = $this->stack->currentFrame(); $a = $f->module->memAddrs[0]; $mem = $this->store->mems[$a]; - $i = $this->stack->popInt(); + $i = self::wasmI32ToPhpInt($this->stack->popInt()); $ea = $i + $offset; $c = $mem->loadI32_u8($ea); if ($c === null) { @@ -2031,7 +2031,7 @@ final class Runtime $a = $f->module->memAddrs[0]; $mem = $this->store->mems[$a]; $c = $this->stack->popInt(); - $i = $this->stack->popInt(); + $i = self::wasmI32ToPhpInt($this->stack->popInt()); $ea = $i + $offset; $ok = $mem->storeI32_s32($ea, $c); if (!$ok) { @@ -2046,7 +2046,7 @@ final class Runtime $a = $f->module->memAddrs[0]; $mem = $this->store->mems[$a]; $c = $this->stack->popInt(); - $i = $this->stack->popInt(); + $i = self::wasmI32ToPhpInt($this->stack->popInt()); $ea = $i + $offset; $ok = $mem->storeI32_s16($ea, $c); if (!$ok) { @@ -2061,7 +2061,7 @@ final class Runtime $a = $f->module->memAddrs[0]; $mem = $this->store->mems[$a]; $c = $this->stack->popInt(); - $i = $this->stack->popInt(); + $i = self::wasmI32ToPhpInt($this->stack->popInt()); $ea = $i + $offset; $ok = $mem->storeI32_s8($ea, $c); if (!$ok) { @@ -2075,7 +2075,7 @@ final class Runtime $f = $this->stack->currentFrame(); $a = $f->module->memAddrs[0]; $mem = $this->store->mems[$a]; - $i = $this->stack->popInt(); + $i = self::wasmI32ToPhpInt($this->stack->popInt()); $ea = $i + $offset; $c = $mem->loadI64_s64($ea); if ($c === null) { @@ -2090,7 +2090,7 @@ final class Runtime $f = $this->stack->currentFrame(); $a = $f->module->memAddrs[0]; $mem = $this->store->mems[$a]; - $i = $this->stack->popInt(); + $i = self::wasmI32ToPhpInt($this->stack->popInt()); $ea = $i + $offset; $c = $mem->loadI64_s16($ea); if ($c === null) { @@ -2105,7 +2105,7 @@ final class Runtime $f = $this->stack->currentFrame(); $a = $f->module->memAddrs[0]; $mem = $this->store->mems[$a]; - $i = $this->stack->popInt(); + $i = self::wasmI32ToPhpInt($this->stack->popInt()); $ea = $i + $offset; $c = $mem->loadI64_u16($ea); if ($c === null) { @@ -2120,7 +2120,7 @@ final class Runtime $f = $this->stack->currentFrame(); $a = $f->module->memAddrs[0]; $mem = $this->store->mems[$a]; - $i = $this->stack->popInt(); + $i = self::wasmI32ToPhpInt($this->stack->popInt()); $ea = $i + $offset; $c = $mem->loadI64_s32($ea); if ($c === null) { @@ -2135,7 +2135,7 @@ final class Runtime $f = $this->stack->currentFrame(); $a = $f->module->memAddrs[0]; $mem = $this->store->mems[$a]; - $i = $this->stack->popInt(); + $i = self::wasmI32ToPhpInt($this->stack->popInt()); $ea = $i + $offset; $c = $mem->loadI64_u32($ea); if ($c === null) { @@ -2150,7 +2150,7 @@ final class Runtime $f = $this->stack->currentFrame(); $a = $f->module->memAddrs[0]; $mem = $this->store->mems[$a]; - $i = $this->stack->popInt(); + $i = self::wasmI32ToPhpInt($this->stack->popInt()); $ea = $i + $offset; $c = $mem->loadI64_s8($ea); if ($c === null) { @@ -2165,7 +2165,7 @@ final class Runtime $f = $this->stack->currentFrame(); $a = $f->module->memAddrs[0]; $mem = $this->store->mems[$a]; - $i = $this->stack->popInt(); + $i = self::wasmI32ToPhpInt($this->stack->popInt()); $ea = $i + $offset; $c = $mem->loadI64_u8($ea); if ($c === null) { @@ -2181,7 +2181,7 @@ final class Runtime $a = $f->module->memAddrs[0]; $mem = $this->store->mems[$a]; $c = $this->stack->popInt(); - $i = $this->stack->popInt(); + $i = self::wasmI32ToPhpInt($this->stack->popInt()); $ea = $i + $offset; $ok = $mem->storeI64_s64($ea, $c); if (!$ok) { @@ -2196,7 +2196,7 @@ final class Runtime $a = $f->module->memAddrs[0]; $mem = $this->store->mems[$a]; $c = $this->stack->popInt(); - $i = $this->stack->popInt(); + $i = self::wasmI32ToPhpInt($this->stack->popInt()); $ea = $i + $offset; $ok = $mem->storeI64_s16($ea, $c); if (!$ok) { @@ -2211,7 +2211,7 @@ final class Runtime $a = $f->module->memAddrs[0]; $mem = $this->store->mems[$a]; $c = $this->stack->popInt(); - $i = $this->stack->popInt(); + $i = self::wasmI32ToPhpInt($this->stack->popInt()); $ea = $i + $offset; $ok = $mem->storeI64_s32($ea, $c); if (!$ok) { @@ -2226,7 +2226,7 @@ final class Runtime $a = $f->module->memAddrs[0]; $mem = $this->store->mems[$a]; $c = $this->stack->popInt(); - $i = $this->stack->popInt(); + $i = self::wasmI32ToPhpInt($this->stack->popInt()); $ea = $i + $offset; $ok = $mem->storeI64_s8($ea, $c); if (!$ok) { @@ -2457,7 +2457,7 @@ final class Runtime $f = $this->stack->currentFrame(); $a = $f->module->memAddrs[0]; $mem = $this->store->mems[$a]; - $i = $this->stack->popInt(); + $i = self::wasmI32ToPhpInt($this->stack->popInt()); $ea = $i + $offset; $c = $mem->loadF32($ea); if ($c === null) { @@ -2471,7 +2471,7 @@ final class Runtime $f = $this->stack->currentFrame(); $a = $f->module->memAddrs[0]; $mem = $this->store->mems[$a]; - $i = $this->stack->popInt(); + $i = self::wasmI32ToPhpInt($this->stack->popInt()); $ea = $i + $offset; $c = $mem->loadF64($ea); if ($c === null) { diff --git a/tests/src/SpecTestsuites/SpecTestsuiteBase.php b/tests/src/SpecTestsuites/SpecTestsuiteBase.php index 9939196..0fc7e2e 100644 --- a/tests/src/SpecTestsuites/SpecTestsuiteBase.php +++ b/tests/src/SpecTestsuites/SpecTestsuiteBase.php @@ -147,17 +147,17 @@ abstract class SpecTestsuiteBase extends TestCase /** * @param array{type: string, value: string} $arg */ - private function toWasmArg(array $arg): int|float|Ref + private static function wastValueToInternalValue(array $arg): int|float|RefExtern { $type = $arg['type']; $value = $arg['value']; return match ($type) { - 'i32' => (int)$value, - 'i64' => (int)$value, + 'i32' => unpack('l', pack('l', (int)$value))[1], + 'i64' => unpack('q', self::convertInt64ToBinary($value))[1], 'f32' => unpack('g', pack('l', (int)$value))[1], - 'f64' => unpack('e', pack('q', (int)$value))[1], + 'f64' => unpack('e', self::convertInt64ToBinary($value))[1], 'externref' => Ref::RefExtern((int)$value), - default => $this->assertTrue(false, "unknown arg type: $type"), + default => throw new \RuntimeException("unknown type: $type"), }; } @@ -174,7 +174,7 @@ abstract class SpecTestsuiteBase extends TestCase $runtime = self::$runtimes[$targetModuleName]; return $runtime->invoke( $actionField, - array_map($this->toWasmArg(...), $actionArgs), + array_map(self::wastValueToInternalValue(...), $actionArgs), ); } else { $this->assertTrue(false, "unknown action: $actionType"); @@ -201,65 +201,31 @@ abstract class SpecTestsuiteBase extends TestCase for ($i = 0; $i < count($expectedResults); $i++) { $expectedResult = $expectedResults[$i]; + $expectedValue = self::wastValueToInternalValue($expectedResult); $actualResult = $actualResults[$i]; - if ($expectedResult['type'] === 'i32') { - $expectedValue = unpack('l', pack('l', (int)$expectedResult['value']))[1]; - $this->assertSame( - $expectedValue, - $actualResult, - "result $i mismatch" . $message, + if (is_float($expectedValue) && is_nan($expectedValue)) { + // @todo check NaN bit pattern. + $this->assertTrue( + is_nan($actualResult), + "result $i is not NaN" . $message, ); - } elseif ($expectedResult['type'] === 'i64') { - $expectedValue = unpack('q', self::convertInt64ToBinary($expectedResult['value']))[1]; - $this->assertSame( - $expectedValue, - $actualResult, - "result $i mismatch" . $message, - ); - } elseif ($expectedResult['type'] === 'f32') { - $expectedValue = unpack('g', pack('l', (int)$expectedResult['value']))[1]; - if (is_nan($expectedValue)) { - // @todo check NaN bit pattern. - $this->assertTrue( - is_nan($actualResult), - "result $i is not NaN" . $message, - ); - } else { - $this->assertSame( - $expectedValue, - $actualResult, - "result $i mismatch" . $message, - ); - } - } elseif ($expectedResult['type'] === 'f64') { - $expectedValue = unpack('e', self::convertInt64ToBinary($expectedResult['value']))[1]; - if (is_nan($expectedValue)) { - // @todo check NaN bit pattern. - $this->assertTrue( - is_nan($actualResult), - "result $i is not NaN" . $message, - ); - } else { - $this->assertSame( - $expectedValue, - $actualResult, - "result $i mismatch" . $message, - ); - } - } elseif ($expectedResult['type'] === 'externref') { - $expectedValue = (int)$expectedResult['value']; + } else if ($expectedValue instanceof RefExtern) { $this->assertInstanceOf( RefExtern::class, $actualResult, "result $i is not an externref" . $message, ); $this->assertSame( - $expectedValue, + $expectedValue->addr, $actualResult->addr, "result $i mismatch" . $message, ); } else { - $this->assertTrue(false, "unknown result type: {$expectedResult['type']}"); + $this->assertSame( + $expectedValue, + $actualResult, + "result $i mismatch" . $message, + ); } } } |
