Skip to content

Commit 4223bb7

Browse files
fix: null ref element initialization
Signed-off-by: Henry Gressmann <[email protected]>
1 parent 4297566 commit 4223bb7

File tree

5 files changed

+39
-23
lines changed

5 files changed

+39
-23
lines changed

crates/tinywasm/src/runtime/executor/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -595,8 +595,8 @@ fn exec_one(
595595
TableSet(table_index) => {
596596
let table_idx = module.resolve_table_addr(*table_index);
597597
let table = store.get_table(table_idx as usize)?;
598-
let idx = stack.values.pop_t::<u32>()? as usize;
599598
let val = stack.values.pop_t::<u32>()?;
599+
let idx = stack.values.pop_t::<u32>()? as usize;
600600
table.borrow_mut().set(idx, val)?;
601601
}
602602

crates/tinywasm/src/store.rs

Lines changed: 29 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -429,6 +429,8 @@ impl TableElement {
429429
}
430430
}
431431

432+
const MAX_TABLE_SIZE: u32 = 10000000;
433+
432434
/// A WebAssembly Table Instance
433435
///
434436
/// See <https://webassembly.github.io/spec/core/exec/runtime.html#table-instances>
@@ -459,28 +461,42 @@ impl TableInstance {
459461
}
460462

461463
pub(crate) fn set(&mut self, table_idx: usize, value: Addr) -> Result<()> {
462-
let el = self
463-
.elements
464-
.get_mut(table_idx)
465-
.ok_or_else(|| Error::Other(format!("table element {} not found", table_idx)))?;
466-
*el = TableElement::Initialized(value);
467-
Ok(())
464+
self.grow_to_fit(table_idx + 1)
465+
.ok_or_else(|| {
466+
Error::Trap(crate::Trap::TableOutOfBounds { offset: table_idx, len: 1, max: self.elements.len() })
467+
})
468+
.and_then(|_| {
469+
self.elements[table_idx] = TableElement::Initialized(value);
470+
Ok(())
471+
})
472+
}
473+
474+
pub(crate) fn grow_to_fit(&mut self, new_size: usize) -> Option<()> {
475+
if new_size > self.elements.len() {
476+
if new_size <= self.kind.size_max.unwrap_or(MAX_TABLE_SIZE) as usize {
477+
self.elements.resize(new_size, TableElement::Uninitialized);
478+
} else {
479+
return None;
480+
}
481+
}
482+
Some(())
468483
}
469484

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

474-
pub(crate) fn init(&mut self, func_addrs: &[u32], offset: i32, init: &[Addr]) -> Result<()> {
489+
pub(crate) fn init(&mut self, func_addrs: &[u32], offset: i32, init: &[Option<Addr>]) -> Result<()> {
475490
let init = init
476491
.iter()
477-
.map(|item| {
478-
TableElement::Initialized(match self.kind.element_type == ValType::RefFunc {
492+
.map(|item| match item {
493+
None => TableElement::Uninitialized,
494+
Some(item) => TableElement::Initialized(match self.kind.element_type == ValType::RefFunc {
479495
true => *func_addrs.get(*item as usize).expect(
480496
"error initializing table: function not found. This should have been caught by the validator",
481497
),
482498
false => *item,
483-
})
499+
}),
484500
})
485501
.collect::<Vec<_>>();
486502

@@ -620,12 +636,12 @@ impl GlobalInstance {
620636
#[derive(Debug)]
621637
pub(crate) struct ElementInstance {
622638
pub(crate) kind: ElementKind,
623-
pub(crate) items: Option<Vec<u32>>, // none is the element was dropped
624-
_owner: ModuleInstanceAddr, // index into store.module_instances
639+
pub(crate) items: Option<Vec<Option<u32>>>, // none is the element was dropped
640+
_owner: ModuleInstanceAddr, // index into store.module_instances
625641
}
626642

627643
impl ElementInstance {
628-
pub(crate) fn new(kind: ElementKind, owner: ModuleInstanceAddr, items: Option<Vec<u32>>) -> Self {
644+
pub(crate) fn new(kind: ElementKind, owner: ModuleInstanceAddr, items: Option<Vec<Option<u32>>>) -> Self {
629645
Self { kind, _owner: owner, items }
630646
}
631647
}

0 commit comments

Comments
 (0)