Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit be0c5aa

Browse files
chore: import should error on invalid memory/table type
Signed-off-by: Henry Gressmann <[email protected]>
1 parent 4501b9b commit be0c5aa

File tree

6 files changed

+93
-29
lines changed

6 files changed

+93
-29
lines changed

crates/tinywasm/src/error.rs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use alloc::string::String;
1+
use alloc::string::{String, ToString};
22
use core::fmt::Display;
33
use tinywasm_types::FuncType;
44

@@ -66,6 +66,12 @@ pub enum LinkingError {
6666
},
6767
}
6868

69+
impl LinkingError {
70+
pub(crate) fn incompatible_import_type(import: &tinywasm_types::Import) -> Self {
71+
Self::IncompatibleImportType { module: import.module.to_string(), name: import.name.to_string() }
72+
}
73+
}
74+
6975
#[derive(Debug)]
7076
/// A WebAssembly trap
7177
///

crates/tinywasm/src/imports.rs

Lines changed: 74 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ use core::fmt::Debug;
44

55
use crate::{
66
func::{FromWasmValueTuple, IntoWasmValueTuple, ValTypesFromTuple},
7-
Result,
7+
LinkingError, Result,
88
};
99
use alloc::{
1010
collections::BTreeMap,
@@ -263,19 +263,79 @@ impl Imports {
263263
None
264264
}
265265

266-
fn compare_types<T>(import: &Import, expected: &T, actual: &T) -> Result<()>
266+
fn compare_types<T>(import: &Import, actual: &T, expected: &T) -> Result<()>
267267
where
268268
T: Debug + PartialEq,
269269
{
270270
if expected != actual {
271271
log::error!("failed to link import {}, expected {:?}, got {:?}", import.name, expected, actual);
272-
return Err(crate::LinkingError::IncompatibleImportType {
273-
module: import.module.to_string(),
274-
name: import.name.to_string(),
272+
return Err(LinkingError::incompatible_import_type(import).into());
273+
}
274+
275+
Ok(())
276+
}
277+
278+
fn compare_table_types(import: &Import, expected: &TableType, actual: &TableType) -> Result<()> {
279+
Self::compare_types(import, &actual.element_type, &expected.element_type)?;
280+
281+
if actual.size_initial > expected.size_initial {
282+
return Err(LinkingError::incompatible_import_type(import).into());
283+
}
284+
285+
match (expected.size_max, actual.size_max) {
286+
(None, Some(_)) => return Err(LinkingError::incompatible_import_type(import).into()),
287+
(Some(expected_max), Some(actual_max)) if actual_max < expected_max => {
288+
return Err(LinkingError::incompatible_import_type(import).into())
289+
}
290+
_ => {}
291+
}
292+
293+
// if expected.size_max.is_none() && actual.size_max.is_some() {
294+
// return Err(LinkingError::incompatible_import_type(import).into());
295+
// }
296+
297+
// if expected.size_max.unwrap_or(0) < actual.size_max.unwrap_or(0) {
298+
// return Err(LinkingError::incompatible_import_type(import).into());
299+
// }
300+
301+
log::error!("size_initial: expected: {:?} got: {:?}", expected.size_initial, actual.size_initial);
302+
log::error!("size_max: expected: {:?} got: {:?}", expected.size_max, actual.size_max);
303+
// TODO: check limits
304+
305+
Ok(())
306+
}
307+
308+
fn compare_memory_types(
309+
import: &Import,
310+
expected: &MemoryType,
311+
actual: &MemoryType,
312+
real_size: Option<usize>,
313+
) -> Result<()> {
314+
Self::compare_types(import, &expected.arch, &actual.arch)?;
315+
316+
if actual.page_count_initial > expected.page_count_initial {
317+
if let Some(real_size) = real_size {
318+
if actual.page_count_initial > real_size as u64 {
319+
return Err(LinkingError::incompatible_import_type(import).into());
320+
}
321+
} else {
322+
return Err(LinkingError::incompatible_import_type(import).into());
323+
}
324+
}
325+
326+
match (expected.page_count_max, actual.page_count_max) {
327+
(None, Some(_)) => return Err(LinkingError::incompatible_import_type(import).into()),
328+
(Some(expected_max), Some(actual_max)) if actual_max < expected_max => {
329+
return Err(LinkingError::incompatible_import_type(import).into())
275330
}
276-
.into());
331+
_ => {}
277332
}
278333

334+
log::error!("size_initial: {:?} {:?}", expected.page_count_initial, actual.page_count_initial);
335+
log::error!("size_max: {:?} {:?}", expected.page_count_max, actual.page_count_max);
336+
337+
// TODO: check limits
338+
279339
Ok(())
280340
}
281341

@@ -304,13 +364,11 @@ impl Imports {
304364
imports.globals.push(store.add_global(extern_global.ty, extern_global.val.into(), idx)?);
305365
}
306366
(Extern::Table(extern_table), ImportKind::Table(ty)) => {
307-
Self::compare_types(import, &extern_table.ty.element_type, &ty.element_type)?;
308-
// TODO: do we need to check any limits?
367+
Self::compare_table_types(import, &extern_table.ty, &ty)?;
309368
imports.tables.push(store.add_table(extern_table.ty, idx)?);
310369
}
311370
(Extern::Memory(extern_memory), ImportKind::Memory(ty)) => {
312-
Self::compare_types(import, &extern_memory.ty.arch, &ty.arch)?;
313-
// TODO: do we need to check any limits?
371+
Self::compare_memory_types(import, &extern_memory.ty, &ty, None)?;
314372
imports.memories.push(store.add_mem(extern_memory.ty, idx)?);
315373
}
316374
(Extern::Function(extern_func), ImportKind::Function(ty)) => {
@@ -352,14 +410,16 @@ impl Imports {
352410
}
353411
(ExternVal::Table(table_addr), ImportKind::Table(ty)) => {
354412
let table = store.get_table(table_addr as usize)?;
355-
// TODO: do we need to check any limits?
356-
Self::compare_types(import, &table.borrow().kind.element_type, &ty.element_type)?;
413+
Self::compare_table_types(import, &table.borrow().kind, &ty)?;
357414
imports.tables.push(table_addr);
358415
}
359416
(ExternVal::Mem(memory_addr), ImportKind::Memory(ty)) => {
360417
let mem = store.get_mem(memory_addr as usize)?;
361-
// TODO: do we need to check any limits?
362-
Self::compare_types(import, &mem.borrow().kind.arch, &ty.arch)?;
418+
let (size, kind) = {
419+
let mem = mem.borrow();
420+
(mem.page_count(), mem.kind.clone())
421+
};
422+
Self::compare_memory_types(import, &kind, &ty, Some(size))?;
363423
imports.memories.push(memory_addr);
364424
}
365425
(ExternVal::Func(func_addr), ImportKind::Function(ty)) => {

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -385,7 +385,7 @@ fn exec_one(
385385

386386
let mem_idx = module.resolve_mem_addr(*addr);
387387
let mem = store.get_mem(mem_idx as usize)?;
388-
stack.values.push(mem.borrow().size().into());
388+
stack.values.push((mem.borrow().page_count() as i32).into());
389389
}
390390

391391
MemoryGrow(addr, byte) => {
@@ -398,7 +398,7 @@ fn exec_one(
398398

399399
let (res, prev_size) = {
400400
let mut mem = mem.borrow_mut();
401-
let prev_size = mem.size();
401+
let prev_size = mem.page_count() as i32;
402402
(mem.grow(stack.values.pop_t::<i32>()?), prev_size)
403403
};
404404

crates/tinywasm/src/store.rs

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -607,17 +607,15 @@ impl MemoryInstance {
607607
Ok(&self.data[addr..end])
608608
}
609609

610-
pub(crate) fn size(&self) -> i32 {
611-
log::debug!("memory pages: {}", self.page_count);
612-
log::debug!("memory size: {}", self.page_count * PAGE_SIZE);
613-
self.page_count as i32
610+
pub(crate) fn page_count(&self) -> usize {
611+
self.page_count
614612
}
615613

616614
pub(crate) fn grow(&mut self, delta: i32) -> Option<i32> {
617-
let current_pages = self.size();
618-
let new_pages = current_pages + delta;
615+
let current_pages = self.page_count();
616+
let new_pages = current_pages as i64 + delta as i64;
619617

620-
if new_pages < 0 || new_pages > MAX_PAGES as i32 {
618+
if new_pages < 0 || new_pages > MAX_PAGES as i64 {
621619
return None;
622620
}
623621

@@ -639,7 +637,7 @@ impl MemoryInstance {
639637
log::debug!("memory grown by {} pages", delta);
640638
log::debug!("memory grown to {} pages", self.page_count);
641639

642-
Some(current_pages)
640+
Some(current_pages.try_into().expect("memory size out of bounds, this should have been caught earlier"))
643641
}
644642
}
645643

0 commit comments

Comments
 (0)