Skip to content

Commit

Permalink
fix: null ref element initialization
Browse files Browse the repository at this point in the history
Signed-off-by: Henry Gressmann <mail@henrygressmann.de>
  • Loading branch information
explodingcamera committed Jan 24, 2024
1 parent 4297566 commit 4223bb7
Show file tree
Hide file tree
Showing 5 changed files with 39 additions and 23 deletions.
2 changes: 1 addition & 1 deletion crates/tinywasm/src/runtime/executor/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -595,8 +595,8 @@ fn exec_one(
TableSet(table_index) => {
let table_idx = module.resolve_table_addr(*table_index);
let table = store.get_table(table_idx as usize)?;
let idx = stack.values.pop_t::<u32>()? as usize;
let val = stack.values.pop_t::<u32>()?;
let idx = stack.values.pop_t::<u32>()? as usize;
table.borrow_mut().set(idx, val)?;
}

Expand Down
42 changes: 29 additions & 13 deletions crates/tinywasm/src/store.rs
Original file line number Diff line number Diff line change
Expand Up @@ -429,6 +429,8 @@ impl TableElement {
}
}

const MAX_TABLE_SIZE: u32 = 10000000;

/// A WebAssembly Table Instance
///
/// See <https://webassembly.github.io/spec/core/exec/runtime.html#table-instances>
Expand Down Expand Up @@ -459,28 +461,42 @@ impl TableInstance {
}

pub(crate) fn set(&mut self, table_idx: usize, value: Addr) -> Result<()> {
let el = self
.elements
.get_mut(table_idx)
.ok_or_else(|| Error::Other(format!("table element {} not found", table_idx)))?;
*el = TableElement::Initialized(value);
Ok(())
self.grow_to_fit(table_idx + 1)
.ok_or_else(|| {
Error::Trap(crate::Trap::TableOutOfBounds { offset: table_idx, len: 1, max: self.elements.len() })
})
.and_then(|_| {
self.elements[table_idx] = TableElement::Initialized(value);
Ok(())
})
}

pub(crate) fn grow_to_fit(&mut self, new_size: usize) -> Option<()> {
if new_size > self.elements.len() {
if new_size <= self.kind.size_max.unwrap_or(MAX_TABLE_SIZE) as usize {
self.elements.resize(new_size, TableElement::Uninitialized);
} else {
return None;
}
}
Some(())
}

pub(crate) fn size(&self) -> i32 {
self.elements.len() as i32
}

pub(crate) fn init(&mut self, func_addrs: &[u32], offset: i32, init: &[Addr]) -> Result<()> {
pub(crate) fn init(&mut self, func_addrs: &[u32], offset: i32, init: &[Option<Addr>]) -> Result<()> {
let init = init
.iter()
.map(|item| {
TableElement::Initialized(match self.kind.element_type == ValType::RefFunc {
.map(|item| match item {
None => TableElement::Uninitialized,
Some(item) => TableElement::Initialized(match self.kind.element_type == ValType::RefFunc {
true => *func_addrs.get(*item as usize).expect(
"error initializing table: function not found. This should have been caught by the validator",
),
false => *item,
})
}),
})
.collect::<Vec<_>>();

Expand Down Expand Up @@ -620,12 +636,12 @@ impl GlobalInstance {
#[derive(Debug)]
pub(crate) struct ElementInstance {
pub(crate) kind: ElementKind,
pub(crate) items: Option<Vec<u32>>, // none is the element was dropped
_owner: ModuleInstanceAddr, // index into store.module_instances
pub(crate) items: Option<Vec<Option<u32>>>, // none is the element was dropped
_owner: ModuleInstanceAddr, // index into store.module_instances
}

impl ElementInstance {
pub(crate) fn new(kind: ElementKind, owner: ModuleInstanceAddr, items: Option<Vec<u32>>) -> Self {
pub(crate) fn new(kind: ElementKind, owner: ModuleInstanceAddr, items: Option<Vec<Option<u32>>>) -> Self {
Self { kind, _owner: owner, items }
}
}
Expand Down
Loading

0 comments on commit 4223bb7

Please sign in to comment.