Skip to content

Commit 97547d6

Browse files
authored
Fix cross-component-instance streams being flagged as intra-instance (#14018)
* Fix cross-component-instance streams being flagged as intra-instance The comparison key before this commit was `RuntimeComponentInstanceIndex` which is a component-local index and can't be compared across component instance. The fix is to use `RuntimeInstance` which has the store-local component instance id plus the `RuntimeComponentInstanceIndex` within that instance. * Fix compile
1 parent 9bdbd42 commit 97547d6

3 files changed

Lines changed: 137 additions & 15 deletions

File tree

crates/wasmtime/src/runtime/component/concurrent/futures_and_streams.rs

Lines changed: 11 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,8 @@ use crate::component::matching::InstanceType;
66
use crate::component::types;
77
use crate::component::values::ErrorContextAny;
88
use crate::component::{
9-
AsAccessor, ComponentInstanceId, ComponentType, FutureAny, Instance, Lift, Lower, StreamAny,
10-
Val, WasmList,
9+
AsAccessor, ComponentInstanceId, ComponentType, FutureAny, Instance, Lift, Lower,
10+
RuntimeInstance, StreamAny, Val, WasmList,
1111
};
1212
use crate::prelude::*;
1313
use crate::store::{StoreOpaque, StoreToken};
@@ -3265,20 +3265,20 @@ impl Instance {
32653265
fn copy<T: 'static>(
32663266
store: StoreContextMut<T>,
32673267
flat_abi: Option<FlatAbi>,
3268-
write_instance: Instance,
3269-
write_caller_instance: RuntimeComponentInstanceIndex,
3268+
write_runtime_instance: RuntimeInstance,
32703269
write_ty: TransmitIndex,
32713270
write_options: OptionsIndex,
32723271
write_address: usize,
3273-
read_instance: Instance,
3274-
read_caller_instance: RuntimeComponentInstanceIndex,
3272+
read_runtime_instance: RuntimeInstance,
32753273
read_caller_thread: QualifiedThreadId,
32763274
read_ty: TransmitIndex,
32773275
read_options: OptionsIndex,
32783276
read_address: usize,
32793277
count: ItemCount,
32803278
rep: u32,
32813279
) -> Result<()> {
3280+
let write_instance = Instance::from_runtime_instance(store.0, write_runtime_instance);
3281+
let read_instance = Instance::from_runtime_instance(store.0, read_runtime_instance);
32823282
let (write_component, store) = write_instance.component_and_store_mut(store.0);
32833283
let (read_component, mut store) = read_instance.component_and_store_mut(store);
32843284
let write_types = write_component.types();
@@ -3327,7 +3327,7 @@ impl Instance {
33273327
.ok_or_else(|| crate::format_err!("read pointer out of bounds"))?;
33283328
}
33293329

3330-
if write_caller_instance == read_caller_instance
3330+
if write_runtime_instance == read_runtime_instance
33313331
&& !allow_intra_component_read_write(write_payload_ty)
33323332
{
33333333
bail!(
@@ -3610,13 +3610,11 @@ impl Instance {
36103610
Instance::copy(
36113611
store.as_context_mut(),
36123612
flat_abi,
3613-
self,
3614-
caller,
3613+
self.runtime_instance(caller),
36153614
ty,
36163615
options,
36173616
address,
3618-
read_instance,
3619-
read_caller_instance,
3617+
read_instance.runtime_instance(read_caller_instance),
36203618
read_caller_thread,
36213619
read_ty,
36223620
read_options,
@@ -3848,13 +3846,11 @@ impl Instance {
38483846
Instance::copy(
38493847
store.as_context_mut(),
38503848
flat_abi,
3851-
write_instance,
3852-
write_caller,
3849+
write_instance.runtime_instance(write_caller),
38533850
write_ty,
38543851
write_options,
38553852
write_address,
3856-
self,
3857-
caller_instance,
3853+
self.runtime_instance(caller_instance),
38583854
caller_thread,
38593855
ty,
38603856
options,

crates/wasmtime/src/runtime/component/instance.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -572,6 +572,12 @@ impl Instance {
572572
index,
573573
}
574574
}
575+
576+
#[cfg(feature = "component-model-async")]
577+
pub(crate) fn from_runtime_instance(store: &StoreOpaque, instance: RuntimeInstance) -> Self {
578+
let id = StoreComponentInstanceId::new(store.id(), instance.instance);
579+
Instance { id }
580+
}
575581
}
576582

577583
/// Translates a `CoreDef`, a definition of a core wasm item, to an

tests/all/component_model/async.rs

Lines changed: 120 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1062,3 +1062,123 @@ async fn async_call_stack() -> Result<()> {
10621062
.await??;
10631063
Ok(())
10641064
}
1065+
1066+
#[test]
1067+
#[cfg_attr(miri, ignore)]
1068+
fn inter_component_stream_is_not_intra_component() -> Result<()> {
1069+
let engine = Engine::default();
1070+
1071+
let writer = Component::new(
1072+
&engine,
1073+
r#"
1074+
(component
1075+
(core module $libc
1076+
(memory (export "m") 1)
1077+
(data (i32.const 0x100) "hello")
1078+
)
1079+
(core instance $libc (instantiate $libc))
1080+
1081+
(type $s (stream string))
1082+
(core func $stream.new (canon stream.new $s))
1083+
(core func $stream.write (canon stream.write $s async (memory (core memory $libc "m"))))
1084+
1085+
(core module $m
1086+
(import "" "m" (memory 1))
1087+
(import "" "stream.new" (func $stream.new (result i64)))
1088+
(import "" "stream.write" (func $stream.write (param i32 i32 i32) (result i32)))
1089+
1090+
(global $w (mut i32) (i32.const 0))
1091+
1092+
(func (export "mk") (result i32)
1093+
(local $tmp i64)
1094+
(local.set $tmp (call $stream.new))
1095+
(global.set $w (i32.wrap_i64 (i64.shr_u (local.get $tmp) (i64.const 32))))
1096+
(i32.wrap_i64 (local.get $tmp))
1097+
)
1098+
1099+
(func (export "write")
1100+
;; store ptr/len at 0x10
1101+
(i32.store (i32.const 0x10) (i32.const 0x100))
1102+
(i32.store (i32.const 0x14) (i32.const 5))
1103+
1104+
(call $stream.write (global.get $w) (i32.const 0x10) (i32.const 1))
1105+
i32.const -1 ;; BLOCKED
1106+
i32.ne
1107+
if unreachable end
1108+
)
1109+
)
1110+
1111+
(core instance $i (instantiate $m
1112+
(with "" (instance
1113+
(export "m" (memory $libc "m"))
1114+
(export "stream.new" (func $stream.new))
1115+
(export "stream.write" (func $stream.write))
1116+
))
1117+
))
1118+
1119+
(func (export "mk") (result $s) (canon lift (core func $i "mk")))
1120+
(func (export "write") (canon lift (core func $i "write")))
1121+
)
1122+
"#,
1123+
)?;
1124+
1125+
let reader = Component::new(
1126+
&engine,
1127+
r#"
1128+
(component
1129+
(core module $libc
1130+
(memory (export "m") 1)
1131+
(func (export "realloc") (param i32 i32 i32 i32) (result i32)
1132+
(i32.const 0x200)
1133+
)
1134+
)
1135+
(core instance $libc (instantiate $libc))
1136+
1137+
(type $s (stream string))
1138+
(core func $stream.read
1139+
(canon stream.read $s async
1140+
(memory (core memory $libc "m"))
1141+
(realloc (core func $libc "realloc"))))
1142+
1143+
(core module $m
1144+
(import "" "m" (memory 1))
1145+
(import "" "stream.read" (func $stream.read (param i32 i32 i32) (result i32)))
1146+
1147+
(func (export "read") (param $r i32) (result i32)
1148+
(call $stream.read (local.get $r) (i32.const 0x10) (i32.const 1))
1149+
i32.const 0x10 ;; COMPLETED | (1 << 4)
1150+
i32.ne
1151+
if unreachable end
1152+
1153+
i32.const 0x10
1154+
)
1155+
)
1156+
1157+
(core instance $i (instantiate $m
1158+
(with "" (instance
1159+
(export "m" (memory $libc "m"))
1160+
(export "stream.read" (func $stream.read))
1161+
))
1162+
))
1163+
1164+
(func (export "read") (param "s" $s) (result string)
1165+
(canon lift (core func $i "read") (memory (core memory $libc "m"))))
1166+
)
1167+
"#,
1168+
)?;
1169+
1170+
let linker = Linker::new(&engine);
1171+
let mut store = Store::new(&engine, ());
1172+
let writer = linker.instantiate(&mut store, &writer)?;
1173+
let reader = linker.instantiate(&mut store, &reader)?;
1174+
1175+
let mk = writer.get_typed_func::<(), (StreamReader<String>,)>(&mut store, "mk")?;
1176+
let write = writer.get_typed_func::<(), ()>(&mut store, "write")?;
1177+
let read = reader.get_typed_func::<(StreamReader<String>,), (String,)>(&mut store, "read")?;
1178+
1179+
let (stream,) = mk.call(&mut store, ())?;
1180+
write.call(&mut store, ())?;
1181+
assert_eq!(read.call(&mut store, (stream,))?, ("hello".to_string(),));
1182+
1183+
Ok(())
1184+
}

0 commit comments

Comments
 (0)