Skip to content

Commit 35e2c88

Browse files
authored
Fix tables holding their registered types (#11107)
This commit fixes an issue where host-created tables with concrete reference types previously did not keep their associated type registrations alive for the duration of the table itself. This could lead to runtime panics when reflecting on their type and additionally lead to some type confusion about the table itself. As described in #11102 this is not a security issue, just a bug that needs fixing. Closes #11102
1 parent e7198a3 commit 35e2c88

File tree

7 files changed

+117
-51
lines changed

7 files changed

+117
-51
lines changed

crates/wasmtime/src/runtime/trampoline.rs

Lines changed: 3 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -12,46 +12,10 @@ pub(crate) use memory::MemoryCreatorProxy;
1212
use self::memory::create_memory;
1313
use self::table::create_table;
1414
use crate::prelude::*;
15-
use crate::runtime::vm::{
16-
Imports, InstanceAllocationRequest, InstanceAllocator, ModuleRuntimeInfo,
17-
OnDemandInstanceAllocator, SharedMemory, StorePtr, VMFunctionImport,
18-
};
19-
use crate::store::{InstanceId, StoreOpaque};
15+
use crate::runtime::vm::SharedMemory;
16+
use crate::store::StoreOpaque;
2017
use crate::{MemoryType, TableType};
21-
use alloc::sync::Arc;
22-
use core::any::Any;
23-
use wasmtime_environ::{MemoryIndex, Module, TableIndex, VMSharedTypeIndex};
24-
25-
fn create_handle(
26-
module: Module,
27-
store: &mut StoreOpaque,
28-
host_state: Box<dyn Any + Send + Sync>,
29-
func_imports: &[VMFunctionImport],
30-
one_signature: Option<VMSharedTypeIndex>,
31-
) -> Result<InstanceId> {
32-
let mut imports = Imports::default();
33-
imports.functions = func_imports;
34-
35-
unsafe {
36-
let config = store.engine().config();
37-
// Use the on-demand allocator when creating handles associated with host objects
38-
// The configured instance allocator should only be used when creating module instances
39-
// as we don't want host objects to count towards instance limits.
40-
let module = Arc::new(module);
41-
let runtime_info = &ModuleRuntimeInfo::bare_maybe_imported_func(module, one_signature);
42-
let allocator = OnDemandInstanceAllocator::new(config.mem_creator.clone(), 0);
43-
let handle = allocator.allocate_module(InstanceAllocationRequest {
44-
imports,
45-
host_state,
46-
store: StorePtr::new(store.traitobj()),
47-
runtime_info,
48-
wmemcheck: false,
49-
pkey: None,
50-
})?;
51-
52-
Ok(store.add_dummy_instance(handle))
53-
}
54-
}
18+
use wasmtime_environ::{MemoryIndex, TableIndex};
5519

5620
pub fn generate_memory_export(
5721
store: &mut StoreOpaque,

crates/wasmtime/src/runtime/trampoline/memory.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ pub fn create_memory(
5454
// associated with external objects. The configured instance allocator
5555
// should only be used when creating module instances as we don't want host
5656
// objects to count towards instance limits.
57-
let runtime_info = &ModuleRuntimeInfo::bare_maybe_imported_func(Arc::new(module), None);
57+
let runtime_info = &ModuleRuntimeInfo::bare(Arc::new(module));
5858
let host_state = Box::new(());
5959
let imports = Imports::default();
6060
let request = InstanceAllocationRequest {

crates/wasmtime/src/runtime/trampoline/table.rs

Lines changed: 29 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,11 @@
11
use crate::prelude::*;
2+
use crate::runtime::vm::{
3+
Imports, InstanceAllocationRequest, InstanceAllocator, ModuleRuntimeInfo,
4+
OnDemandInstanceAllocator, StorePtr,
5+
};
26
use crate::store::{InstanceId, StoreOpaque};
3-
use crate::trampoline::create_handle;
47
use crate::TableType;
8+
use alloc::sync::Arc;
59
use wasmtime_environ::{EntityIndex, Module, TypeTrace};
610

711
pub fn create_table(store: &mut StoreOpaque, table: &TableType) -> Result<InstanceId> {
@@ -24,5 +28,28 @@ pub fn create_table(store: &mut StoreOpaque, table: &TableType) -> Result<Instan
2428
.exports
2529
.insert(String::new(), EntityIndex::Table(table_id));
2630

27-
create_handle(module, store, Box::new(()), &[], None)
31+
let imports = Imports::default();
32+
33+
unsafe {
34+
let config = store.engine().config();
35+
// Use the on-demand allocator when creating handles associated with host objects
36+
// The configured instance allocator should only be used when creating module instances
37+
// as we don't want host objects to count towards instance limits.
38+
let module = Arc::new(module);
39+
let runtime_info = &ModuleRuntimeInfo::bare_with_registered_type(
40+
module,
41+
table.element().clone().into_registered_type(),
42+
);
43+
let allocator = OnDemandInstanceAllocator::new(config.mem_creator.clone(), 0);
44+
let handle = allocator.allocate_module(InstanceAllocationRequest {
45+
imports,
46+
host_state: Box::new(()),
47+
store: StorePtr::new(store.traitobj()),
48+
runtime_info,
49+
wmemcheck: false,
50+
pkey: None,
51+
})?;
52+
53+
Ok(store.add_dummy_instance(handle))
54+
}
2855
}

crates/wasmtime/src/runtime/types.rs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -497,6 +497,10 @@ impl RefType {
497497
pub(crate) fn is_vmgcref_type_and_points_to_object(&self) -> bool {
498498
self.heap_type().is_vmgcref_type_and_points_to_object()
499499
}
500+
501+
pub(crate) fn into_registered_type(self) -> Option<RegisteredType> {
502+
self.heap_type.into_registered_type()
503+
}
500504
}
501505

502506
/// The heap types that can Wasm can have references to.
@@ -1119,6 +1123,18 @@ impl HeapType {
11191123
HeapType::I31 | HeapType::NoExtern | HeapType::NoFunc | HeapType::None
11201124
)
11211125
}
1126+
1127+
pub(crate) fn into_registered_type(self) -> Option<RegisteredType> {
1128+
use HeapType::*;
1129+
match self {
1130+
ConcreteFunc(ty) => Some(ty.registered_type),
1131+
ConcreteArray(ty) => Some(ty.registered_type),
1132+
ConcreteStruct(ty) => Some(ty.registered_type),
1133+
Extern | NoExtern | Func | NoFunc | Any | Eq | I31 | Array | Struct | None => {
1134+
Option::None
1135+
}
1136+
}
1137+
}
11221138
}
11231139

11241140
// External Types

crates/wasmtime/src/runtime/vm.rs

Lines changed: 7 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
#![warn(clippy::cast_sign_loss)]
55

66
use crate::prelude::*;
7+
use crate::type_registry::RegisteredType;
78
use alloc::sync::Arc;
89
use core::fmt;
910
use core::mem;
@@ -196,23 +197,23 @@ pub enum ModuleRuntimeInfo {
196197
#[derive(Clone)]
197198
pub struct BareModuleInfo {
198199
module: Arc<wasmtime_environ::Module>,
199-
one_signature: Option<VMSharedTypeIndex>,
200200
offsets: VMOffsets<HostPtr>,
201+
_registered_type: Option<RegisteredType>,
201202
}
202203

203204
impl ModuleRuntimeInfo {
204205
pub(crate) fn bare(module: Arc<wasmtime_environ::Module>) -> Self {
205-
ModuleRuntimeInfo::bare_maybe_imported_func(module, None)
206+
ModuleRuntimeInfo::bare_with_registered_type(module, None)
206207
}
207208

208-
pub(crate) fn bare_maybe_imported_func(
209+
pub(crate) fn bare_with_registered_type(
209210
module: Arc<wasmtime_environ::Module>,
210-
one_signature: Option<VMSharedTypeIndex>,
211+
registered_type: Option<RegisteredType>,
211212
) -> Self {
212213
ModuleRuntimeInfo::Bare(Box::new(BareModuleInfo {
213214
offsets: VMOffsets::new(HostPtr, &module),
214215
module,
215-
one_signature,
216+
_registered_type: registered_type,
216217
}))
217218
}
218219

@@ -312,10 +313,7 @@ impl ModuleRuntimeInfo {
312313
.as_module_map()
313314
.values()
314315
.as_slice(),
315-
ModuleRuntimeInfo::Bare(b) => match &b.one_signature {
316-
Some(s) => core::slice::from_ref(s),
317-
None => &[],
318-
},
316+
ModuleRuntimeInfo::Bare(_) => &[],
319317
}
320318
}
321319

tests/all/globals.rs

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -350,3 +350,35 @@ fn i31ref_as_anyref_global_ty() -> Result<()> {
350350
}
351351
Ok(())
352352
}
353+
354+
#[test]
355+
fn host_globals_keep_type_registration() -> Result<()> {
356+
let engine = Engine::default();
357+
let mut store = Store::new(&engine, ());
358+
359+
let ty = FuncType::new(&engine, [], []);
360+
361+
let g = Global::new(
362+
&mut store,
363+
GlobalType::new(
364+
RefType::new(true, HeapType::ConcreteFunc(ty)).into(),
365+
Mutability::Const,
366+
),
367+
Val::FuncRef(None),
368+
)?;
369+
370+
{
371+
let _ty2 = FuncType::new(&engine, [ValType::I32], [ValType::I32]);
372+
let ty = g.ty(&store);
373+
let fty = ty.content().unwrap_ref().heap_type().unwrap_concrete_func();
374+
assert!(fty.params().len() == 0);
375+
assert!(fty.results().len() == 0);
376+
}
377+
378+
let ty = g.ty(&store);
379+
let fty = ty.content().unwrap_ref().heap_type().unwrap_concrete_func();
380+
assert!(fty.params().len() == 0);
381+
assert!(fty.results().len() == 0);
382+
383+
Ok(())
384+
}

tests/all/table.rs

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -337,3 +337,32 @@ fn i31ref_table_copy() -> Result<()> {
337337

338338
Ok(())
339339
}
340+
341+
#[test]
342+
fn host_table_keep_type_registration() -> Result<()> {
343+
let engine = Engine::default();
344+
let mut store = Store::new(&engine, ());
345+
346+
let ty = FuncType::new(&engine, [], []);
347+
348+
let t = Table::new(
349+
&mut store,
350+
TableType::new(RefType::new(true, HeapType::ConcreteFunc(ty)), 1, None),
351+
Ref::Func(None),
352+
)?;
353+
354+
{
355+
let _ty2 = FuncType::new(&engine, [ValType::I32], [ValType::I32]);
356+
let ty = t.ty(&store);
357+
let fty = ty.element().heap_type().unwrap_concrete_func();
358+
assert!(fty.params().len() == 0);
359+
assert!(fty.results().len() == 0);
360+
}
361+
362+
let ty = t.ty(&store);
363+
let fty = ty.element().heap_type().unwrap_concrete_func();
364+
assert!(fty.params().len() == 0);
365+
assert!(fty.results().len() == 0);
366+
367+
Ok(())
368+
}

0 commit comments

Comments
 (0)