wasm_interp: don't panic when unwrapping Value

This commit is contained in:
Brian Carroll 2022-12-06 20:19:25 +00:00
parent d49ae6701a
commit 9d912a6cc7
No known key found for this signature in database
GPG key ID: 5C7B2EC4101703C0
5 changed files with 49 additions and 39 deletions

View file

@ -712,55 +712,55 @@ impl<'a, I: ImportDispatcher> Instance<'a, I> {
} }
I32STORE => { I32STORE => {
let (addr, value) = self.get_store_addr_value(module)?; let (addr, value) = self.get_store_addr_value(module)?;
let unwrapped = value.unwrap_i32(); let unwrapped = value.expect_i32().map_err(Error::from)?;
let target = &mut self.memory[addr..][..4]; let target = &mut self.memory[addr..][..4];
target.copy_from_slice(&unwrapped.to_le_bytes()); target.copy_from_slice(&unwrapped.to_le_bytes());
} }
I64STORE => { I64STORE => {
let (addr, value) = self.get_store_addr_value(module)?; let (addr, value) = self.get_store_addr_value(module)?;
let unwrapped = value.unwrap_i64(); let unwrapped = value.expect_i64().map_err(Error::from)?;
let target = &mut self.memory[addr..][..8]; let target = &mut self.memory[addr..][..8];
target.copy_from_slice(&unwrapped.to_le_bytes()); target.copy_from_slice(&unwrapped.to_le_bytes());
} }
F32STORE => { F32STORE => {
let (addr, value) = self.get_store_addr_value(module)?; let (addr, value) = self.get_store_addr_value(module)?;
let unwrapped = value.unwrap_f32(); let unwrapped = value.expect_f32().map_err(Error::from)?;
let target = &mut self.memory[addr..][..4]; let target = &mut self.memory[addr..][..4];
target.copy_from_slice(&unwrapped.to_le_bytes()); target.copy_from_slice(&unwrapped.to_le_bytes());
} }
F64STORE => { F64STORE => {
let (addr, value) = self.get_store_addr_value(module)?; let (addr, value) = self.get_store_addr_value(module)?;
let unwrapped = value.unwrap_f64(); let unwrapped = value.expect_f64().map_err(Error::from)?;
let target = &mut self.memory[addr..][..8]; let target = &mut self.memory[addr..][..8];
target.copy_from_slice(&unwrapped.to_le_bytes()); target.copy_from_slice(&unwrapped.to_le_bytes());
} }
I32STORE8 => { I32STORE8 => {
let (addr, value) = self.get_store_addr_value(module)?; let (addr, value) = self.get_store_addr_value(module)?;
let unwrapped = value.unwrap_i32(); let unwrapped = value.expect_i32().map_err(Error::from)?;
let target = &mut self.memory[addr..][..1]; let target = &mut self.memory[addr..][..1];
target.copy_from_slice(&unwrapped.to_le_bytes()[..1]); target.copy_from_slice(&unwrapped.to_le_bytes()[..1]);
} }
I32STORE16 => { I32STORE16 => {
let (addr, value) = self.get_store_addr_value(module)?; let (addr, value) = self.get_store_addr_value(module)?;
let unwrapped = value.unwrap_i32(); let unwrapped = value.expect_i32().map_err(Error::from)?;
let target = &mut self.memory[addr..][..2]; let target = &mut self.memory[addr..][..2];
target.copy_from_slice(&unwrapped.to_le_bytes()[..2]); target.copy_from_slice(&unwrapped.to_le_bytes()[..2]);
} }
I64STORE8 => { I64STORE8 => {
let (addr, value) = self.get_store_addr_value(module)?; let (addr, value) = self.get_store_addr_value(module)?;
let unwrapped = value.unwrap_i64(); let unwrapped = value.expect_i64().map_err(Error::from)?;
let target = &mut self.memory[addr..][..1]; let target = &mut self.memory[addr..][..1];
target.copy_from_slice(&unwrapped.to_le_bytes()[..1]); target.copy_from_slice(&unwrapped.to_le_bytes()[..1]);
} }
I64STORE16 => { I64STORE16 => {
let (addr, value) = self.get_store_addr_value(module)?; let (addr, value) = self.get_store_addr_value(module)?;
let unwrapped = value.unwrap_i64(); let unwrapped = value.expect_i64().map_err(Error::from)?;
let target = &mut self.memory[addr..][..2]; let target = &mut self.memory[addr..][..2];
target.copy_from_slice(&unwrapped.to_le_bytes()[..2]); target.copy_from_slice(&unwrapped.to_le_bytes()[..2]);
} }
I64STORE32 => { I64STORE32 => {
let (addr, value) = self.get_store_addr_value(module)?; let (addr, value) = self.get_store_addr_value(module)?;
let unwrapped = value.unwrap_i64(); let unwrapped = value.expect_i64().map_err(Error::from)?;
let target = &mut self.memory[addr..][..4]; let target = &mut self.memory[addr..][..4];
target.copy_from_slice(&unwrapped.to_le_bytes()[..4]); target.copy_from_slice(&unwrapped.to_le_bytes()[..4]);
} }

