Skip to content

Commit 2d4072b

Browse files
authored
Fix tables holding their registered types (#11105)
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 ed25433 commit 2d4072b

File tree

7 files changed

+118
-52
lines changed

7 files changed

+118
-52
lines changed

crates/wasmtime/src/runtime/trampoline.rs

Lines changed: 3 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -12,47 +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, false);
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-
tunables: store.engine().tunables(),
51-
})?;
52-
53-
Ok(store.add_dummy_instance(handle))
54-
}
55-
}
18+
use wasmtime_environ::{MemoryIndex, TableIndex};
5619

5720
pub fn generate_memory_export(
5821
store: &mut StoreOpaque,

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

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

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

Lines changed: 30 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> {
@@ -22,5 +26,29 @@ pub fn create_table(store: &mut StoreOpaque, table: &TableType) -> Result<Instan
2226
.exports
2327
.insert(String::new(), EntityIndex::Table(table_id));
2428

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

crates/wasmtime/src/runtime/types.rs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -536,6 +536,10 @@ impl RefType {
536536
pub(crate) fn is_vmgcref_type_and_points_to_object(&self) -> bool {
537537
self.heap_type().is_vmgcref_type_and_points_to_object()
538538
}
539+
540+
pub(crate) fn into_registered_type(self) -> Option<RegisteredType> {
541+
self.heap_type.into_registered_type()
542+
}
539543
}
540544

541545
/// The heap types that can Wasm can have references to.
@@ -1160,6 +1164,18 @@ impl HeapType {
11601164
HeapType::I31 | HeapType::NoExtern | HeapType::NoFunc | HeapType::None
11611165
)
11621166
}
1167+
1168+
pub(crate) fn into_registered_type(self) -> Option<RegisteredType> {
1169+
use HeapType::*;
1170+
match self {
1171+
ConcreteFunc(ty) => Some(ty.registered_type),
1172+
ConcreteArray(ty) => Some(ty.registered_type),
1173+
ConcreteStruct(ty) => Some(ty.registered_type),
1174+
Extern | NoExtern | Func | NoFunc | Any | Eq | I31 | Array | Struct | None => {
1175+
Option::None
1176+
}
1177+
}
1178+
}
11631179
}
11641180

11651181
// External Types

crates/wasmtime/src/runtime/vm.rs

Lines changed: 7 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ pub(crate) struct f64x2(crate::uninhabited::Uninhabited);
3535

3636
use crate::prelude::*;
3737
use crate::store::StoreOpaque;
38+
use crate::type_registry::RegisteredType;
3839
use alloc::sync::Arc;
3940
use core::fmt;
4041
use core::ops::Deref;
@@ -312,23 +313,23 @@ pub enum ModuleRuntimeInfo {
312313
#[derive(Clone)]
313314
pub struct BareModuleInfo {
314315
module: Arc<wasmtime_environ::Module>,
315-
one_signature: Option<VMSharedTypeIndex>,
316316
offsets: VMOffsets<HostPtr>,
317+
_registered_type: Option<RegisteredType>,
317318
}
318319

319320
impl ModuleRuntimeInfo {
320321
pub(crate) fn bare(module: Arc<wasmtime_environ::Module>) -> Self {
321-
ModuleRuntimeInfo::bare_maybe_imported_func(module, None)
322+
ModuleRuntimeInfo::bare_with_registered_type(module, None)
322323
}
323324

324-
pub(crate) fn bare_maybe_imported_func(
325+
pub(crate) fn bare_with_registered_type(
325326
module: Arc<wasmtime_environ::Module>,
326-
one_signature: Option<VMSharedTypeIndex>,
327+
registered_type: Option<RegisteredType>,
327328
) -> Self {
328329
ModuleRuntimeInfo::Bare(Box::new(BareModuleInfo {
329330
offsets: VMOffsets::new(HostPtr, &module),
330331
module,
331-
one_signature,
332+
_registered_type: registered_type,
332333
}))
333334
}
334335

@@ -430,10 +431,7 @@ impl ModuleRuntimeInfo {
430431
.as_module_map()
431432
.values()
432433
.as_slice(),
433-
ModuleRuntimeInfo::Bare(b) => match &b.one_signature {
434-
Some(s) => core::slice::from_ref(s),
435-
None => &[],
436-
},
434+
ModuleRuntimeInfo::Bare(_) => &[],
437435
}
438436
}
439437

tests/all/globals.rs

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -428,3 +428,35 @@ fn instantiate_global_with_subtype() -> Result<()> {
428428

429429
Ok(())
430430
}
431+
432+
#[test]
433+
fn host_globals_keep_type_registration() -> Result<()> {
434+
let engine = Engine::default();
435+
let mut store = Store::new(&engine, ());
436+
437+
let ty = FuncType::new(&engine, [], []);
438+
439+
let g = Global::new(
440+
&mut store,
441+
GlobalType::new(
442+
RefType::new(true, HeapType::ConcreteFunc(ty)).into(),
443+
Mutability::Const,
444+
),
445+
Val::FuncRef(None),
446+
)?;
447+
448+
{
449+
let _ty2 = FuncType::new(&engine, [ValType::I32], [ValType::I32]);
450+
let ty = g.ty(&store);
451+
let fty = ty.content().unwrap_ref().heap_type().unwrap_concrete_func();
452+
assert!(fty.params().len() == 0);
453+
assert!(fty.results().len() == 0);
454+
}
455+
456+
let ty = g.ty(&store);
457+
let fty = ty.content().unwrap_ref().heap_type().unwrap_concrete_func();
458+
assert!(fty.params().len() == 0);
459+
assert!(fty.results().len() == 0);
460+
461+
Ok(())
462+
}

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)