@@ -3,10 +3,11 @@ use crate::gc::ReallocScheme;
3
3
use crate :: validation:: {
4
4
Import , ImportMap , ValidatedModule , validate_adapter_module, validate_module,
5
5
} ;
6
- use anyhow:: { Context , Result } ;
6
+ use anyhow:: { Context , Result , bail } ;
7
7
use indexmap:: { IndexMap , IndexSet } ;
8
8
use std:: borrow:: Cow ;
9
9
use std:: collections:: { HashMap , HashSet } ;
10
+ use wasmparser:: { FuncType , ValType } ;
10
11
use wit_parser:: {
11
12
Function , InterfaceId , LiveTypes , Resolve , TypeDefKind , TypeId , TypeOwner , WorldId , WorldItem ,
12
13
WorldKey ,
@@ -86,17 +87,29 @@ impl<'a> ComponentWorld<'a> {
86
87
87
88
/// Given that there is no realloc function exported from the main module,
88
89
/// 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 > {
90
94
if self . encoder . module_is_produced_by_tiny_go {
91
95
// If it appears the module was emitted by TinyGo, we delegate to
92
96
// its `malloc()` function. (TinyGo assumes its GC has rein over the
93
97
// whole memory and quickly overwrites the adapter's
94
98
// `memory.grow`-allocated State struct, causing a crash. So we use
95
99
// `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
+ }
97
110
} else {
98
111
// If it's not TinyGo, use `memory.grow` instead.
99
- ReallocScheme :: MemoryGrow
112
+ Ok ( ReallocScheme :: MemoryGrow )
100
113
}
101
114
}
102
115
@@ -183,11 +196,11 @@ impl<'a> ComponentWorld<'a> {
183
196
let realloc = if self . encoder . realloc_via_memory_grow {
184
197
// User explicitly requested memory-grow-based realloc. We
185
198
// give them that unless it would definitely crash.
186
- self . fallback_realloc_scheme ( )
199
+ self . fallback_realloc_scheme ( ) ?
187
200
} else {
188
201
match self . info . exports . realloc_to_import_into_adapter ( ) {
189
202
Some ( name) => ReallocScheme :: Realloc ( name) ,
190
- None => self . fallback_realloc_scheme ( ) ,
203
+ None => self . fallback_realloc_scheme ( ) ? ,
191
204
}
192
205
} ;
193
206
Cow :: Owned (
0 commit comments