View file

@ -68,13 +68,23 @@ pub(crate) enum Error {
impl Error { impl Error {
fn value_stack_type(expected: ValueType, is_float: bool, is_64: bool) -> Self { fn value_stack_type(expected: ValueType, is_float: bool, is_64: bool) -> Self {
let ty = match (is_float, is_64) { let ty = type_from_flags_f_64(is_float, is_64);
Error::ValueStackType(expected, ty)
}
}
impl From<(ValueType, ValueType)> for Error {
fn from((expected, actual): (ValueType, ValueType)) -> Self {
Error::ValueStackType(expected, actual)
}
}
pub(crate) fn type_from_flags_f_64(is_float: bool, is_64: bool) -> ValueType {
match (is_float, is_64) {
(false, false) => ValueType::I32, (false, false) => ValueType::I32,
(false, true) => ValueType::I64, (false, true) => ValueType::I64,
(true, false) => ValueType::F32, (true, false) => ValueType::F32,
(true, true) => ValueType::F64, (true, true) => ValueType::F64,
};
Error::ValueStackType(expected, ty)
} }
} }

View file

@ -472,7 +472,7 @@ impl ImportDispatcher for TestDispatcher {
assert_eq!(module_name, "env"); assert_eq!(module_name, "env");
assert_eq!(function_name, "increment_state"); assert_eq!(function_name, "increment_state");
assert_eq!(arguments.len(), 1); assert_eq!(arguments.len(), 1);
let val = arguments[0].unwrap_i32(); let val = arguments[0].expect_i32().unwrap();
self.internal_state += val; self.internal_state += val;
dbg!(val, self.internal_state); dbg!(val, self.internal_state);
Some(Value::I32(self.internal_state)) Some(Value::I32(self.internal_state))

View file

@ -28,9 +28,9 @@ impl<'a> WasiDispatcher<'a> {
match function_name { match function_name {
"args_get" => { "args_get" => {
// uint8_t ** argv, // uint8_t ** argv,
let mut ptr_ptr_argv = arguments[0].unwrap_i32() as usize; let mut ptr_ptr_argv = arguments[0].expect_i32().unwrap() as usize;
// uint8_t * argv_buf // uint8_t * argv_buf
let mut ptr_argv_buf = arguments[1].unwrap_i32() as usize; let mut ptr_argv_buf = arguments[1].expect_i32().unwrap() as usize;
for arg in self.args { for arg in self.args {
write_u32(memory, ptr_ptr_argv, ptr_argv_buf as u32); write_u32(memory, ptr_ptr_argv, ptr_argv_buf as u32);
@ -47,9 +47,9 @@ impl<'a> WasiDispatcher<'a> {
// (i32, i32) -> i32 // (i32, i32) -> i32
// number of string arguments // number of string arguments
let ptr_argc = arguments[0].unwrap_i32() as usize; let ptr_argc = arguments[0].expect_i32().unwrap() as usize;
// size of string arguments buffer // size of string arguments buffer
let ptr_argv_buf_size = arguments[1].unwrap_i32() as usize; let ptr_argv_buf_size = arguments[1].expect_i32().unwrap() as usize;
let argc = self.args.len() as u32; let argc = self.args.len() as u32;
write_u32(memory, ptr_argc, argc); write_u32(memory, ptr_argc, argc);
@ -61,8 +61,8 @@ impl<'a> WasiDispatcher<'a> {
} }
"environ_get" => todo!("WASI {}({:?})", function_name, arguments), "environ_get" => todo!("WASI {}({:?})", function_name, arguments),
"environ_sizes_get" => todo!("WASI {}({:?})", function_name, arguments), "environ_sizes_get" => todo!("WASI {}({:?})", function_name, arguments),
"clock_res_get" => todo!("WASI {}({:?})", function_name, arguments), "clock_res_get" => success_code,
"clock_time_get" => todo!("WASI {}({:?})", function_name, arguments), "clock_time_get" => success_code,
"fd_advise" => todo!("WASI {}({:?})", function_name, arguments), "fd_advise" => todo!("WASI {}({:?})", function_name, arguments),
"fd_allocate" => todo!("WASI {}({:?})", function_name, arguments), "fd_allocate" => todo!("WASI {}({:?})", function_name, arguments),
"fd_close" => todo!("WASI {}({:?})", function_name, arguments), "fd_close" => todo!("WASI {}({:?})", function_name, arguments),
@ -85,13 +85,13 @@ impl<'a> WasiDispatcher<'a> {
"fd_tell" => todo!("WASI {}({:?})", function_name, arguments), "fd_tell" => todo!("WASI {}({:?})", function_name, arguments),
"fd_write" => { "fd_write" => {
// file descriptor // file descriptor
let fd = arguments[0].unwrap_i32(); let fd = arguments[0].expect_i32().unwrap();
// Array of IO vectors // Array of IO vectors
let ptr_iovs = arguments[1].unwrap_i32() as usize; let ptr_iovs = arguments[1].expect_i32().unwrap() as usize;
// Length of array // Length of array
let iovs_len = arguments[2].unwrap_i32(); let iovs_len = arguments[2].expect_i32().unwrap();
// Out param: number of bytes written // Out param: number of bytes written
let ptr_nwritten = arguments[3].unwrap_i32() as usize; let ptr_nwritten = arguments[3].expect_i32().unwrap() as usize;
let mut write_lock = match fd { let mut write_lock = match fd {
1 => Ok(io::stdout().lock()), 1 => Ok(io::stdout().lock()),
@ -151,7 +151,7 @@ impl<'a> WasiDispatcher<'a> {
"path_unlink_file" => todo!("WASI {}({:?})", function_name, arguments), "path_unlink_file" => todo!("WASI {}({:?})", function_name, arguments),
"poll_oneoff" => todo!("WASI {}({:?})", function_name, arguments), "poll_oneoff" => todo!("WASI {}({:?})", function_name, arguments),
"proc_exit" => { "proc_exit" => {
let exit_code = arguments[0].unwrap_i32(); let exit_code = arguments[0].expect_i32().unwrap();
exit(exit_code); exit(exit_code);
} }
"proc_raise" => todo!("WASI {}({:?})", function_name, arguments), "proc_raise" => todo!("WASI {}({:?})", function_name, arguments),

View file

@ -695,28 +695,28 @@ pub enum Value {
} }
impl Value { impl Value {
pub fn unwrap_i32(&self) -> i32 { pub fn expect_i32(&self) -> Result<i32, (ValueType, ValueType)> {
match self { match self {
Value::I32(x) => *x, Value::I32(x) => Ok(*x),
_ => panic!("Expected I32 but found {:?}", self), _ => Err((ValueType::I32, ValueType::from(*self))),
} }
} }
pub fn unwrap_i64(&self) -> i64 { pub fn expect_i64(&self) -> Result<i64, (ValueType, ValueType)> {
match self { match self {
Value::I64(x) => *x, Value::I64(x) => Ok(*x),
_ => panic!("Expected I64 but found {:?}", self), _ => Err((ValueType::I64, ValueType::from(*self))),
} }
} }
pub fn unwrap_f32(&self) -> f32 { pub fn expect_f32(&self) -> Result<f32, (ValueType, ValueType)> {
match self { match self {
Value::F32(x) => *x, Value::F32(x) => Ok(*x),
_ => panic!("Expected F32 but found {:?}", self), _ => Err((ValueType::F32, ValueType::from(*self))),
} }
} }
pub fn unwrap_f64(&self) -> f64 { pub fn expect_f64(&self) -> Result<f64, (ValueType, ValueType)> {
match self { match self {
Value::F64(x) => *x, Value::F64(x) => Ok(*x),
_ => panic!("Expected F64 but found {:?}", self), _ => Err((ValueType::F64, ValueType::from(*self))),
} }
} }
} }