Skip to content

Commit 0f457fa

Browse files
authored
Raise unsafe_op_in_unsafe_fn further in Wasmtime (#11322)
* Raise `unsafe_op_in_unsafe_fn` further in Wasmtime Now it's at `wasmtime::runtime`, not just `wasmtime::runtime::vm`. * Review comments
1 parent 88079b4 commit 0f457fa

File tree

20 files changed

+410
-184
lines changed

20 files changed

+410
-184
lines changed

crates/wasmtime/src/runtime.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,10 @@
2525
// explanation of why truncation shouldn't be happening at runtime. This
2626
// situation should be pretty rare though.
2727
#![warn(clippy::cast_possible_truncation)]
28+
#![warn(
29+
unsafe_op_in_unsafe_fn,
30+
reason = "opt-in until the crate opts-in as a whole -- #11180"
31+
)]
2832

2933
#[macro_use]
3034
pub(crate) mod func;

crates/wasmtime/src/runtime/code_memory.rs

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -394,12 +394,14 @@ impl CodeMemory {
394394
{
395395
let text = self.text();
396396
let unwind_info = &self.mmap[self.unwind.clone()];
397-
let registration = crate::runtime::vm::UnwindRegistration::new(
398-
text.as_ptr(),
399-
unwind_info.as_ptr(),
400-
unwind_info.len(),
401-
)
402-
.context("failed to create unwind info registration")?;
397+
let registration = unsafe {
398+
crate::runtime::vm::UnwindRegistration::new(
399+
text.as_ptr(),
400+
unwind_info.as_ptr(),
401+
unwind_info.len(),
402+
)
403+
.context("failed to create unwind info registration")?
404+
};
403405
self.unwind_registration = Some(registration);
404406
return Ok(());
405407
}

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

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -223,7 +223,9 @@ impl Component {
223223
/// lives for as long as the module and is nevery externally modified for
224224
/// the lifetime of the deserialized module.
225225
pub unsafe fn deserialize_raw(engine: &Engine, memory: NonNull<[u8]>) -> Result<Component> {
226-
let code = engine.load_code_raw(memory, ObjectKind::Component)?;
226+
// SAFETY: the contract required by `load_code_raw` is the same as this
227+
// function.
228+
let code = unsafe { engine.load_code_raw(memory, ObjectKind::Component)? };
227229
Component::from_parts(engine, code, None)
228230
}
229231

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

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
#![deny(unsafe_op_in_unsafe_fn)]
2-
31
//! Runtime support for the Component Model Async ABI.
42
//!
53
//! This module and its submodules provide host runtime support for Component

crates/wasmtime/src/runtime/component/func/host.rs

Lines changed: 72 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -255,19 +255,21 @@ where
255255
Params: Lift,
256256
Return: Lower + 'static,
257257
{
258-
let options = Options::new(
259-
store.0.store_opaque().id(),
260-
NonNull::new(memory),
261-
NonNull::new(realloc),
262-
string_encoding,
263-
async_,
264-
None,
265-
);
258+
let options = unsafe {
259+
Options::new(
260+
store.0.store_opaque().id(),
261+
NonNull::new(memory),
262+
NonNull::new(realloc),
263+
string_encoding,
264+
async_,
265+
None,
266+
)
267+
};
266268

267269
// Perform a dynamic check that this instance can indeed be left. Exiting
268270
// the component is disallowed, for example, when the `realloc` function
269271
// calls a canonical import.
270-
if !flags.may_leave() {
272+
if unsafe { !flags.may_leave() } {
271273
bail!("cannot leave component instance");
272274
}
273275

@@ -279,7 +281,7 @@ where
279281
if async_ {
280282
#[cfg(feature = "component-model-async")]
281283
{
282-
let mut storage = Storage::<'_, Params, u32>::new_async::<Return>(storage);
284+
let mut storage = unsafe { Storage::<'_, Params, u32>::new_async::<Return>(storage) };
283285

284286
// Lift the parameters, either from flat storage or from linear
285287
// memory.
@@ -309,10 +311,14 @@ where
309311
let mut lower_result = {
310312
let types = types.clone();
311313
move |store: StoreContextMut<T>, instance: Instance, ret: Return| {
312-
flags.set_may_leave(false);
314+
unsafe {
315+
flags.set_may_leave(false);
316+
}
313317
let mut lower = LowerContext::new(store, &options, &types, instance);
314318
ret.linear_lower_to_memory(&mut lower, result_tys, retptr)?;
315-
flags.set_may_leave(true);
319+
unsafe {
320+
flags.set_may_leave(true);
321+
}
316322
lower.exit_call()?;
317323
Ok(())
318324
}
@@ -349,7 +355,7 @@ where
349355
);
350356
}
351357
} else {
352-
let mut storage = Storage::<'_, Params, Return>::new_sync(storage);
358+
let mut storage = unsafe { Storage::<'_, Params, Return>::new_sync(storage) };
353359
let mut lift = LiftContext::new(store.0.store_opaque_mut(), &options, instance);
354360
lift.enter_call();
355361
let params = storage.lift_params(&mut lift, param_tys)?;
@@ -362,10 +368,14 @@ where
362368
}
363369
};
364370

365-
flags.set_may_leave(false);
371+
unsafe {
372+
flags.set_may_leave(false);
373+
}
366374
let mut lower = LowerContext::new(store, &options, &types, instance);
367375
storage.lower_results(&mut lower, result_tys, ret)?;
368-
flags.set_may_leave(true);
376+
unsafe {
377+
flags.set_may_leave(true);
378+
}
369379
lower.exit_call()?;
370380
}
371381

@@ -691,17 +701,19 @@ unsafe fn call_host_and_handle_result<T>(
691701
where
692702
T: 'static,
693703
{
694-
let cx = VMComponentContext::from_opaque(cx);
695-
ComponentInstance::from_vmctx(cx, |store, instance| {
696-
let mut store = store.unchecked_context_mut();
697-
698-
crate::runtime::vm::catch_unwind_and_record_trap(|| {
699-
store.0.call_hook(CallHook::CallingHost)?;
700-
let res = func(store.as_context_mut(), instance);
701-
store.0.call_hook(CallHook::ReturningFromHost)?;
702-
res
704+
let cx = unsafe { VMComponentContext::from_opaque(cx) };
705+
unsafe {
706+
ComponentInstance::from_vmctx(cx, |store, instance| {
707+
let mut store = store.unchecked_context_mut();
708+
709+
crate::runtime::vm::catch_unwind_and_record_trap(|| {
710+
store.0.call_hook(CallHook::CallingHost)?;
711+
let res = func(store.as_context_mut(), instance);
712+
store.0.call_hook(CallHook::ReturningFromHost)?;
713+
res
714+
})
703715
})
704-
})
716+
}
705717
}
706718

707719
unsafe fn call_host_dynamic<T, F>(
@@ -729,19 +741,21 @@ where
729741
+ 'static,
730742
T: 'static,
731743
{
732-
let options = Options::new(
733-
store.0.store_opaque().id(),
734-
NonNull::new(memory),
735-
NonNull::new(realloc),
736-
string_encoding,
737-
async_,
738-
None,
739-
);
744+
let options = unsafe {
745+
Options::new(
746+
store.0.store_opaque().id(),
747+
NonNull::new(memory),
748+
NonNull::new(realloc),
749+
string_encoding,
750+
async_,
751+
None,
752+
)
753+
};
740754

741755
// Perform a dynamic check that this instance can indeed be left. Exiting
742756
// the component is disallowed, for example, when the `realloc` function
743757
// calls a canonical import.
744-
if !flags.may_leave() {
758+
if unsafe { !flags.may_leave() } {
745759
bail!("cannot leave component instance");
746760
}
747761

@@ -759,14 +773,16 @@ where
759773
MAX_FLAT_PARAMS
760774
};
761775

762-
let ret_index = dynamic_params_load(
763-
&mut lift,
764-
&types,
765-
storage,
766-
param_tys,
767-
&mut params_and_results,
768-
max_flat,
769-
)?;
776+
let ret_index = unsafe {
777+
dynamic_params_load(
778+
&mut lift,
779+
&types,
780+
storage,
781+
param_tys,
782+
&mut params_and_results,
783+
max_flat,
784+
)?
785+
};
770786
let result_start = params_and_results.len();
771787
for _ in 0..result_tys.types.len() {
772788
params_and_results.push(Val::Bool(false));
@@ -778,7 +794,7 @@ where
778794
let retptr = if result_tys.types.len() == 0 {
779795
0
780796
} else {
781-
let retptr = storage[ret_index].assume_init();
797+
let retptr = unsafe { storage[ret_index].assume_init() };
782798
let mut lower =
783799
LowerContext::new(store.as_context_mut(), &options, &types, instance);
784800
validate_inbounds_dynamic(&result_tys.abi, lower.as_slice_mut(), &retptr)?
@@ -799,7 +815,9 @@ where
799815
let result_vals = &result_vals[result_start..];
800816
assert_eq!(result_vals.len(), result_tys.types.len());
801817

802-
flags.set_may_leave(false);
818+
unsafe {
819+
flags.set_may_leave(false);
820+
}
803821

804822
let mut lower = LowerContext::new(store, &options, &types, instance);
805823
let mut ptr = retptr;
@@ -808,7 +826,9 @@ where
808826
val.store(&mut lower, *ty, offset)?;
809827
}
810828

811-
flags.set_may_leave(true);
829+
unsafe {
830+
flags.set_may_leave(true);
831+
}
812832

813833
lower.exit_call()?;
814834

@@ -842,7 +862,9 @@ where
842862
instance.poll_and_block(store.0.traitobj_mut(), future, caller_instance)?;
843863
let result_vals = &result_vals[result_start..];
844864

845-
flags.set_may_leave(false);
865+
unsafe {
866+
flags.set_may_leave(false);
867+
}
846868

847869
let mut cx = LowerContext::new(store, &options, &types, instance);
848870
if let Some(cnt) = result_tys.abi.flat_count(MAX_FLAT_RESULTS) {
@@ -852,15 +874,17 @@ where
852874
}
853875
assert!(dst.next().is_none());
854876
} else {
855-
let ret_ptr = storage[ret_index].assume_init_ref();
877+
let ret_ptr = unsafe { storage[ret_index].assume_init_ref() };
856878
let mut ptr = validate_inbounds_dynamic(&result_tys.abi, cx.as_slice_mut(), ret_ptr)?;
857879
for (val, ty) in result_vals.iter().zip(result_tys.types.iter()) {
858880
let offset = types.canonical_abi(ty).next_field32_size(&mut ptr);
859881
val.store(&mut cx, *ty, offset)?;
860882
}
861883
}
862884

863-
flags.set_may_leave(true);
885+
unsafe {
886+
flags.set_may_leave(true);
887+
}
864888

865889
cx.exit_call()?;
866890
}

crates/wasmtime/src/runtime/component/func/typed.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2404,8 +2404,8 @@ pub unsafe fn lower_payload<P, T>(
24042404
let typed = typed_payload(payload);
24052405
lower(typed)?;
24062406

2407-
let typed_len = storage_as_slice(typed).len();
2408-
let payload = storage_as_slice_mut(payload);
2407+
let typed_len = unsafe { storage_as_slice(typed).len() };
2408+
let payload = unsafe { storage_as_slice_mut(payload) };
24092409
for slot in payload[typed_len..].iter_mut() {
24102410
slot.write(ValRaw::u64(0));
24112411
}

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

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -12,20 +12,24 @@ fn assert_raw_slice_compat<T>() {
1212
pub unsafe fn storage_as_slice<T>(storage: &T) -> &[ValRaw] {
1313
assert_raw_slice_compat::<T>();
1414

15-
slice::from_raw_parts(
16-
(storage as *const T).cast(),
17-
mem::size_of_val(storage) / mem::size_of::<ValRaw>(),
18-
)
15+
unsafe {
16+
slice::from_raw_parts(
17+
(storage as *const T).cast(),
18+
mem::size_of_val(storage) / mem::size_of::<ValRaw>(),
19+
)
20+
}
1921
}
2022

2123
/// Same as `storage_as_slice`, but mutable.
2224
pub unsafe fn storage_as_slice_mut<T>(storage: &mut MaybeUninit<T>) -> &mut [MaybeUninit<ValRaw>] {
2325
assert_raw_slice_compat::<T>();
2426

25-
slice::from_raw_parts_mut(
26-
(storage as *mut MaybeUninit<T>).cast(),
27-
mem::size_of_val(storage) / mem::size_of::<ValRaw>(),
28-
)
27+
unsafe {
28+
slice::from_raw_parts_mut(
29+
(storage as *mut MaybeUninit<T>).cast(),
30+
mem::size_of_val(storage) / mem::size_of::<ValRaw>(),
31+
)
32+
}
2933
}
3034

3135
/// Same as `storage_as_slice`, but in reverse and mutable.
@@ -44,7 +48,7 @@ pub unsafe fn slice_to_storage_mut<T>(slice: &mut [MaybeUninit<ValRaw>]) -> &mut
4448
mem::size_of_val(slice)
4549
);
4650

47-
&mut *slice.as_mut_ptr().cast()
51+
unsafe { &mut *slice.as_mut_ptr().cast() }
4852
}
4953

5054
/// Same as `storage_as_slice`, but in reverse
@@ -61,5 +65,5 @@ pub unsafe fn slice_to_storage<T>(slice: &[ValRaw]) -> &T {
6165
mem::size_of_val(slice)
6266
);
6367

64-
&*slice.as_ptr().cast()
68+
unsafe { &*slice.as_ptr().cast() }
6569
}

crates/wasmtime/src/runtime/fiber.rs

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
#![deny(unsafe_op_in_unsafe_fn)]
2-
31
use crate::prelude::*;
42
use crate::store::{Executor, StoreId, StoreInner, StoreOpaque};
53
use crate::vm::mpk::{self, ProtectionMask};

0 commit comments

Comments
 (0)