Skip to content

Commit 7a5784e

Browse files
authored
Fix tables holding their registered types (#11106)
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 721fa95 commit 7a5784e

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
@@ -7,6 +7,7 @@
77

88
use crate::prelude::*;
99
use crate::store::StoreOpaque;
10+
use crate::type_registry::RegisteredType;
1011
use alloc::sync::Arc;
1112
use core::fmt;
1213
use core::ops::Deref;
@@ -275,23 +276,23 @@ pub enum ModuleRuntimeInfo {
275276
#[derive(Clone)]
276277
pub struct BareModuleInfo {
277278
module: Arc<wasmtime_environ::Module>,
278-
one_signature: Option<VMSharedTypeIndex>,
279279
offsets: VMOffsets<HostPtr>,
280+
_registered_type: Option<RegisteredType>,
280281
}
281282

282283
impl ModuleRuntimeInfo {
283284
pub(crate) fn bare(module: Arc<wasmtime_environ::Module>) -> Self {
284-
ModuleRuntimeInfo::bare_maybe_imported_func(module, None)
285+
ModuleRuntimeInfo::bare_with_registered_type(module, None)
285286
}
286287

287-
pub(crate) fn bare_maybe_imported_func(
288+
pub(crate) fn bare_with_registered_type(
288289
module: Arc<wasmtime_environ::Module>,
289-
one_signature: Option<VMSharedTypeIndex>,
290+
registered_type: Option<RegisteredType>,
290291
) -> Self {
291292
ModuleRuntimeInfo::Bare(Box::new(BareModuleInfo {
292293
offsets: VMOffsets::new(HostPtr, &module),
293294
module,
294-
one_signature,
295+
_registered_type: registered_type,
295296
}))
296297
}
297298

@@ -393,10 +394,7 @@ impl ModuleRuntimeInfo {
393394
.as_module_map()
394395
.values()
395396
.as_slice(),
396-
ModuleRuntimeInfo::Bare(b) => match &b.one_signature {
397-
Some(s) => core::slice::from_ref(s),
398-
None => &[],
399-
},
397+
ModuleRuntimeInfo::Bare(_) => &[],
400398
}
401399
}
402400

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)