Skip to content

Commit

Permalink
Add non-exhaustive wasmtime::TrapCode
Browse files Browse the repository at this point in the history
  • Loading branch information
leoyvens committed Oct 23, 2020
1 parent 84cf782 commit 728493e
Showing 1 changed file with 95 additions and 24 deletions.
119 changes: 95 additions & 24 deletions crates/wasmtime/src/trap.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use crate::FrameInfo;
use backtrace::Backtrace;
use std::fmt;
use std::sync::Arc;
use wasmtime_environ::ir::TrapCode;
use wasmtime_environ::ir;

/// A struct representing an aborted instruction execution, with a message
/// indicating the cause.
Expand Down Expand Up @@ -31,32 +31,103 @@ enum TrapReason {

impl fmt::Display for TrapReason {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
use wasmtime_environ::ir::TrapCode::*;
match self {
TrapReason::Message(s) => write!(f, "{}", s),
TrapReason::I32Exit(status) => write!(f, "Exited with i32 exit status {}", status),
TrapReason::Error(e) => write!(f, "{}", e),
TrapReason::InstructionTrap(code) => {
let desc = match code {
StackOverflow => "call stack exhausted",
HeapOutOfBounds => "out of bounds memory access",
HeapMisaligned => "misaligned memory access",
TableOutOfBounds => "undefined element: out of bounds table access",
IndirectCallToNull => "uninitialized element",
BadSignature => "indirect call type mismatch",
IntegerOverflow => "integer overflow",
IntegerDivisionByZero => "integer divide by zero",
BadConversionToInteger => "invalid conversion to integer",
UnreachableCodeReached => "unreachable",
Interrupt => "interrupt",
User(_) => unreachable!(),
};
write!(f, "wasm trap: {}", desc)
}
TrapReason::InstructionTrap(code) => write!(f, "wasm trap: {}", code),
}
}
}

/// A trap code describing the reason for a trap.
///
/// All trap instructions have an explicit trap code.
#[non_exhaustive]
#[derive(Clone, Copy, PartialEq, Eq, Debug, Hash)]
pub enum TrapCode {
/// The current stack space was exhausted.
///
/// On some platforms, a stack overflow may also be indicated by a segmentation fault from the
/// stack guard page.
StackOverflow,

/// A `heap_addr` instruction detected an out-of-bounds error.
///
/// Note that not all out-of-bounds heap accesses are reported this way;
/// some are detected by a segmentation fault on the heap unmapped or
/// offset-guard pages.
HeapOutOfBounds,

/// A wasm atomic operation was presented with a not-naturally-aligned linear-memory address.
HeapMisaligned,

/// A `table_addr` instruction detected an out-of-bounds error.
TableOutOfBounds,

/// Indirect call to a null table entry.
IndirectCallToNull,

/// Signature mismatch on indirect call.
BadSignature,

/// An integer arithmetic operation caused an overflow.
IntegerOverflow,

/// An integer division by zero.
IntegerDivisionByZero,

/// Failed float-to-int conversion.
BadConversionToInteger,

/// Code that was supposed to have been unreachable was reached.
UnreachableCodeReached,

/// Execution has potentially run too long and may be interrupted.
/// This trap is resumable.
Interrupt,
}

impl TrapCode {
/// Panics if `code` is `ir::TrapCode::User`.
fn from_non_user(code: ir::TrapCode) -> Self {
match code {
ir::TrapCode::StackOverflow => TrapCode::StackOverflow,
ir::TrapCode::HeapOutOfBounds => TrapCode::HeapOutOfBounds,
ir::TrapCode::HeapMisaligned => TrapCode::HeapMisaligned,
ir::TrapCode::TableOutOfBounds => TrapCode::TableOutOfBounds,
ir::TrapCode::IndirectCallToNull => TrapCode::IndirectCallToNull,
ir::TrapCode::BadSignature => TrapCode::BadSignature,
ir::TrapCode::IntegerOverflow => TrapCode::IntegerOverflow,
ir::TrapCode::IntegerDivisionByZero => TrapCode::IntegerDivisionByZero,
ir::TrapCode::BadConversionToInteger => TrapCode::BadConversionToInteger,
ir::TrapCode::UnreachableCodeReached => TrapCode::UnreachableCodeReached,
ir::TrapCode::Interrupt => TrapCode::Interrupt,
ir::TrapCode::User(_) => panic!("Called `TrapCode::from_non_user` with user code"),
}
}
}

impl fmt::Display for TrapCode {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
use TrapCode::*;
let desc = match self {
StackOverflow => "call stack exhausted",
HeapOutOfBounds => "out of bounds memory access",
HeapMisaligned => "misaligned memory access",
TableOutOfBounds => "undefined element: out of bounds table access",
IndirectCallToNull => "uninitialized element",
BadSignature => "indirect call type mismatch",
IntegerOverflow => "integer overflow",
IntegerDivisionByZero => "integer divide by zero",
BadConversionToInteger => "invalid conversion to integer",
UnreachableCodeReached => "unreachable",
Interrupt => "interrupt",
};
write!(f, "{}", desc)
}
}

struct TrapInner {
reason: TrapReason,
wasm_trace: Vec<FrameInfo>,
Expand Down Expand Up @@ -104,9 +175,9 @@ impl Trap {
let mut code = info
.lookup_trap_info(pc)
.map(|info| info.trap_code)
.unwrap_or(TrapCode::StackOverflow);
if maybe_interrupted && code == TrapCode::StackOverflow {
code = TrapCode::Interrupt;
.unwrap_or(ir::TrapCode::StackOverflow);
if maybe_interrupted && code == ir::TrapCode::StackOverflow {
code = ir::TrapCode::Interrupt;
}
Trap::new_wasm(&info, Some(pc), code, backtrace)
}
Expand All @@ -124,10 +195,10 @@ impl Trap {
fn new_wasm(
info: &GlobalFrameInfo,
trap_pc: Option<usize>,
code: TrapCode,
code: ir::TrapCode,
backtrace: Backtrace,
) -> Self {
assert!(!matches!(code, TrapCode::User(_)));
let code = TrapCode::from_non_user(code);
Trap::new_with_trace(info, trap_pc, TrapReason::InstructionTrap(code), backtrace)
}

Expand Down

0 comments on commit 728493e

Please sign in to comment.