Skip to content

Commit 0986d4b

Browse files
committed
Complain if a TinyGo module has a missing or malformed malloc().
In this case, we have no non-crashing way of allocating memory for the adapter state.
1 parent 5007939 commit 0986d4b

File tree

2 files changed

+25
-6
lines changed

2 files changed

+25
-6
lines changed

crates/wit-component/src/encoding/world.rs

Lines changed: 19 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,11 @@ use crate::gc::ReallocScheme;
33
use crate::validation::{
44
Import, ImportMap, ValidatedModule, validate_adapter_module, validate_module,
55
};
6-
use anyhow::{Context, Result};
6+
use anyhow::{Context, Result, bail};
77
use indexmap::{IndexMap, IndexSet};
88
use std::borrow::Cow;
99
use std::collections::{HashMap, HashSet};
10+
use wasmparser::{FuncType, ValType};
1011
use wit_parser::{
1112
Function, InterfaceId, LiveTypes, Resolve, TypeDefKind, TypeId, TypeOwner, WorldId, WorldItem,
1213
WorldKey,
@@ -86,17 +87,29 @@ impl<'a> ComponentWorld<'a> {
8687

8788
/// Given that there is no realloc function exported from the main module,
8889
/// returns the realloc scheme we should use.
89-
fn fallback_realloc_scheme(&self) -> ReallocScheme {
90+
///
91+
/// Return an error if we need to use an exported malloc() and it wasn't
92+
/// there.
93+
fn fallback_realloc_scheme(&self) -> Result<ReallocScheme> {
9094
if self.encoder.module_is_produced_by_tiny_go {
9195
// If it appears the module was emitted by TinyGo, we delegate to
9296
// its `malloc()` function. (TinyGo assumes its GC has rein over the
9397
// whole memory and quickly overwrites the adapter's
9498
// `memory.grow`-allocated State struct, causing a crash. So we use
9599
// `malloc()` to inform TinyGo's GC of the memory we use.)
96-
ReallocScheme::Malloc("malloc")
100+
let malloc_type = FuncType::new([ValType::I32], [ValType::I32]);
101+
match self.info.exports.get_func_type("malloc") {
102+
Some(func_type) if *func_type == malloc_type => Ok(ReallocScheme::Malloc("malloc")),
103+
Some(_) => bail!(
104+
"TinyGo-derived wasm had a malloc() export, but it lacked the expected type of malloc(i32) -> i32"
105+
),
106+
None => bail!(
107+
"TinyGo-derived wasm lacked a malloc() export; we don't know how else to reserve space for the adapter's state from its GC"
108+
),
109+
}
97110
} else {
98111
// If it's not TinyGo, use `memory.grow` instead.
99-
ReallocScheme::MemoryGrow
112+
Ok(ReallocScheme::MemoryGrow)
100113
}
101114
}
102115

@@ -183,11 +196,11 @@ impl<'a> ComponentWorld<'a> {
183196
let realloc = if self.encoder.realloc_via_memory_grow {
184197
// User explicitly requested memory-grow-based realloc. We
185198
// give them that unless it would definitely crash.
186-
self.fallback_realloc_scheme()
199+
self.fallback_realloc_scheme()?
187200
} else {
188201
match self.info.exports.realloc_to_import_into_adapter() {
189202
Some(name) => ReallocScheme::Realloc(name),
190-
None => self.fallback_realloc_scheme(),
203+
None => self.fallback_realloc_scheme()?,
191204
}
192205
};
193206
Cow::Owned(

crates/wit-component/src/validation.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1103,6 +1103,12 @@ impl ExportMap {
11031103
Ok(())
11041104
}
11051105

1106+
/// Returns the type of the given exported function, None if an exported
1107+
/// function of that name does not exist.
1108+
pub(crate) fn get_func_type<'a>(&'a self, name: &str) -> Option<&'a FuncType> {
1109+
self.raw_exports.get(name)
1110+
}
1111+
11061112
fn classify(
11071113
&mut self,
11081114
export: wasmparser::Export<'_>,

0 commit comments

Comments
 (0)