diff --git a/Cargo.toml b/Cargo.toml index be5cb0fd91..0121123b95 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -22,7 +22,7 @@ wat = "1.0.83" name = "wasm-interpreter" version = "0.2.0" edition = "2021" -rust-version = "1.81.0" # Keep this in sync with the requirements! +rust-version = "1.87.0" # Keep this in sync with the requirements! description = """ A WASM interpreter tailored for safety use-cases, such as automotive and avionics applications """ diff --git a/crates/benchmark/Cargo.toml b/crates/benchmark/Cargo.toml index 5a4384d675..6b39669ee9 100644 --- a/crates/benchmark/Cargo.toml +++ b/crates/benchmark/Cargo.toml @@ -2,7 +2,7 @@ name = "benchmark" version = "0.1.0" edition = "2021" -rust-version = "1.81.0" +rust-version = "1.87.0" [dev-dependencies] criterion = { version = "0.5.1", default-features = false, features = [ diff --git a/crates/log_wrapper/Cargo.toml b/crates/log_wrapper/Cargo.toml index a37ee19853..15f85fa148 100644 --- a/crates/log_wrapper/Cargo.toml +++ b/crates/log_wrapper/Cargo.toml @@ -2,7 +2,7 @@ name = "log_wrapper" version = "0.1.0" edition = "2021" -rust-version = "1.81.0" # Keep this in sync with the requirements! +rust-version = "1.87.0" # Keep this in sync with the requirements! description = """ A WASM interpreter tailored for safety use-cases, such as automotive and avionics applications """ diff --git a/requirements/requirements.sdoc b/requirements/requirements.sdoc index 7715946535..45181c93b2 100644 --- a/requirements/requirements.sdoc +++ b/requirements/requirements.sdoc @@ -172,7 +172,7 @@ RELATIONS: UID: REQ-17 TITLE: Minimum Supported Rust Version (MSRV) STATEMENT: >>> -The interpreter shall compile on Rust ``1.81.0`` and later versions +The interpreter shall compile on Rust ``1.87.0`` and later versions <<< RATIONALE: >>> An MSRV should be clearly stated to specify which toolchain is acceptable. diff --git a/src/core/reader/section_header.rs b/src/core/reader/section_header.rs index abf5f2a4d1..06820a585e 100644 --- a/src/core/reader/section_header.rs +++ b/src/core/reader/section_header.rs @@ -1,5 +1,6 @@ use crate::core::reader::span::Span; use crate::core::reader::WasmReader; +use crate::core::utils::ToUsizeExt; use crate::ValidationError; #[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)] @@ -53,7 +54,7 @@ impl SectionHeader { pub fn read(wasm: &mut WasmReader) -> Result { let ty = SectionTy::read(wasm)?; let size: u32 = wasm.read_var_u32()?; - let contents_span = wasm.make_span(size as usize)?; + let contents_span = wasm.make_span(size.into_usize())?; Ok(SectionHeader { ty, diff --git a/src/core/reader/types/element.rs b/src/core/reader/types/element.rs index 162943063b..0708e1aa98 100644 --- a/src/core/reader/types/element.rs +++ b/src/core/reader/types/element.rs @@ -1,9 +1,10 @@ use super::global::GlobalType; use super::RefType; -use crate::core::indices::{FuncIdx, TableIdx}; +use crate::core::indices::FuncIdx; use crate::core::reader::span::Span; use crate::core::reader::types::TableType; use crate::core::reader::WasmReader; +use crate::core::utils::ToUsizeExt; use crate::read_constant_expression::read_constant_expression; use crate::validation_stack::ValidationStack; use crate::{NumType, ValType, ValidationError}; @@ -230,8 +231,8 @@ impl ElemType { // start validating elemmode of form active {table x, offset expr} // 1-2. C.tables[x] must be defined with type: limits t let table_type = tables - .get(x as usize) - .ok_or(ValidationError::InvalidTableIdx(x as TableIdx))? + .get(x.into_usize()) + .ok_or(ValidationError::InvalidTableIdx(x.into_usize()))? .et; if table_type != t { return Err(ValidationError::ActiveElementSegmentTypeMismatch); @@ -325,11 +326,11 @@ fn parse_validate_shortened_initializer_list( ) -> Result { wasm.read_vec(|w| { let func_idx = w.read_var_u32()?; - if num_funcs <= func_idx as usize { + if num_funcs <= func_idx.into_usize() { // TODO fix error - return Err(ValidationError::InvalidFuncIdx(func_idx as usize)); + return Err(ValidationError::InvalidFuncIdx(func_idx.into_usize())); } - validation_context_refs.insert(func_idx as FuncIdx); + validation_context_refs.insert(func_idx.into_usize()); Ok(func_idx) }) .map(ElemItems::RefFuncs) diff --git a/src/core/reader/types/export.rs b/src/core/reader/types/export.rs index 72ba045c62..8a111fc47d 100644 --- a/src/core/reader/types/export.rs +++ b/src/core/reader/types/export.rs @@ -1,6 +1,7 @@ use crate::core::indices::{FuncIdx, GlobalIdx, MemIdx, TableIdx}; use crate::core::reader::types::import::ImportDesc; use crate::core::reader::WasmReader; +use crate::core::utils::ToUsizeExt; use crate::{ValidationError, ValidationInfo}; use super::ExternType; @@ -120,7 +121,7 @@ impl ExportDesc { impl ExportDesc { pub fn read(wasm: &mut WasmReader) -> Result { let desc_id = wasm.read_u8()?; - let desc_idx = wasm.read_var_u32()? as usize; + let desc_idx = wasm.read_var_u32()?.into_usize(); let desc = match desc_id { 0x00 => ExportDesc::Func(desc_idx), diff --git a/src/core/reader/types/import.rs b/src/core/reader/types/import.rs index 329bfb3ff8..120828603f 100644 --- a/src/core/reader/types/import.rs +++ b/src/core/reader/types/import.rs @@ -1,5 +1,6 @@ use crate::core::indices::TypeIdx; use crate::core::reader::WasmReader; +use crate::core::utils::ToUsizeExt; use crate::{ValidationError, ValidationInfo}; use super::global::GlobalType; @@ -37,7 +38,7 @@ pub enum ImportDesc { impl ImportDesc { pub fn read(wasm: &mut WasmReader) -> Result { let desc = match wasm.read_u8()? { - 0x00 => Self::Func(wasm.read_var_u32()? as TypeIdx), + 0x00 => Self::Func(wasm.read_var_u32()?.into_usize()), // https://webassembly.github.io/spec/core/binary/types.html#table-types 0x01 => Self::Table(TableType::read(wasm)?), 0x02 => Self::Mem(MemType::read(wasm)?), diff --git a/src/core/reader/types/mod.rs b/src/core/reader/types/mod.rs index 73761f3cbe..4e33be8467 100644 --- a/src/core/reader/types/mod.rs +++ b/src/core/reader/types/mod.rs @@ -6,8 +6,8 @@ use alloc::vec::Vec; use core::fmt::{Debug, Formatter}; use global::GlobalType; -use crate::core::indices::TypeIdx; use crate::core::reader::WasmReader; +use crate::core::utils::ToUsizeExt; use crate::execution::assert_validated::UnwrapValidatedExt; use crate::ValidationError; @@ -162,7 +162,7 @@ pub enum BlockType { impl BlockType { pub fn read(wasm: &mut WasmReader) -> Result { - if wasm.peek_u8()? as i8 == 0x40 { + if wasm.peek_u8()? == 0x40 { // Empty block type let _ = wasm.read_u8().unwrap_validated(); Ok(BlockType::Empty) @@ -196,7 +196,7 @@ impl BlockType { }, }), BlockType::Type(type_idx) => { - let type_idx = *type_idx as TypeIdx; + let type_idx = type_idx.into_usize(); func_types .get(type_idx) .cloned() diff --git a/src/core/reader/types/values.rs b/src/core/reader/types/values.rs index 85505777d0..2f1d105b71 100644 --- a/src/core/reader/types/values.rs +++ b/src/core/reader/types/values.rs @@ -8,6 +8,7 @@ use alloc::vec::Vec; use crate::core::reader::WasmReader; +use crate::core::utils::ToUsizeExt; use crate::ValidationError; /// Wasm encodes integers according to the LEB128 format, which specifies that @@ -352,7 +353,7 @@ impl<'wasm> WasmReader<'wasm> { /// Note: If `Err`, the [WasmReader] object is no longer guaranteed to be in a valid state pub fn read_name(&mut self) -> Result<&'wasm str, ValidationError> { - let len = self.read_var_u32()? as usize; + let len = self.read_var_u32()?.into_usize(); let utf8_str = &self .full_wasm_binary @@ -388,7 +389,7 @@ impl<'wasm> WasmReader<'wasm> { { let len = self.read_var_u32()?; core::iter::repeat_with(|| read_element(self)) - .take(len as usize) + .take(len.into_usize()) .collect() } } diff --git a/src/core/rw_spinlock.rs b/src/core/rw_spinlock.rs index 1bab6d01cd..c4519e4b74 100644 --- a/src/core/rw_spinlock.rs +++ b/src/core/rw_spinlock.rs @@ -54,7 +54,7 @@ impl RwSpinLock { loop { // s is even, so there are maybe active readers but no active or waiting writer // -> reader can acquire read guard (as long as an overflow is avoided) - if s % 2 == 0 && s < u32::MAX - 2 { + if s.is_multiple_of(2) && s < u32::MAX - 2 { match self.state.compare_exchange_weak( s, s + 2, @@ -95,7 +95,7 @@ impl RwSpinLock { } // announce that a writer is waiting if this is not yet announced - if s % 2 == 0 { + if s.is_multiple_of(2) { match self .state // ordering by the book diff --git a/src/core/utils.rs b/src/core/utils.rs index d1ef958aad..10f24f76f4 100644 --- a/src/core/utils.rs +++ b/src/core/utils.rs @@ -32,3 +32,20 @@ pub fn print_beautiful_fd_extension(second_byte: u32, pc: usize) { pc, ); } + +#[cfg(any(target_pointer_width = "32", target_pointer_width = "64"))] +pub trait ToUsizeExt { + fn into_usize(self) -> usize; +} + +#[cfg(any(target_pointer_width = "32", target_pointer_width = "64"))] +impl ToUsizeExt for u32 { + fn into_usize(self) -> usize { + // SAFETY: The current trait only exists for architectures where + // pointers are at least 32 bits wide. + unsafe { usize::try_from(self).unwrap_unchecked() } + } +} + +#[cfg(target_pointer_width = "16")] +compile_error!("targets with 16 bit wide pointers are currently not supported"); diff --git a/src/execution/const_interpreter_loop.rs b/src/execution/const_interpreter_loop.rs index 596e6951e9..5dbe467a9e 100644 --- a/src/execution/const_interpreter_loop.rs +++ b/src/execution/const_interpreter_loop.rs @@ -5,12 +5,12 @@ use crate::{ assert_validated::UnwrapValidatedExt, config::Config, core::{ - indices::GlobalIdx, reader::{ span::Span, types::{FuncType, ResultType}, WasmReader, }, + utils::ToUsizeExt, }, unreachable_validated, value::{self, Ref}, @@ -51,7 +51,7 @@ pub(crate) fn run_const( break; } GLOBAL_GET => { - let global_idx = wasm.read_var_u32().unwrap_validated() as GlobalIdx; + let global_idx = wasm.read_var_u32().unwrap_validated().into_usize(); //TODO replace double indirection let global = store @@ -92,7 +92,7 @@ pub(crate) fn run_const( } REF_FUNC => { // we already checked for the func_idx to be in bounds during validation - let func_idx = wasm.read_var_u32().unwrap_validated() as usize; + let func_idx = wasm.read_var_u32().unwrap_validated().into_usize(); let func_addr = *store .modules .get(module) diff --git a/src/execution/interpreter_loop.rs b/src/execution/interpreter_loop.rs index 50ee329853..bb0f1b53aa 100644 --- a/src/execution/interpreter_loop.rs +++ b/src/execution/interpreter_loop.rs @@ -19,12 +19,12 @@ use crate::{ addrs::{AddrVec, DataAddr, ElemAddr, MemAddr, ModuleAddr, TableAddr}, assert_validated::UnwrapValidatedExt, core::{ - indices::{DataIdx, FuncIdx, GlobalIdx, LabelIdx, LocalIdx, TableIdx, TypeIdx}, reader::{ types::{memarg::MemArg, BlockType}, WasmReader, }, sidetable::Sidetable, + utils::ToUsizeExt, }, instances::{DataInst, ElemInst, FuncInst, MemInst, ModuleInst, TableInst}, resumable::Resumable, @@ -176,13 +176,13 @@ pub(super) fn run( BR_TABLE => { decrement_fuel!(T::get_flat_cost(BR_TABLE)); let label_vec = wasm - .read_vec(|wasm| wasm.read_var_u32().map(|v| v as LabelIdx)) + .read_vec(|wasm| wasm.read_var_u32().map(|v| v.into_usize())) .unwrap_validated(); wasm.read_var_u32().unwrap_validated(); // TODO is this correct? let case_val_i32: i32 = stack.pop_value().try_into().unwrap_validated(); - let case_val = case_val_i32 as usize; + let case_val = case_val_i32.cast_unsigned().into_usize(); if case_val >= label_vec.len() { stp += label_vec.len(); @@ -213,7 +213,7 @@ pub(super) fn run( } CALL => { decrement_fuel!(T::get_flat_cost(CALL)); - let local_func_idx = wasm.read_var_u32().unwrap_validated() as FuncIdx; + let local_func_idx = wasm.read_var_u32().unwrap_validated().into_usize(); let FuncInst::WasmFunc(current_wasm_func_inst) = store.functions.get(current_func_addr) else { @@ -289,8 +289,8 @@ pub(super) fn run( // TODO: fix push_call_frame, because the func idx that you get from the table is global func idx CALL_INDIRECT => { decrement_fuel!(T::get_flat_cost(CALL_INDIRECT)); - let given_type_idx = wasm.read_var_u32().unwrap_validated() as TypeIdx; - let table_idx = wasm.read_var_u32().unwrap_validated() as TableIdx; + let given_type_idx = wasm.read_var_u32().unwrap_validated().into_usize(); + let table_idx = wasm.read_var_u32().unwrap_validated().into_usize(); let table_addr = *store .modules @@ -310,7 +310,7 @@ pub(super) fn run( let r = tab .elem - .get(i as usize) + .get(i.into_usize()) .ok_or(TrapError::TableAccessOutOfBounds) .and_then(|r| { if matches!(r, Ref::Null(_)) { @@ -423,28 +423,28 @@ pub(super) fn run( } LOCAL_GET => { decrement_fuel!(T::get_flat_cost(LOCAL_GET)); - let local_idx = wasm.read_var_u32().unwrap_validated() as LocalIdx; + let local_idx = wasm.read_var_u32().unwrap_validated().into_usize(); let value = *stack.get_local(local_idx); stack.push_value::(value)?; trace!("Instruction: local.get {} [] -> [t]", local_idx); } LOCAL_SET => { decrement_fuel!(T::get_flat_cost(LOCAL_SET)); - let local_idx = wasm.read_var_u32().unwrap_validated() as LocalIdx; + let local_idx = wasm.read_var_u32().unwrap_validated().into_usize(); let value = stack.pop_value(); *stack.get_local_mut(local_idx) = value; trace!("Instruction: local.set {} [t] -> []", local_idx); } LOCAL_TEE => { decrement_fuel!(T::get_flat_cost(LOCAL_TEE)); - let local_idx = wasm.read_var_u32().unwrap_validated() as LocalIdx; + let local_idx = wasm.read_var_u32().unwrap_validated().into_usize(); let value = stack.peek_value().unwrap_validated(); *stack.get_local_mut(local_idx) = value; trace!("Instruction: local.tee {} [t] -> [t]", local_idx); } GLOBAL_GET => { decrement_fuel!(T::get_flat_cost(GLOBAL_GET)); - let global_idx = wasm.read_var_u32().unwrap_validated() as GlobalIdx; + let global_idx = wasm.read_var_u32().unwrap_validated().into_usize(); let global_addr = *store .modules .get(current_module) @@ -463,7 +463,7 @@ pub(super) fn run( } GLOBAL_SET => { decrement_fuel!(T::get_flat_cost(GLOBAL_SET)); - let global_idx = wasm.read_var_u32().unwrap_validated() as GlobalIdx; + let global_idx = wasm.read_var_u32().unwrap_validated().into_usize(); let global_addr = *store .modules .get(current_module) @@ -476,7 +476,7 @@ pub(super) fn run( } TABLE_GET => { decrement_fuel!(T::get_flat_cost(TABLE_GET)); - let table_idx = wasm.read_var_u32().unwrap_validated() as TableIdx; + let table_idx = wasm.read_var_u32().unwrap_validated().into_usize(); let table_addr = *store .modules .get(current_module) @@ -489,7 +489,7 @@ pub(super) fn run( let val = tab .elem - .get(i as usize) + .get(i.cast_unsigned().into_usize()) .ok_or(TrapError::TableOrElementAccessOutOfBounds)?; stack.push_value::((*val).into())?; @@ -502,7 +502,7 @@ pub(super) fn run( } TABLE_SET => { decrement_fuel!(T::get_flat_cost(TABLE_SET)); - let table_idx = wasm.read_var_u32().unwrap_validated() as TableIdx; + let table_idx = wasm.read_var_u32().unwrap_validated().into_usize(); let table_addr = *store .modules .get(current_module) @@ -515,7 +515,7 @@ pub(super) fn run( let i: i32 = stack.pop_value().try_into().unwrap_validated(); tab.elem - .get_mut(i as usize) + .get_mut(i.cast_unsigned().into_usize()) .ok_or(TrapError::TableOrElementAccessOutOfBounds) .map(|r| *r = val)?; trace!( @@ -986,7 +986,7 @@ pub(super) fn run( } MEMORY_SIZE => { decrement_fuel!(T::get_flat_cost(MEMORY_SIZE)); - let mem_idx = wasm.read_u8().unwrap_validated() as usize; + let mem_idx = usize::from(wasm.read_u8().unwrap_validated()); let mem_addr = *store .modules .get(current_module) @@ -999,7 +999,7 @@ pub(super) fn run( trace!("Instruction: memory.size [] -> [{}]", size); } MEMORY_GROW => { - let mem_idx = wasm.read_u8().unwrap_validated() as usize; + let mem_idx = usize::from(wasm.read_u8().unwrap_validated()); let mem_addr = *store .modules .get(current_module) @@ -2340,7 +2340,7 @@ pub(super) fn run( // https://webassembly.github.io/spec/core/exec/instructions.html#xref-syntax-instructions-syntax-instr-ref-mathsf-ref-func-x REF_FUNC => { decrement_fuel!(T::get_flat_cost(REF_FUNC)); - let func_idx = wasm.read_var_u32().unwrap_validated() as FuncIdx; + let func_idx = wasm.read_var_u32().unwrap_validated().into_usize(); let func_addr = *store .modules .get(current_module) @@ -2498,8 +2498,8 @@ pub(super) fn run( // n => number of bytes to copy // s => starting pointer in the data segment // d => destination address to copy to - let data_idx = wasm.read_var_u32().unwrap_validated() as DataIdx; - let mem_idx = wasm.read_u8().unwrap_validated() as usize; + let data_idx = wasm.read_var_u32().unwrap_validated().into_usize(); + let mem_idx = usize::from(wasm.read_u8().unwrap_validated()); let n: u32 = stack.pop_value().try_into().unwrap_validated(); // decrement fuel, but push n back if it fails @@ -2534,7 +2534,7 @@ pub(super) fn run( } DATA_DROP => { decrement_fuel!(T::get_fc_extension_flat_cost(DATA_DROP)); - let data_idx = wasm.read_var_u32().unwrap_validated() as DataIdx; + let data_idx = wasm.read_var_u32().unwrap_validated().into_usize(); data_drop(&store.modules, &mut store.data, current_module, data_idx); } // See https://webassembly.github.io/bulk-memory-operations/core/exec/instructions.html#xref-syntax-instructions-syntax-instr-memory-mathsf-memory-copy @@ -2544,8 +2544,8 @@ pub(super) fn run( // s => source address to copy from // d => destination address to copy to let (dst_idx, src_idx) = ( - wasm.read_u8().unwrap_validated() as usize, - wasm.read_u8().unwrap_validated() as usize, + usize::from(wasm.read_u8().unwrap_validated()), + usize::from(wasm.read_u8().unwrap_validated()), ); let n: u32 = stack.pop_value().try_into().unwrap_validated(); @@ -2583,9 +2583,12 @@ pub(super) fn run( let src_mem = store.memories.get(src_addr); let dest_mem = store.memories.get(dst_addr); - dest_mem - .mem - .copy(d as usize, &src_mem.mem, s as usize, n as usize)?; + dest_mem.mem.copy( + d.cast_unsigned().into_usize(), + &src_mem.mem, + s.cast_unsigned().into_usize(), + n.into_usize(), + )?; trace!("Instruction: memory.copy"); } // See https://webassembly.github.io/bulk-memory-operations/core/exec/instructions.html#xref-syntax-instructions-syntax-instr-memory-mathsf-memory-fill @@ -2594,7 +2597,7 @@ pub(super) fn run( // n => number of bytes to update // val => the value to set each byte to (must be < 256) // d => the pointer to the region to update - let mem_idx = wasm.read_u8().unwrap_validated() as usize; + let mem_idx = usize::from(wasm.read_u8().unwrap_validated()); let mem_addr = *store .modules .get(current_module) @@ -2627,7 +2630,8 @@ pub(super) fn run( let d: i32 = stack.pop_value().try_into().unwrap_validated(); - mem.mem.fill(d as usize, val as u8, n as usize)?; + mem.mem + .fill(d.cast_unsigned().into_usize(), val as u8, n.into_usize())?; trace!("Instruction: memory.fill"); } @@ -2636,8 +2640,8 @@ pub(super) fn run( // in binary format it seems that elemidx is first ??????? // this is ONLY for passive elements TABLE_INIT => { - let elem_idx = wasm.read_var_u32().unwrap_validated() as usize; - let table_idx = wasm.read_var_u32().unwrap_validated() as usize; + let elem_idx = wasm.read_var_u32().unwrap_validated().into_usize(); + let table_idx = wasm.read_var_u32().unwrap_validated().into_usize(); let n: u32 = stack.pop_value().try_into().unwrap_validated(); // size let cost = T::get_fc_extension_flat_cost(TABLE_INIT) @@ -2671,7 +2675,7 @@ pub(super) fn run( } ELEM_DROP => { decrement_fuel!(T::get_fc_extension_flat_cost(ELEM_DROP)); - let elem_idx = wasm.read_var_u32().unwrap_validated() as usize; + let elem_idx = wasm.read_var_u32().unwrap_validated().into_usize(); elem_drop( &store.modules, @@ -2683,8 +2687,8 @@ pub(super) fn run( // https://webassembly.github.io/spec/core/exec/instructions.html#xref-syntax-instructions-syntax-instr-table-mathsf-table-copy-x-y TABLE_COPY => { decrement_fuel!(T::get_fc_extension_flat_cost(TABLE_COPY)); - let table_x_idx = wasm.read_var_u32().unwrap_validated() as usize; - let table_y_idx = wasm.read_var_u32().unwrap_validated() as usize; + let table_x_idx = wasm.read_var_u32().unwrap_validated().into_usize(); + let table_y_idx = wasm.read_var_u32().unwrap_validated().into_usize(); let tab_x_elem_len = store .tables @@ -2720,7 +2724,7 @@ pub(super) fn run( if res > tab_y_elem_len as u32 { return Err(TrapError::TableOrElementAccessOutOfBounds.into()); } else { - res as usize + res.into_usize() } } _ => return Err(TrapError::TableOrElementAccessOutOfBounds.into()), @@ -2731,7 +2735,7 @@ pub(super) fn run( if res > tab_x_elem_len as u32 { return Err(TrapError::TableOrElementAccessOutOfBounds.into()); } else { - res as usize + res.into_usize() } } _ => return Err(TrapError::TableOrElementAccessOutOfBounds.into()), @@ -2748,7 +2752,9 @@ pub(super) fn run( .get(table_x_idx) .unwrap_validated(); let table = store.tables.get_mut(table_addr); - table.elem.copy_within(s as usize..src_res, d as usize); + table + .elem + .copy_within(s.into_usize()..src_res, d.into_usize()); } else { let src_addr = *store .modules @@ -2768,8 +2774,8 @@ pub(super) fn run( .get_two_mut(src_addr, dst_addr) .expect("both addrs to never be equal"); - dst_table.elem[d as usize..dst_res] - .copy_from_slice(&src_table.elem[s as usize..src_res]); + dst_table.elem[d.into_usize()..dst_res] + .copy_from_slice(&src_table.elem[s.into_usize()..src_res]); } trace!( @@ -2783,7 +2789,7 @@ pub(super) fn run( } TABLE_GROW => { decrement_fuel!(T::get_fc_extension_flat_cost(TABLE_GROW)); - let table_idx = wasm.read_var_u32().unwrap_validated() as usize; + let table_idx = wasm.read_var_u32().unwrap_validated().into_usize(); let table_addr = *store .modules .get(current_module) @@ -2825,7 +2831,7 @@ pub(super) fn run( } TABLE_SIZE => { decrement_fuel!(T::get_fc_extension_flat_cost(TABLE_SIZE)); - let table_idx = wasm.read_var_u32().unwrap_validated() as usize; + let table_idx = wasm.read_var_u32().unwrap_validated().into_usize(); let table_addr = *store .modules .get(current_module) @@ -2842,7 +2848,7 @@ pub(super) fn run( } TABLE_FILL => { decrement_fuel!(T::get_fc_extension_flat_cost(TABLE_FILL)); - let table_idx = wasm.read_var_u32().unwrap_validated() as usize; + let table_idx = wasm.read_var_u32().unwrap_validated().into_usize(); let table_addr = *store .modules .get(current_module) @@ -2869,12 +2875,12 @@ pub(super) fn run( let val: Ref = stack.pop_value().try_into().unwrap_validated(); let dst: u32 = stack.pop_value().try_into().unwrap_validated(); - let end = (dst as usize) - .checked_add(len as usize) + let end = (dst.into_usize()) + .checked_add(len.into_usize()) .ok_or(TrapError::TableOrElementAccessOutOfBounds)?; tab.elem - .get_mut(dst as usize..end) + .get_mut(dst.into_usize()..end) .ok_or(TrapError::TableOrElementAccessOutOfBounds)? .fill(val); @@ -3290,7 +3296,7 @@ pub(super) fn run( .unwrap_validated(); let memory = store.memories.get(mem_addr); let idx = calculate_mem_address(&memarg, relative_address)?; - let lane_idx = wasm.read_u8().unwrap_validated() as usize; + let lane_idx = usize::from(wasm.read_u8().unwrap_validated()); let mut lanes: [u8; 16] = to_lanes(data); *lanes.get_mut(lane_idx).unwrap_validated() = memory.mem.load::<1, u8>(idx)?; @@ -3310,7 +3316,7 @@ pub(super) fn run( .unwrap_validated(); let memory = store.memories.get(mem_addr); let idx = calculate_mem_address(&memarg, relative_address)?; - let lane_idx = wasm.read_u8().unwrap_validated() as usize; + let lane_idx = usize::from(wasm.read_u8().unwrap_validated()); let mut lanes: [u16; 8] = to_lanes(data); *lanes.get_mut(lane_idx).unwrap_validated() = memory.mem.load::<2, u16>(idx)?; @@ -3329,7 +3335,7 @@ pub(super) fn run( .unwrap_validated(); let memory = store.memories.get(mem_addr); let idx = calculate_mem_address(&memarg, relative_address)?; - let lane_idx = wasm.read_u8().unwrap_validated() as usize; + let lane_idx = usize::from(wasm.read_u8().unwrap_validated()); let mut lanes: [u32; 4] = to_lanes(data); *lanes.get_mut(lane_idx).unwrap_validated() = memory.mem.load::<4, u32>(idx)?; @@ -3348,7 +3354,7 @@ pub(super) fn run( .unwrap_validated(); let memory = store.memories.get(mem_addr); let idx = calculate_mem_address(&memarg, relative_address)?; - let lane_idx = wasm.read_u8().unwrap_validated() as usize; + let lane_idx = usize::from(wasm.read_u8().unwrap_validated()); let mut lanes: [u64; 2] = to_lanes(data); *lanes.get_mut(lane_idx).unwrap_validated() = memory.mem.load::<8, u64>(idx)?; @@ -3369,7 +3375,7 @@ pub(super) fn run( .unwrap_validated(); let memory = store.memories.get(mem_addr); let idx = calculate_mem_address(&memarg, relative_address)?; - let lane_idx = wasm.read_u8().unwrap_validated() as usize; + let lane_idx = usize::from(wasm.read_u8().unwrap_validated()); let lane = *to_lanes::<1, 16, u8>(data).get(lane_idx).unwrap_validated(); @@ -3388,7 +3394,7 @@ pub(super) fn run( .unwrap_validated(); let memory = store.memories.get(mem_addr); let idx = calculate_mem_address(&memarg, relative_address)?; - let lane_idx = wasm.read_u8().unwrap_validated() as usize; + let lane_idx = usize::from(wasm.read_u8().unwrap_validated()); let lane = *to_lanes::<2, 8, u16>(data).get(lane_idx).unwrap_validated(); @@ -3407,7 +3413,7 @@ pub(super) fn run( .unwrap_validated(); let memory = store.memories.get(mem_addr); let idx = calculate_mem_address(&memarg, relative_address)?; - let lane_idx = wasm.read_u8().unwrap_validated() as usize; + let lane_idx = usize::from(wasm.read_u8().unwrap_validated()); let lane = *to_lanes::<4, 4, u32>(data).get(lane_idx).unwrap_validated(); @@ -3426,7 +3432,7 @@ pub(super) fn run( .unwrap_validated(); let memory = store.memories.get(mem_addr); let idx = calculate_mem_address(&memarg, relative_address)?; - let lane_idx = wasm.read_u8().unwrap_validated() as usize; + let lane_idx = usize::from(wasm.read_u8().unwrap_validated()); let lane = *to_lanes::<8, 2, u64>(data).get(lane_idx).unwrap_validated(); @@ -3504,7 +3510,7 @@ pub(super) fn run( let data2: [u8; 16] = stack.pop_value().try_into().unwrap_validated(); let data1: [u8; 16] = stack.pop_value().try_into().unwrap_validated(); let result = - array::from_fn(|i| *data1.get(data2[i] as usize).unwrap_or(&0)); + array::from_fn(|i| *data1.get(usize::from(data2[i])).unwrap_or(&0)); stack.push_value::(Value::V128(result))?; } @@ -3518,8 +3524,8 @@ pub(super) fn run( let result = lane_selector_indices.map(|i| { *data1 - .get(i as usize) - .or_else(|| data2.get(i as usize - 16)) + .get(usize::from(i)) + .or_else(|| data2.get(usize::from(i) - 16)) .unwrap_validated() }); @@ -3569,7 +3575,7 @@ pub(super) fn run( // shape.extract_lane I8X16_EXTRACT_LANE_S => { decrement_fuel!(T::get_fd_extension_flat_cost(I8X16_EXTRACT_LANE_S)); - let lane_idx = wasm.read_u8().unwrap_validated() as usize; + let lane_idx = usize::from(wasm.read_u8().unwrap_validated()); let data: [u8; 16] = stack.pop_value().try_into().unwrap_validated(); let lanes: [i8; 16] = to_lanes(data); let lane = *lanes.get(lane_idx).unwrap_validated(); @@ -3577,7 +3583,7 @@ pub(super) fn run( } I8X16_EXTRACT_LANE_U => { decrement_fuel!(T::get_fd_extension_flat_cost(I8X16_EXTRACT_LANE_U)); - let lane_idx = wasm.read_u8().unwrap_validated() as usize; + let lane_idx = usize::from(wasm.read_u8().unwrap_validated()); let data: [u8; 16] = stack.pop_value().try_into().unwrap_validated(); let lanes: [u8; 16] = to_lanes(data); let lane = *lanes.get(lane_idx).unwrap_validated(); @@ -3585,7 +3591,7 @@ pub(super) fn run( } I16X8_EXTRACT_LANE_S => { decrement_fuel!(T::get_fd_extension_flat_cost(I16X8_EXTRACT_LANE_S)); - let lane_idx = wasm.read_u8().unwrap_validated() as usize; + let lane_idx = usize::from(wasm.read_u8().unwrap_validated()); let data: [u8; 16] = stack.pop_value().try_into().unwrap_validated(); let lanes: [i16; 8] = to_lanes(data); let lane = *lanes.get(lane_idx).unwrap_validated(); @@ -3593,7 +3599,7 @@ pub(super) fn run( } I16X8_EXTRACT_LANE_U => { decrement_fuel!(T::get_fd_extension_flat_cost(I16X8_EXTRACT_LANE_U)); - let lane_idx = wasm.read_u8().unwrap_validated() as usize; + let lane_idx = usize::from(wasm.read_u8().unwrap_validated()); let data: [u8; 16] = stack.pop_value().try_into().unwrap_validated(); let lanes: [u16; 8] = to_lanes(data); let lane = *lanes.get(lane_idx).unwrap_validated(); @@ -3601,7 +3607,7 @@ pub(super) fn run( } I32X4_EXTRACT_LANE => { decrement_fuel!(T::get_fd_extension_flat_cost(I32X4_EXTRACT_LANE)); - let lane_idx = wasm.read_u8().unwrap_validated() as usize; + let lane_idx = usize::from(wasm.read_u8().unwrap_validated()); let data: [u8; 16] = stack.pop_value().try_into().unwrap_validated(); let lanes: [u32; 4] = to_lanes(data); let lane = *lanes.get(lane_idx).unwrap_validated(); @@ -3609,7 +3615,7 @@ pub(super) fn run( } I64X2_EXTRACT_LANE => { decrement_fuel!(T::get_fd_extension_flat_cost(I64X2_EXTRACT_LANE)); - let lane_idx = wasm.read_u8().unwrap_validated() as usize; + let lane_idx = usize::from(wasm.read_u8().unwrap_validated()); let data: [u8; 16] = stack.pop_value().try_into().unwrap_validated(); let lanes: [u64; 2] = to_lanes(data); let lane = *lanes.get(lane_idx).unwrap_validated(); @@ -3617,7 +3623,7 @@ pub(super) fn run( } F32X4_EXTRACT_LANE => { decrement_fuel!(T::get_fd_extension_flat_cost(F32X4_EXTRACT_LANE)); - let lane_idx = wasm.read_u8().unwrap_validated() as usize; + let lane_idx = usize::from(wasm.read_u8().unwrap_validated()); let data: [u8; 16] = stack.pop_value().try_into().unwrap_validated(); let lanes: [F32; 4] = to_lanes(data); let lane = *lanes.get(lane_idx).unwrap_validated(); @@ -3625,7 +3631,7 @@ pub(super) fn run( } F64X2_EXTRACT_LANE => { decrement_fuel!(T::get_fd_extension_flat_cost(F64X2_EXTRACT_LANE)); - let lane_idx = wasm.read_u8().unwrap_validated() as usize; + let lane_idx = usize::from(wasm.read_u8().unwrap_validated()); let data: [u8; 16] = stack.pop_value().try_into().unwrap_validated(); let lanes: [F64; 2] = to_lanes(data); let lane = *lanes.get(lane_idx).unwrap_validated(); @@ -3635,7 +3641,7 @@ pub(super) fn run( // shape.replace_lane I8X16_REPLACE_LANE => { decrement_fuel!(T::get_fd_extension_flat_cost(I8X16_REPLACE_LANE)); - let lane_idx = wasm.read_u8().unwrap_validated() as usize; + let lane_idx = usize::from(wasm.read_u8().unwrap_validated()); let value: u32 = stack.pop_value().try_into().unwrap_validated(); let new_lane = value as u8; let data: [u8; 16] = stack.pop_value().try_into().unwrap_validated(); @@ -3645,7 +3651,7 @@ pub(super) fn run( } I16X8_REPLACE_LANE => { decrement_fuel!(T::get_fd_extension_flat_cost(I16X8_REPLACE_LANE)); - let lane_idx = wasm.read_u8().unwrap_validated() as usize; + let lane_idx = usize::from(wasm.read_u8().unwrap_validated()); let value: u32 = stack.pop_value().try_into().unwrap_validated(); let new_lane = value as u16; let data: [u8; 16] = stack.pop_value().try_into().unwrap_validated(); @@ -3655,7 +3661,7 @@ pub(super) fn run( } I32X4_REPLACE_LANE => { decrement_fuel!(T::get_fd_extension_flat_cost(I32X4_REPLACE_LANE)); - let lane_idx = wasm.read_u8().unwrap_validated() as usize; + let lane_idx = usize::from(wasm.read_u8().unwrap_validated()); let new_lane: u32 = stack.pop_value().try_into().unwrap_validated(); let data: [u8; 16] = stack.pop_value().try_into().unwrap_validated(); let mut lanes: [u32; 4] = to_lanes(data); @@ -3664,7 +3670,7 @@ pub(super) fn run( } I64X2_REPLACE_LANE => { decrement_fuel!(T::get_fd_extension_flat_cost(I64X2_REPLACE_LANE)); - let lane_idx = wasm.read_u8().unwrap_validated() as usize; + let lane_idx = usize::from(wasm.read_u8().unwrap_validated()); let new_lane: u64 = stack.pop_value().try_into().unwrap_validated(); let data: [u8; 16] = stack.pop_value().try_into().unwrap_validated(); let mut lanes: [u64; 2] = to_lanes(data); @@ -3673,7 +3679,7 @@ pub(super) fn run( } F32X4_REPLACE_LANE => { decrement_fuel!(T::get_fd_extension_flat_cost(F32X4_REPLACE_LANE)); - let lane_idx = wasm.read_u8().unwrap_validated() as usize; + let lane_idx = usize::from(wasm.read_u8().unwrap_validated()); let new_lane: F32 = stack.pop_value().try_into().unwrap_validated(); let data: [u8; 16] = stack.pop_value().try_into().unwrap_validated(); let mut lanes: [F32; 4] = to_lanes(data); @@ -3682,7 +3688,7 @@ pub(super) fn run( } F64X2_REPLACE_LANE => { decrement_fuel!(T::get_fd_extension_flat_cost(F64X2_REPLACE_LANE)); - let lane_idx = wasm.read_u8().unwrap_validated() as usize; + let lane_idx = usize::from(wasm.read_u8().unwrap_validated()); let new_lane: F64 = stack.pop_value().try_into().unwrap_validated(); let data: [u8; 16] = stack.pop_value().try_into().unwrap_validated(); let mut lanes: [F64; 2] = to_lanes(data); @@ -5615,8 +5621,10 @@ fn do_sidetable_control_transfer( stack.remove_in_between(sidetable_entry.popcnt, sidetable_entry.valcnt); - *current_stp = (*current_stp as isize + sidetable_entry.delta_stp) as usize; - wasm.pc = (wasm.pc as isize + sidetable_entry.delta_pc) as usize; + *current_stp = current_stp.checked_add_signed(sidetable_entry.delta_stp) + .expect("that adding the delta stp never causes the stp to go out of bounds unless there is a bug in the sidetable generation"); + wasm.pc = wasm.pc.checked_add_signed(sidetable_entry.delta_pc) + .expect("that adding the delta pc never causes the pc to go out of bounds unless there is a bug in the sidetable generation"); Ok(()) } @@ -5649,6 +5657,10 @@ pub(super) fn table_init( s: i32, d: i32, ) -> Result<(), RuntimeError> { + let n = n.into_usize(); + let s = s.cast_unsigned().into_usize(); + let d = d.cast_unsigned().into_usize(); + let tab_addr = *store_modules .get(current_module) .table_addrs @@ -5673,21 +5685,17 @@ pub(super) fn table_init( n ); - let final_src_offset = (s as usize) - .checked_add(n as usize) + let final_src_offset = s + .checked_add(n) .filter(|&res| res <= elem.len()) .ok_or(TrapError::TableOrElementAccessOutOfBounds)?; - if (d as usize) - .checked_add(n as usize) - .filter(|&res| res <= tab.len()) - .is_none() - { + if d.checked_add(n).filter(|&res| res <= tab.len()).is_none() { return Err(TrapError::TableOrElementAccessOutOfBounds.into()); } - let dest = &mut tab.elem[d as usize..]; - let src = &elem.references[s as usize..final_src_offset]; + let dest = &mut tab.elem[d..]; + let src = &elem.references[s..final_src_offset]; dest[..src.len()].copy_from_slice(src); Ok(()) } @@ -5721,9 +5729,9 @@ pub(super) fn memory_init( s: u32, d: u32, ) -> Result<(), RuntimeError> { - let n = usize::try_from(n).expect("pointer width to be at least 32 bits wide"); - let s = usize::try_from(s).expect("pointer width to be at least 32 bits wide"); - let d = usize::try_from(d).expect("pointer width to be at least 32 bits wide"); + let n = n.into_usize(); + let s = s.into_usize(); + let d = d.into_usize(); let mem_addr = *store_modules .get(current_module) diff --git a/src/execution/store/instances.rs b/src/execution/store/instances.rs index 71b3c40bb5..1faee6fd3f 100644 --- a/src/execution/store/instances.rs +++ b/src/execution/store/instances.rs @@ -8,6 +8,7 @@ use crate::{ types::{FuncType, MemType, TableType}, }, sidetable::Sidetable, + utils::ToUsizeExt, }, linear_memory::LinearMemory, value::Ref, @@ -100,7 +101,7 @@ impl TableInst { max: self.ty.lim.max, }; - self.elem.extend(vec![reff; n as usize]); + self.elem.extend(vec![reff; n.into_usize()]); self.ty.lim = limits_prime; Ok(()) @@ -147,7 +148,7 @@ impl MemInst { /// Can never be bigger than 65,356 pages pub fn size(&self) -> usize { - self.mem.len() / (crate::Limits::MEM_PAGE_SIZE as usize) + self.mem.len() / (crate::Limits::MEM_PAGE_SIZE.into_usize()) } } diff --git a/src/execution/store/linear_memory.rs b/src/execution/store/linear_memory.rs index b6fd021d9f..dd5ef73837 100644 --- a/src/execution/store/linear_memory.rs +++ b/src/execution/store/linear_memory.rs @@ -108,7 +108,7 @@ impl LinearMemory { /// Create a new, empty [`LinearMemory`] pub fn new_with_initial_pages(pages: PageCountTy) -> Self { - let size_bytes = Self::PAGE_SIZE * pages as usize; + let size_bytes = Self::PAGE_SIZE * usize::from(pages); let mut data = Vec::with_capacity(size_bytes); data.resize_with(size_bytes, || AtomicU8::new(0)); @@ -121,7 +121,7 @@ impl LinearMemory { pub fn grow(&self, pages_to_add: PageCountTy) { let mut lock_guard = self.inner_data.write(); let prior_length_bytes = lock_guard.len(); - let new_length_bytes = prior_length_bytes + Self::PAGE_SIZE * pages_to_add as usize; + let new_length_bytes = prior_length_bytes + Self::PAGE_SIZE * usize::from(pages_to_add); lock_guard.resize_with(new_length_bytes, || AtomicU8::new(0)); } @@ -523,7 +523,7 @@ impl core::fmt::Debug for LinearMemory { let mut list = f.debug_list(); deduplicated_with_count.for_each(|(count, value)| { if count < MIN_REPETITIONS_FOR_GROUP { - list.entries(iter::repeat(value).take(count)); + list.entries(iter::repeat_n(value, count)); } else { list.entry(&format_args!("#{count} × {value}")); } diff --git a/src/execution/store/mod.rs b/src/execution/store/mod.rs index 511f247bda..d7345415b9 100644 --- a/src/execution/store/mod.rs +++ b/src/execution/store/mod.rs @@ -15,6 +15,7 @@ use crate::core::reader::types::{ ExternType, FuncType, ImportSubTypeRelation, MemType, ResultType, TableType, }; use crate::core::reader::WasmReader; +use crate::core::utils::ToUsizeExt; use crate::execution::interpreter_loop::{self, memory_init, table_init}; use crate::execution::value::{Ref, Value}; use crate::execution::{run_const_span, Stack}; @@ -200,7 +201,7 @@ impl<'b, T: Config> Store<'b, T> { .modules .get(module_addr) .func_addrs - .get(*func_idx as usize) + .get(func_idx.into_usize()) .unwrap_validated(); new_list.push(Ref::Func(func_addr)); @@ -351,7 +352,7 @@ impl<'b, T: Config> Store<'b, T> { &self.elements, module_addr, i, - *table_idx_i as usize, + table_idx_i.into_usize(), n, s, d, @@ -584,7 +585,7 @@ impl<'b, T: Config> Store<'b, T> { /// the current [`Store`] object. pub fn table_read_unchecked(&self, table_addr: TableAddr, i: u32) -> Result { // Convert `i` to usize for indexing - let i = usize::try_from(i).expect("the architecture to be at least 32-bit"); + let i = i.into_usize(); // 1. Let `ti` be the table instance `store.tables[tableaddr]` let ti = self.tables.get(table_addr); @@ -613,7 +614,7 @@ impl<'b, T: Config> Store<'b, T> { r#ref: Ref, ) -> Result<(), RuntimeError> { // Convert `i` to usize for indexing - let i = usize::try_from(i).expect("the architecture to be at least 32-bit"); + let i = i.into_usize(); // 1. Let `ti` be the table instance `store.tables[tableaddr]`. let ti = self.tables.get_mut(table_addr); @@ -718,7 +719,7 @@ impl<'b, T: Config> Store<'b, T> { /// current [`Store`] object. pub fn mem_read_unchecked(&self, mem_addr: MemAddr, i: u32) -> Result { // Convert the index type - let i = usize::try_from(i).expect("the architecture to be at least 32-bit"); + let i = i.into_usize(); // 1. Let `mi` be the memory instance `store.mems[memaddr]`. let mi = self.memories.get(mem_addr); @@ -742,7 +743,7 @@ impl<'b, T: Config> Store<'b, T> { byte: u8, ) -> Result<(), RuntimeError> { // Convert the index type - let i = usize::try_from(i).expect("the architecture to be at least 32-bit"); + let i = i.into_usize(); // 1. Let `mi` be the memory instance `store.mems[memaddr]`. let mi = self.memories.get(mem_addr); @@ -930,7 +931,7 @@ impl<'b, T: Config> Store<'b, T> { fn alloc_table(&mut self, table_type: TableType, reff: Ref) -> TableAddr { let table_inst = TableInst { ty: table_type, - elem: vec![reff; table_type.lim.min as usize], + elem: vec![reff; table_type.lim.min.into_usize()], }; self.tables.insert(table_inst) diff --git a/src/validation/code.rs b/src/validation/code.rs index 0cc6c24df2..e67421c871 100644 --- a/src/validation/code.rs +++ b/src/validation/code.rs @@ -1,10 +1,9 @@ +use core::iter; + use alloc::collections::btree_set::BTreeSet; use alloc::vec::Vec; -use core::iter; -use crate::core::indices::{ - DataIdx, ElemIdx, FuncIdx, GlobalIdx, LabelIdx, LocalIdx, MemIdx, TableIdx, TypeIdx, -}; +use crate::core::indices::{DataIdx, FuncIdx}; use crate::core::reader::section_header::{SectionHeader, SectionTy}; use crate::core::reader::span::Span; use crate::core::reader::types::element::ElemType; @@ -13,6 +12,7 @@ use crate::core::reader::types::memarg::MemArg; use crate::core::reader::types::{BlockType, FuncType, MemType, NumType, TableType, ValType}; use crate::core::reader::WasmReader; use crate::core::sidetable::{Sidetable, SidetableEntry}; +use crate::core::utils::ToUsizeExt; use crate::validation_stack::{LabelInfo, ValidationStack}; use crate::{RefType, ValidationError}; @@ -42,7 +42,7 @@ pub fn validate_code_section( let func_ty = fn_types[ty_idx].clone(); let func_size = wasm.read_var_u32()?; - let func_block = wasm.make_span(func_size as usize)?; + let func_block = wasm.make_span(func_size.into_usize())?; let previous_pc = wasm.pc; let locals = { @@ -70,7 +70,7 @@ pub fn validate_code_section( )?; // Check if there were unread trailing instructions after the last END - if previous_pc + func_size as usize != wasm.pc { + if previous_pc + func_size.into_usize() != wasm.pc { return Err(ValidationError::CodeExprHasTrailingInstructions); } @@ -87,7 +87,7 @@ pub fn validate_code_section( pub fn read_declared_locals(wasm: &mut WasmReader) -> Result, ValidationError> { let locals = wasm.read_vec(|wasm| { - let n = wasm.read_var_u32()? as usize; + let n = wasm.read_var_u32()?.into_usize(); let valtype = ValType::read(wasm)?; Ok((n, valtype)) @@ -116,7 +116,7 @@ pub fn read_declared_locals(wasm: &mut WasmReader) -> Result, Valid // Flatten local types for easier representation where n > 1 let locals = locals .into_iter() - .flat_map(|entry| iter::repeat(entry.1).take(entry.0)) + .flat_map(|entry| iter::repeat_n(entry.1, entry.0)) .collect::>(); Ok(locals) @@ -302,14 +302,14 @@ fn read_instructions( } } BR => { - let label_idx = wasm.read_var_u32()? as LabelIdx; + let label_idx = wasm.read_var_u32()?.into_usize(); validate_branch_and_generate_sidetable_entry( wasm, label_idx, stack, sidetable, false, )?; stack.make_unspecified()?; } BR_IF => { - let label_idx = wasm.read_var_u32()? as LabelIdx; + let label_idx = wasm.read_var_u32()?.into_usize(); stack.assert_pop_val_type(ValType::NumType(NumType::I32))?; // The types are explicitly popped and pushed in // https://webassembly.github.io/spec/core/appendix/algorithm.html @@ -319,8 +319,9 @@ fn read_instructions( )?; } BR_TABLE => { - let label_vec = wasm.read_vec(|wasm| wasm.read_var_u32().map(|v| v as LabelIdx))?; - let max_label_idx = wasm.read_var_u32()? as LabelIdx; + let label_vec = + wasm.read_vec(|wasm| wasm.read_var_u32().map(|v| v.into_usize()))?; + let max_label_idx = wasm.read_var_u32()?.into_usize(); stack.assert_pop_val_type(ValType::NumType(NumType::I32))?; for label_idx in &label_vec { validate_branch_and_generate_sidetable_entry( @@ -426,7 +427,7 @@ fn read_instructions( } // call [t1*] -> [t2*] CALL => { - let func_idx = wasm.read_var_u32()? as FuncIdx; + let func_idx = wasm.read_var_u32()?.into_usize(); let type_idx = *type_idx_of_fn .get(func_idx) .ok_or(ValidationError::InvalidFuncIdx(func_idx))?; @@ -441,9 +442,9 @@ fn read_instructions( } } CALL_INDIRECT => { - let type_idx = wasm.read_var_u32()? as TypeIdx; + let type_idx = wasm.read_var_u32()?.into_usize(); - let table_idx = wasm.read_var_u32()? as TableIdx; + let table_idx = wasm.read_var_u32()?.into_usize(); let tab = tables .get(table_idx) @@ -491,7 +492,7 @@ fn read_instructions( } // local.get: [] -> [t] LOCAL_GET => { - let local_idx = wasm.read_var_u32()? as LocalIdx; + let local_idx = wasm.read_var_u32()?.into_usize(); let local_ty = locals .get(local_idx) .ok_or(ValidationError::InvalidLocalIdx(local_idx))?; @@ -499,7 +500,7 @@ fn read_instructions( } // local.set [t] -> [] LOCAL_SET => { - let local_idx = wasm.read_var_u32()? as LocalIdx; + let local_idx = wasm.read_var_u32()?.into_usize(); let local_ty = locals .get(local_idx) .ok_or(ValidationError::InvalidLocalIdx(local_idx))?; @@ -507,7 +508,7 @@ fn read_instructions( } // local.set [t] -> [t] LOCAL_TEE => { - let local_idx = wasm.read_var_u32()? as LocalIdx; + let local_idx = wasm.read_var_u32()?.into_usize(); let local_ty = locals .get(local_idx) .ok_or(ValidationError::InvalidLocalIdx(local_idx))?; @@ -515,7 +516,7 @@ fn read_instructions( } // global.get [] -> [t] GLOBAL_GET => { - let global_idx = wasm.read_var_u32()? as GlobalIdx; + let global_idx = wasm.read_var_u32()?.into_usize(); let global = globals .get(global_idx) .ok_or(ValidationError::InvalidGlobalIdx(global_idx))?; @@ -530,7 +531,7 @@ fn read_instructions( } // global.set [t] -> [] GLOBAL_SET => { - let global_idx = wasm.read_var_u32()? as GlobalIdx; + let global_idx = wasm.read_var_u32()?.into_usize(); let global = globals .get(global_idx) .ok_or(ValidationError::InvalidGlobalIdx(global_idx))?; @@ -542,7 +543,7 @@ fn read_instructions( stack.assert_pop_val_type(global.ty.ty)?; } TABLE_GET => { - let table_idx = wasm.read_var_u32()? as TableIdx; + let table_idx = wasm.read_var_u32()?.into_usize(); if tables.len() <= table_idx { return Err(ValidationError::InvalidTableIdx(table_idx)); @@ -554,7 +555,7 @@ fn read_instructions( stack.push_valtype(ValType::RefType(t)); } TABLE_SET => { - let table_idx = wasm.read_var_u32()? as TableIdx; + let table_idx = wasm.read_var_u32()?.into_usize(); if tables.len() <= table_idx { return Err(ValidationError::InvalidTableIdx(table_idx)); @@ -888,7 +889,7 @@ fn read_instructions( stack.assert_pop_val_type(ValType::NumType(NumType::I32))?; } MEMORY_SIZE => { - let mem_idx = wasm.read_u8()? as MemIdx; + let mem_idx = usize::from(wasm.read_u8()?); if mem_idx != 0 { return Err(ValidationError::UnsupportedMultipleMemoriesProposal); } @@ -898,7 +899,7 @@ fn read_instructions( stack.push_valtype(ValType::NumType(NumType::I32)); } MEMORY_GROW => { - let mem_idx = wasm.read_u8()? as MemIdx; + let mem_idx = usize::from(wasm.read_u8()?); if mem_idx != 0 { return Err(ValidationError::UnsupportedMultipleMemoriesProposal); } @@ -1101,7 +1102,7 @@ fn read_instructions( } REF_FUNC => { - let func_idx = wasm.read_var_u32()? as FuncIdx; + let func_idx = wasm.read_var_u32()?.into_usize(); // checking for existence suffices for checking whether this function has a valid type. if type_idx_of_fn.len() <= func_idx { @@ -1167,15 +1168,17 @@ fn read_instructions( stack.push_valtype(ValType::NumType(NumType::I64)); } MEMORY_INIT => { - let data_idx = wasm.read_var_u32()? as DataIdx; - let mem_idx = wasm.read_u8()? as MemIdx; + let data_idx = wasm.read_var_u32()?.into_usize(); + let mem_idx = usize::from(wasm.read_u8()?); if mem_idx != 0 { return Err(ValidationError::UnsupportedMultipleMemoriesProposal); } if memories.len() <= mem_idx { return Err(ValidationError::InvalidMemIdx(mem_idx)); } - if data_count.ok_or(ValidationError::MissingDataCountSection)? as usize + if data_count + .ok_or(ValidationError::MissingDataCountSection)? + .into_usize() <= data_idx { return Err(ValidationError::InvalidDataIdx(data_idx)); @@ -1187,14 +1190,17 @@ fn read_instructions( DATA_DROP => { let data_idx = wasm.read_var_u32()? as DataIdx; - if data_count.ok_or(ValidationError::MissingDataCountSection)? as usize + if data_count + .ok_or(ValidationError::MissingDataCountSection)? + .into_usize() <= data_idx { return Err(ValidationError::InvalidDataIdx(data_idx)); } } MEMORY_COPY => { - let (dst, src) = (wasm.read_u8()? as usize, wasm.read_u8()? as usize); + let (dst, src) = + (usize::from(wasm.read_u8()?), usize::from(wasm.read_u8()?)); if dst != 0 || src != 0 { return Err(ValidationError::UnsupportedMultipleMemoriesProposal); } @@ -1206,7 +1212,7 @@ fn read_instructions( stack.assert_pop_val_type(ValType::NumType(NumType::I32))?; } MEMORY_FILL => { - let mem_idx = wasm.read_u8()? as MemIdx; + let mem_idx = usize::from(wasm.read_u8()?); if mem_idx != 0 { return Err(ValidationError::UnsupportedMultipleMemoriesProposal); } @@ -1218,8 +1224,8 @@ fn read_instructions( stack.assert_pop_val_type(ValType::NumType(NumType::I32))?; } TABLE_INIT => { - let elem_idx = wasm.read_var_u32()? as ElemIdx; - let table_idx = wasm.read_var_u32()? as TableIdx; + let elem_idx = wasm.read_var_u32()?.into_usize(); + let table_idx = wasm.read_var_u32()?.into_usize(); if tables.len() <= table_idx { return Err(ValidationError::InvalidTableIdx(table_idx)); @@ -1245,15 +1251,15 @@ fn read_instructions( stack.assert_pop_val_type(ValType::NumType(NumType::I32))?; } ELEM_DROP => { - let elem_idx = wasm.read_var_u32()? as ElemIdx; + let elem_idx = wasm.read_var_u32()?.into_usize(); if elements.len() <= elem_idx { return Err(ValidationError::InvalidElemIdx(elem_idx)); } } TABLE_COPY => { - let table_x_idx = wasm.read_var_u32()? as TableIdx; - let table_y_idx = wasm.read_var_u32()? as TableIdx; + let table_x_idx = wasm.read_var_u32()?.into_usize(); + let table_y_idx = wasm.read_var_u32()?.into_usize(); if tables.len() <= table_x_idx { return Err(ValidationError::InvalidTableIdx(table_x_idx)); @@ -1278,7 +1284,7 @@ fn read_instructions( stack.assert_pop_val_type(ValType::NumType(NumType::I32))?; } TABLE_GROW => { - let table_idx = wasm.read_var_u32()? as TableIdx; + let table_idx = wasm.read_var_u32()?.into_usize(); if tables.len() <= table_idx { return Err(ValidationError::InvalidTableIdx(table_idx)); @@ -1292,7 +1298,7 @@ fn read_instructions( stack.push_valtype(ValType::NumType(NumType::I32)); } TABLE_SIZE => { - let table_idx = wasm.read_var_u32()? as TableIdx; + let table_idx = wasm.read_var_u32()?.into_usize(); if tables.len() <= table_idx { return Err(ValidationError::InvalidTableIdx(table_idx)); @@ -1301,7 +1307,7 @@ fn read_instructions( stack.push_valtype(ValType::NumType(NumType::I32)); } TABLE_FILL => { - let table_idx = wasm.read_var_u32()? as TableIdx; + let table_idx = wasm.read_var_u32()?.into_usize(); if tables.len() <= table_idx { return Err(ValidationError::InvalidTableIdx(table_idx)); diff --git a/src/validation/data.rs b/src/validation/data.rs index c1be1c4f94..29e264dadc 100644 --- a/src/validation/data.rs +++ b/src/validation/data.rs @@ -2,7 +2,6 @@ use alloc::vec::Vec; use crate::{ core::{ - indices::MemIdx, reader::{ section_header::{SectionHeader, SectionTy}, types::{ @@ -11,6 +10,7 @@ use crate::{ }, WasmReader, }, + utils::ToUsizeExt, }, read_constant_expression::read_constant_expression, validation_stack::ValidationStack, @@ -73,7 +73,7 @@ pub(super) fn validate_data_section( } 2 => { trace!("Data section: active {{ memory x, offset e }}"); - let mem_idx = wasm.read_var_u32()? as MemIdx; + let mem_idx = wasm.read_var_u32()?.into_usize(); if mem_idx >= no_of_total_memories { return Err(crate::ValidationError::InvalidMemIdx(mem_idx)); } diff --git a/src/validation/mod.rs b/src/validation/mod.rs index 12025b373c..9c687e2129 100644 --- a/src/validation/mod.rs +++ b/src/validation/mod.rs @@ -14,6 +14,7 @@ use crate::core::reader::types::import::{Import, ImportDesc}; use crate::core::reader::types::{ExternType, FuncType, MemType, ResultType, TableType}; use crate::core::reader::WasmReader; use crate::core::sidetable::Sidetable; +use crate::core::utils::ToUsizeExt; use crate::ValidationError; pub(crate) mod code; @@ -217,7 +218,7 @@ pub fn validate(wasm: &[u8]) -> Result, ValidationError> { let local_functions = handle_section(&mut wasm, &mut header, SectionTy::Function, |wasm, _| { wasm.read_vec(|wasm| { - let type_idx = wasm.read_var_u32()? as usize; + let type_idx = wasm.read_var_u32()?.into_usize(); types .get(type_idx) .ok_or(ValidationError::InvalidTypeIdx(type_idx))?; @@ -354,7 +355,7 @@ pub fn validate(wasm: &[u8]) -> Result, ValidationError> { while (skip_section(&mut wasm, &mut header)?).is_some() {} let start = handle_section(&mut wasm, &mut header, SectionTy::Start, |wasm, _| { - let func_idx = wasm.read_var_u32().map(|idx| idx as FuncIdx)?; + let func_idx = wasm.read_var_u32().map(|idx| idx.into_usize())?; // start function signature must be [] -> [] // https://webassembly.github.io/spec/core/valid/modules.html#start-function let type_idx = *all_functions @@ -445,7 +446,7 @@ pub fn validate(wasm: &[u8]) -> Result, ValidationError> { // https://webassembly.github.io/spec/core/binary/modules.html#data-count-section if let (Some(data_count), data_len) = (data_count, data_section.len()) { - if data_count as usize != data_len { + if data_count.into_usize() != data_len { return Err(ValidationError::DataCountAndDataSectionsLengthAreDifferent); } } diff --git a/src/validation/read_constant_expression.rs b/src/validation/read_constant_expression.rs index 191938ba70..7207d8464f 100644 --- a/src/validation/read_constant_expression.rs +++ b/src/validation/read_constant_expression.rs @@ -1,9 +1,10 @@ use alloc::vec::Vec; -use crate::core::indices::{FuncIdx, GlobalIdx}; +use crate::core::indices::FuncIdx; use crate::core::reader::span::Span; use crate::core::reader::types::global::GlobalType; use crate::core::reader::WasmReader; +use crate::core::utils::ToUsizeExt; use crate::{NumType, RefType, ValType, ValidationError}; use super::validation_stack::ValidationStack; @@ -119,7 +120,7 @@ pub fn read_constant_expression( return Ok((Span::new(start_pc, wasm.pc - start_pc), seen_func_idxs)); } GLOBAL_GET => { - let global_idx = wasm.read_var_u32()? as GlobalIdx; + let global_idx = wasm.read_var_u32()?.into_usize(); trace!("{:?}", globals_ty); let global = globals_ty .get(global_idx) @@ -148,7 +149,7 @@ pub fn read_constant_expression( stack.push_valtype(ValType::RefType(RefType::read(wasm)?)); } REF_FUNC => { - let func_idx = wasm.read_var_u32()? as usize; + let func_idx = wasm.read_var_u32()?.into_usize(); // checking for existence suffices for checking whether this function has a valid type. if num_funcs <= func_idx { diff --git a/src/validation/validation_stack.rs b/src/validation/validation_stack.rs index 1257fa92f8..60c79875b7 100644 --- a/src/validation/validation_stack.rs +++ b/src/validation/validation_stack.rs @@ -178,8 +178,10 @@ impl ValidationStack { } else { stack.splice( stack_len - i..stack_len - i, - iter::repeat(ValidationStackEntry::Bottom) - .take(expected_val_types.len() - i), + iter::repeat_n( + ValidationStackEntry::Bottom, + expected_val_types.len() - i, + ), ); } return Ok(());