aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/Execution
diff options
context:
space:
mode:
Diffstat (limited to 'src/Execution')
-rw-r--r--src/Execution/Runtime.php77
-rw-r--r--src/Execution/TrapKind.php1
2 files changed, 76 insertions, 2 deletions
diff --git a/src/Execution/Runtime.php b/src/Execution/Runtime.php
index aad077a..329a5cd 100644
--- a/src/Execution/Runtime.php
+++ b/src/Execution/Runtime.php
@@ -31,6 +31,7 @@ use function fdiv;
use function floor;
use function intdiv;
use function is_array;
+use function is_infinite;
use function is_int;
use function is_nan;
use function max;
@@ -1239,25 +1240,61 @@ final class Runtime
private function execInstrNumericI32TruncF32S(Instrs\Numeric\I32TruncF32S $instr): void
{
$v = $this->stack->popFloat();
+ if (is_nan($v)) {
+ throw new TrapException($instr::opName() . ": invalid conversion", trapKind: TrapKind::InvalidConversionToInteger);
+ }
+ if (is_infinite($v)) {
+ throw new TrapException($instr::opName() . ": overflow", trapKind: TrapKind::IntegerOverflow);
+ }
+ if ($v <= -2147483649.0 || 2147483648.0 <= $v) {
+ throw new TrapException($instr::opName() . ": overflow", trapKind: TrapKind::IntegerOverflow);
+ }
$this->stack->pushValue((int) $v);
}
private function execInstrNumericI32TruncF32U(Instrs\Numeric\I32TruncF32U $instr): void
{
$v = $this->stack->popFloat();
- $this->stack->pushValue((int) $v);
+ if (is_nan($v)) {
+ throw new TrapException($instr::opName() . ": invalid conversion", trapKind: TrapKind::InvalidConversionToInteger);
+ }
+ if (is_infinite($v)) {
+ throw new TrapException($instr::opName() . ": overflow", trapKind: TrapKind::IntegerOverflow);
+ }
+ if ($v <= -1.0 || 4294967296.0 <= $v) {
+ throw new TrapException($instr::opName() . ": overflow", trapKind: TrapKind::IntegerOverflow);
+ }
+ $this->stack->pushValue(self::convertU32ToS32((int) $v));
}
private function execInstrNumericI32TruncF64S(Instrs\Numeric\I32TruncF64S $instr): void
{
$v = $this->stack->popFloat();
+ if (is_nan($v)) {
+ throw new TrapException($instr::opName() . ": invalid conversion", trapKind: TrapKind::InvalidConversionToInteger);
+ }
+ if (is_infinite($v)) {
+ throw new TrapException($instr::opName() . ": overflow", trapKind: TrapKind::IntegerOverflow);
+ }
+ if ($v <= -2147483649.0 || 2147483648.0 <= $v) {
+ throw new TrapException($instr::opName() . ": overflow", trapKind: TrapKind::IntegerOverflow);
+ }
$this->stack->pushValue((int) $v);
}
private function execInstrNumericI32TruncF64U(Instrs\Numeric\I32TruncF64U $instr): void
{
$v = $this->stack->popFloat();
- $this->stack->pushValue((int) $v);
+ if (is_nan($v)) {
+ throw new TrapException($instr::opName() . ": invalid conversion", trapKind: TrapKind::InvalidConversionToInteger);
+ }
+ if (is_infinite($v)) {
+ throw new TrapException($instr::opName() . ": overflow", trapKind: TrapKind::IntegerOverflow);
+ }
+ if ($v <= -1.0 || 4294967296.0 <= $v) {
+ throw new TrapException($instr::opName() . ": overflow", trapKind: TrapKind::IntegerOverflow);
+ }
+ $this->stack->pushValue(self::convertU32ToS32((int) $v));
}
private function execInstrNumericI32TruncSatF32S(Instrs\Numeric\I32TruncSatF32S $instr): void
@@ -1655,24 +1692,60 @@ final class Runtime
private function execInstrNumericI64TruncF32S(Instrs\Numeric\I64TruncF32S $instr): void
{
$v = $this->stack->popFloat();
+ if (is_nan($v)) {
+ throw new TrapException($instr::opName() . ": invalid conversion ($v)", trapKind: TrapKind::InvalidConversionToInteger);
+ }
+ if (is_infinite($v)) {
+ throw new TrapException($instr::opName() . ": overflow ($v)", trapKind: TrapKind::IntegerOverflow);
+ }
+ if ($v <= -9223372036854775809.0 || 9223372036854775808.0 <= $v) {
+ throw new TrapException($instr::opName() . ": overflow ($v)", trapKind: TrapKind::IntegerOverflow);
+ }
$this->stack->pushValue((int) $v);
}
private function execInstrNumericI64TruncF32U(Instrs\Numeric\I64TruncF32U $instr): void
{
$v = $this->stack->popFloat();
+ if (is_nan($v)) {
+ throw new TrapException($instr::opName() . ": invalid conversion", trapKind: TrapKind::InvalidConversionToInteger);
+ }
+ if (is_infinite($v)) {
+ throw new TrapException($instr::opName() . ": overflow", trapKind: TrapKind::IntegerOverflow);
+ }
+ if ($v <= -1.0 || 18446744073709551616.0 <= $v) {
+ throw new TrapException($instr::opName() . ": overflow", trapKind: TrapKind::IntegerOverflow);
+ }
$this->stack->pushValue((int) $v);
}
private function execInstrNumericI64TruncF64S(Instrs\Numeric\I64TruncF64S $instr): void
{
$v = $this->stack->popFloat();
+ if (is_nan($v)) {
+ throw new TrapException($instr::opName() . ": invalid conversion", trapKind: TrapKind::InvalidConversionToInteger);
+ }
+ if (is_infinite($v)) {
+ throw new TrapException($instr::opName() . ": overflow", trapKind: TrapKind::IntegerOverflow);
+ }
+ if ($v <= -9223372036854775809.0 || 9223372036854775808.0 <= $v) {
+ throw new TrapException($instr::opName() . ": overflow", trapKind: TrapKind::IntegerOverflow);
+ }
$this->stack->pushValue((int) $v);
}
private function execInstrNumericI64TruncF64U(Instrs\Numeric\I64TruncF64U $instr): void
{
$v = $this->stack->popFloat();
+ if (is_nan($v)) {
+ throw new TrapException($instr::opName() . ": invalid conversion", trapKind: TrapKind::InvalidConversionToInteger);
+ }
+ if (is_infinite($v)) {
+ throw new TrapException($instr::opName() . ": overflow", trapKind: TrapKind::IntegerOverflow);
+ }
+ if ($v <= -1.0 || 18446744073709551616.0 <= $v) {
+ throw new TrapException($instr::opName() . ": overflow", trapKind: TrapKind::IntegerOverflow);
+ }
$this->stack->pushValue((int) $v);
}
diff --git a/src/Execution/TrapKind.php b/src/Execution/TrapKind.php
index e6f15b8..a92b973 100644
--- a/src/Execution/TrapKind.php
+++ b/src/Execution/TrapKind.php
@@ -15,4 +15,5 @@ enum TrapKind
case UndefinedElement;
case DivideByZero;
case IntegerOverflow;
+ case InvalidConversionToInteger;
}