diff --git a/crates/wasi-common/src/snapshots/preview_0.rs b/crates/wasi-common/src/snapshots/preview_0.rs index d04b471c1847..c59b7bcfa08f 100644 --- a/crates/wasi-common/src/snapshots/preview_0.rs +++ b/crates/wasi-common/src/snapshots/preview_0.rs @@ -468,14 +468,16 @@ impl wasi_unstable::WasiUnstable for WasiCtx { .get_file_mut(u32::from(fd))? .get_cap_mut(FileCaps::READ)?; - let mut guest_slices: Vec> = iovs - .iter() - .map(|iov_ptr| { - let iov_ptr = iov_ptr?; - let iov: types::Iovec = iov_ptr.read()?; - Ok(iov.buf.as_array(iov.buf_len).as_slice_mut()?) - }) - .collect::>()?; + let mut guest_slices: Vec> = + iovs.iter() + .map(|iov_ptr| { + let iov_ptr = iov_ptr?; + let iov: types::Iovec = iov_ptr.read()?; + Ok(iov.buf.as_array(iov.buf_len).as_slice_mut()?.expect( + "cannot use with shared memories; see https://github.com/bytecodealliance/wasmtime/issues/5235 (TODO)", + )) + }) + .collect::>()?; let mut ioslices: Vec = guest_slices .iter_mut() @@ -497,14 +499,16 @@ impl wasi_unstable::WasiUnstable for WasiCtx { .get_file_mut(u32::from(fd))? .get_cap_mut(FileCaps::READ | FileCaps::SEEK)?; - let mut guest_slices: Vec> = iovs - .iter() - .map(|iov_ptr| { - let iov_ptr = iov_ptr?; - let iov: types::Iovec = iov_ptr.read()?; - Ok(iov.buf.as_array(iov.buf_len).as_slice_mut()?) - }) - .collect::>()?; + let mut guest_slices: Vec> = + iovs.iter() + .map(|iov_ptr| { + let iov_ptr = iov_ptr?; + let iov: types::Iovec = iov_ptr.read()?; + Ok(iov.buf.as_array(iov.buf_len).as_slice_mut()?.expect( + "cannot use with shared memories; see https://github.com/bytecodealliance/wasmtime/issues/5235 (TODO)", + )) + }) + .collect::>()?; let mut ioslices: Vec = guest_slices .iter_mut() @@ -530,7 +534,11 @@ impl wasi_unstable::WasiUnstable for WasiCtx { .map(|iov_ptr| { let iov_ptr = iov_ptr?; let iov: types::Ciovec = iov_ptr.read()?; - Ok(iov.buf.as_array(iov.buf_len).as_slice()?) + Ok(iov + .buf + .as_array(iov.buf_len) + .as_slice()? + .expect("cannot use with shared memories; see https://github.com/bytecodealliance/wasmtime/issues/5235 (TODO)")) }) .collect::>()?; @@ -559,7 +567,11 @@ impl wasi_unstable::WasiUnstable for WasiCtx { .map(|iov_ptr| { let iov_ptr = iov_ptr?; let iov: types::Ciovec = iov_ptr.read()?; - Ok(iov.buf.as_array(iov.buf_len).as_slice()?) + Ok(iov + .buf + .as_array(iov.buf_len) + .as_slice()? + .expect("cannot use with shared memories; see https://github.com/bytecodealliance/wasmtime/issues/5235 (TODO)")) }) .collect::>()?; diff --git a/crates/wasi-common/src/snapshots/preview_1.rs b/crates/wasi-common/src/snapshots/preview_1.rs index ca7dde519d10..670780673593 100644 --- a/crates/wasi-common/src/snapshots/preview_1.rs +++ b/crates/wasi-common/src/snapshots/preview_1.rs @@ -521,14 +521,16 @@ impl wasi_snapshot_preview1::WasiSnapshotPreview1 for WasiCtx { .get_file_mut(u32::from(fd))? .get_cap_mut(FileCaps::READ)?; - let mut guest_slices: Vec> = iovs - .iter() - .map(|iov_ptr| { - let iov_ptr = iov_ptr?; - let iov: types::Iovec = iov_ptr.read()?; - Ok(iov.buf.as_array(iov.buf_len).as_slice_mut()?) - }) - .collect::>()?; + let mut guest_slices: Vec> = + iovs.iter() + .map(|iov_ptr| { + let iov_ptr = iov_ptr?; + let iov: types::Iovec = iov_ptr.read()?; + Ok(iov.buf.as_array(iov.buf_len).as_slice_mut()?.expect( + "cannot use with shared memories; see https://github.com/bytecodealliance/wasmtime/issues/5235 (TODO)", + )) + }) + .collect::>()?; let mut ioslices: Vec = guest_slices .iter_mut() @@ -550,14 +552,16 @@ impl wasi_snapshot_preview1::WasiSnapshotPreview1 for WasiCtx { .get_file_mut(u32::from(fd))? .get_cap_mut(FileCaps::READ | FileCaps::SEEK)?; - let mut guest_slices: Vec> = iovs - .iter() - .map(|iov_ptr| { - let iov_ptr = iov_ptr?; - let iov: types::Iovec = iov_ptr.read()?; - Ok(iov.buf.as_array(iov.buf_len).as_slice_mut()?) - }) - .collect::>()?; + let mut guest_slices: Vec> = + iovs.iter() + .map(|iov_ptr| { + let iov_ptr = iov_ptr?; + let iov: types::Iovec = iov_ptr.read()?; + Ok(iov.buf.as_array(iov.buf_len).as_slice_mut()?.expect( + "cannot use with shared memories; see https://github.com/bytecodealliance/wasmtime/issues/5235 (TODO)", + )) + }) + .collect::>()?; let mut ioslices: Vec = guest_slices .iter_mut() @@ -583,7 +587,11 @@ impl wasi_snapshot_preview1::WasiSnapshotPreview1 for WasiCtx { .map(|iov_ptr| { let iov_ptr = iov_ptr?; let iov: types::Ciovec = iov_ptr.read()?; - Ok(iov.buf.as_array(iov.buf_len).as_slice()?) + Ok(iov + .buf + .as_array(iov.buf_len) + .as_slice()? + .expect("cannot use with shared memories; see https://github.com/bytecodealliance/wasmtime/issues/5235 (TODO)")) }) .collect::>()?; @@ -612,7 +620,11 @@ impl wasi_snapshot_preview1::WasiSnapshotPreview1 for WasiCtx { .map(|iov_ptr| { let iov_ptr = iov_ptr?; let iov: types::Ciovec = iov_ptr.read()?; - Ok(iov.buf.as_array(iov.buf_len).as_slice()?) + Ok(iov + .buf + .as_array(iov.buf_len) + .as_slice()? + .expect("cannot use with shared memories; see https://github.com/bytecodealliance/wasmtime/issues/5235 (TODO)")) }) .collect::>()?; @@ -654,7 +666,10 @@ impl wasi_snapshot_preview1::WasiSnapshotPreview1 for WasiCtx { if path_len < path_max_len as usize { return Err(Error::name_too_long()); } - let mut p_memory = path.as_array(path_len as u32).as_slice_mut()?; + let mut p_memory = path + .as_array(path_len as u32) + .as_slice_mut()? + .expect("cannot use with shared memories; see https://github.com/bytecodealliance/wasmtime/issues/5235 (TODO)"); p_memory.copy_from_slice(path_bytes); Ok(()) } else { @@ -948,7 +963,10 @@ impl wasi_snapshot_preview1::WasiSnapshotPreview1 for WasiCtx { if link_len > buf_len as usize { return Err(Error::range()); } - let mut buf = buf.as_array(link_len as u32).as_slice_mut()?; + let mut buf = buf + .as_array(link_len as u32) + .as_slice_mut()? + .expect("cannot use with shared memories; see https://github.com/bytecodealliance/wasmtime/issues/5235 (TODO)"); buf.copy_from_slice(link_bytes); Ok(link_len as types::Size) } @@ -1236,7 +1254,10 @@ impl wasi_snapshot_preview1::WasiSnapshotPreview1 for WasiCtx { buf: &GuestPtr<'a, u8>, buf_len: types::Size, ) -> Result<(), Error> { - let mut buf = buf.as_array(buf_len).as_slice_mut()?; + let mut buf = buf + .as_array(buf_len) + .as_slice_mut()? + .expect("cannot use with shared memories; see https://github.com/bytecodealliance/wasmtime/issues/5235 (TODO)"); self.random.try_fill_bytes(buf.deref_mut())?; Ok(()) } @@ -1273,14 +1294,17 @@ impl wasi_snapshot_preview1::WasiSnapshotPreview1 for WasiCtx { .get_file_mut(u32::from(fd))? .get_cap_mut(FileCaps::READ)?; - let mut guest_slices: Vec> = ri_data - .iter() - .map(|iov_ptr| { - let iov_ptr = iov_ptr?; - let iov: types::Iovec = iov_ptr.read()?; - Ok(iov.buf.as_array(iov.buf_len).as_slice_mut()?) - }) - .collect::>()?; + let mut guest_slices: Vec> = + ri_data + .iter() + .map(|iov_ptr| { + let iov_ptr = iov_ptr?; + let iov: types::Iovec = iov_ptr.read()?; + Ok(iov.buf.as_array(iov.buf_len).as_slice_mut()?.expect( + "cannot use with shared memories; see https://github.com/bytecodealliance/wasmtime/issues/5235 (TODO)", + )) + }) + .collect::>()?; let mut ioslices: Vec = guest_slices .iter_mut() @@ -1307,7 +1331,11 @@ impl wasi_snapshot_preview1::WasiSnapshotPreview1 for WasiCtx { .map(|iov_ptr| { let iov_ptr = iov_ptr?; let iov: types::Ciovec = iov_ptr.read()?; - Ok(iov.buf.as_array(iov.buf_len).as_slice()?) + Ok(iov + .buf + .as_array(iov.buf_len) + .as_slice()? + .expect("cannot use with shared memories; see https://github.com/bytecodealliance/wasmtime/issues/5235 (TODO)")) }) .collect::>()?; diff --git a/crates/wasi-crypto/src/wiggle_interfaces/asymmetric_common.rs b/crates/wasi-crypto/src/wiggle_interfaces/asymmetric_common.rs index 2d5c25a1f991..dd346257de18 100644 --- a/crates/wasi-crypto/src/wiggle_interfaces/asymmetric_common.rs +++ b/crates/wasi-crypto/src/wiggle_interfaces/asymmetric_common.rs @@ -39,7 +39,10 @@ impl super::wasi_ephemeral_crypto_asymmetric_common::WasiEphemeralCryptoAsymmetr kp_id_ptr: &wiggle::GuestPtr<'_, u8>, kp_id_max_len: guest_types::Size, ) -> Result<(), guest_types::CryptoErrno> { - let key_id_buf = &mut *kp_id_ptr.as_array(kp_id_max_len).as_slice_mut()?; + let key_id_buf = &mut *kp_id_ptr + .as_array(kp_id_max_len) + .as_slice_mut()? + .expect("cannot use with shared memories; see https://github.com/bytecodealliance/wasmtime/issues/5235 (TODO)"); Ok((&*self).keypair_store_managed( secrets_manager_handle.into(), kp_handle.into(), @@ -69,7 +72,10 @@ impl super::wasi_ephemeral_crypto_asymmetric_common::WasiEphemeralCryptoAsymmetr kp_id_len: guest_types::Size, kp_version: guest_types::Version, ) -> Result { - let kp_id = &*kp_id_ptr.as_array(kp_id_len).as_slice()?; + let kp_id = &*kp_id_ptr + .as_array(kp_id_len) + .as_slice()? + .expect("cannot use with shared memories; see https://github.com/bytecodealliance/wasmtime/issues/5235 (TODO)"); Ok((&*self) .keypair_from_id(secrets_manager_handle.into(), kp_id, Version(kp_version))? .into()) @@ -102,7 +108,10 @@ impl super::wasi_ephemeral_crypto_asymmetric_common::WasiEphemeralCryptoAsymmetr encoding: guest_types::KeypairEncoding, ) -> Result { let alg_str = &*alg_str.as_str()?; - let encoded = &*encoded_ptr.as_array(encoded_len).as_slice()?; + let encoded = &*encoded_ptr + .as_array(encoded_len) + .as_slice()? + .expect("cannot use with shared memories; see https://github.com/bytecodealliance/wasmtime/issues/5235 (TODO)"); Ok((&*self) .keypair_import(alg_type.into(), alg_str, encoded, encoding.into())? .into()) @@ -114,7 +123,10 @@ impl super::wasi_ephemeral_crypto_asymmetric_common::WasiEphemeralCryptoAsymmetr kp_id_ptr: &wiggle::GuestPtr<'_, u8>, kp_id_max_len: guest_types::Size, ) -> Result<(guest_types::Size, guest_types::Version), guest_types::CryptoErrno> { - let kp_id_buf = &mut *kp_id_ptr.as_array(kp_id_max_len as _).as_slice_mut()?; + let kp_id_buf = &mut *kp_id_ptr + .as_array(kp_id_max_len as _) + .as_slice_mut()? + .expect("cannot use with shared memories; see https://github.com/bytecodealliance/wasmtime/issues/5235 (TODO)"); let (kp_id, version) = (&*self).keypair_id(kp_handle.into())?; ensure!(kp_id.len() <= kp_id_buf.len(), CryptoError::Overflow.into()); kp_id_buf.copy_from_slice(&kp_id); @@ -156,7 +168,10 @@ impl super::wasi_ephemeral_crypto_asymmetric_common::WasiEphemeralCryptoAsymmetr encoding: guest_types::PublickeyEncoding, ) -> Result { let alg_str = &*alg_str.as_str()?; - let encoded = &*encoded_ptr.as_array(encoded_len).as_slice()?; + let encoded = &*encoded_ptr + .as_array(encoded_len) + .as_slice()? + .expect("cannot use with shared memories; see https://github.com/bytecodealliance/wasmtime/issues/5235 (TODO)"); Ok((&*self) .publickey_import(alg_type.into(), alg_str, encoded, encoding.into())? .into()) @@ -204,7 +219,10 @@ impl super::wasi_ephemeral_crypto_asymmetric_common::WasiEphemeralCryptoAsymmetr encoding: guest_types::SecretkeyEncoding, ) -> Result { let alg_str = &*alg_str.as_str()?; - let encoded = &*encoded_ptr.as_array(encoded_len).as_slice()?; + let encoded = &*encoded_ptr + .as_array(encoded_len) + .as_slice()? + .expect("cannot use with shared memories; see https://github.com/bytecodealliance/wasmtime/issues/5235 (TODO)"); Ok((&*self) .secretkey_import(alg_type.into(), alg_str, encoded, encoding.into())? .into()) diff --git a/crates/wasi-crypto/src/wiggle_interfaces/common.rs b/crates/wasi-crypto/src/wiggle_interfaces/common.rs index 8c5ed13cbde1..1652717581c3 100644 --- a/crates/wasi-crypto/src/wiggle_interfaces/common.rs +++ b/crates/wasi-crypto/src/wiggle_interfaces/common.rs @@ -28,7 +28,12 @@ impl super::wasi_ephemeral_crypto_common::WasiEphemeralCryptoCommon for WasiCryp value_len: guest_types::Size, ) -> Result<(), guest_types::CryptoErrno> { let name_str: &str = &*name_str.as_str()?; - let value: &[u8] = { &*value_ptr.as_array(value_len).as_slice()? }; + let value: &[u8] = { + &*value_ptr + .as_array(value_len) + .as_slice()? + .expect("cannot use with shared memories; see https://github.com/bytecodealliance/wasmtime/issues/5235 (TODO)") + }; Ok((&*self).options_set(options_handle.into(), name_str, value)?) } @@ -40,8 +45,14 @@ impl super::wasi_ephemeral_crypto_common::WasiEphemeralCryptoCommon for WasiCryp buffer_len: guest_types::Size, ) -> Result<(), guest_types::CryptoErrno> { let name_str: &str = &*name_str.as_str()?; - let buffer: &'static mut [u8] = - unsafe { std::mem::transmute(&mut *buffer_ptr.as_array(buffer_len).as_slice_mut()?) }; + let buffer: &'static mut [u8] = unsafe { + std::mem::transmute( + &mut *buffer_ptr + .as_array(buffer_len) + .as_slice_mut()? + .expect("cannot use with shared memories; see https://github.com/bytecodealliance/wasmtime/issues/5235 (TODO)"), + ) + }; Ok((&*self).options_set_guest_buffer(options_handle.into(), name_str, buffer)?) } @@ -72,7 +83,12 @@ impl super::wasi_ephemeral_crypto_common::WasiEphemeralCryptoCommon for WasiCryp buf_ptr: &wiggle::GuestPtr<'_, u8>, buf_len: guest_types::Size, ) -> Result { - let buf: &mut [u8] = { &mut *buf_ptr.as_array(buf_len).as_slice_mut()? }; + let buf: &mut [u8] = { + &mut *buf_ptr + .as_array(buf_len) + .as_slice_mut()? + .expect("cannot use with shared memories; see https://github.com/bytecodealliance/wasmtime/issues/5235 (TODO)") + }; Ok((&*self) .array_output_pull(array_output_handle.into(), buf)? .try_into()?) @@ -107,7 +123,12 @@ impl super::wasi_ephemeral_crypto_common::WasiEphemeralCryptoCommon for WasiCryp key_id_len: guest_types::Size, key_version: guest_types::Version, ) -> Result<(), guest_types::CryptoErrno> { - let key_id: &[u8] = { &*key_id_ptr.as_array(key_id_len).as_slice()? }; + let key_id: &[u8] = { + &*key_id_ptr + .as_array(key_id_len) + .as_slice()? + .expect("cannot use with shared memories; see https://github.com/bytecodealliance/wasmtime/issues/5235 (TODO)") + }; Ok((&*self).secrets_manager_invalidate( secrets_manager_handle.into(), key_id, diff --git a/crates/wasi-crypto/src/wiggle_interfaces/key_exchange.rs b/crates/wasi-crypto/src/wiggle_interfaces/key_exchange.rs index 462d76864581..e7fb1a927ce1 100644 --- a/crates/wasi-crypto/src/wiggle_interfaces/key_exchange.rs +++ b/crates/wasi-crypto/src/wiggle_interfaces/key_exchange.rs @@ -31,7 +31,8 @@ impl super::wasi_ephemeral_crypto_kx::WasiEphemeralCryptoKx for WasiCryptoCtx { ) -> Result { let encapsulated_secret = &*encapsulated_secret_ptr .as_array(encapsulated_secret_len) - .as_slice()?; + .as_slice()? + .expect("cannot use with shared memories; see https://github.com/bytecodealliance/wasmtime/issues/5235 (TODO)"); Ok((&*self) .kx_decapsulate(sk_handle.into(), encapsulated_secret)? .into()) diff --git a/crates/wasi-crypto/src/wiggle_interfaces/signatures.rs b/crates/wasi-crypto/src/wiggle_interfaces/signatures.rs index ff4db33e0a14..653446070f9c 100644 --- a/crates/wasi-crypto/src/wiggle_interfaces/signatures.rs +++ b/crates/wasi-crypto/src/wiggle_interfaces/signatures.rs @@ -23,7 +23,10 @@ impl super::wasi_ephemeral_crypto_signatures::WasiEphemeralCryptoSignatures for encoding: guest_types::SignatureEncoding, ) -> Result { let alg_str = &*alg_str.as_str()?; - let encoded = &*encoded_ptr.as_array(encoded_len).as_slice()?; + let encoded = &*encoded_ptr + .as_array(encoded_len) + .as_slice()? + .expect("cannot use with shared memories; see https://github.com/bytecodealliance/wasmtime/issues/5235 (TODO)"); Ok((&*self) .signature_import(alg_str, encoded, encoding.into())? .into()) @@ -42,7 +45,10 @@ impl super::wasi_ephemeral_crypto_signatures::WasiEphemeralCryptoSignatures for input_ptr: &wiggle::GuestPtr<'_, u8>, input_len: guest_types::Size, ) -> Result<(), guest_types::CryptoErrno> { - let input = &*input_ptr.as_array(input_len).as_slice()?; + let input = &*input_ptr + .as_array(input_len) + .as_slice()? + .expect("cannot use with shared memories; see https://github.com/bytecodealliance/wasmtime/issues/5235 (TODO)"); Ok((&*self).signature_state_update(state_handle.into(), input)?) } @@ -77,7 +83,10 @@ impl super::wasi_ephemeral_crypto_signatures::WasiEphemeralCryptoSignatures for input_ptr: &wiggle::GuestPtr<'_, u8>, input_len: guest_types::Size, ) -> Result<(), guest_types::CryptoErrno> { - let input: &[u8] = &*input_ptr.as_array(input_len).as_slice()?; + let input: &[u8] = &*input_ptr + .as_array(input_len) + .as_slice()? + .expect("cannot use with shared memories; see https://github.com/bytecodealliance/wasmtime/issues/5235 (TODO)"); Ok( (&*self) .signature_verification_state_update(verification_state_handle.into(), input)?, diff --git a/crates/wasi-crypto/src/wiggle_interfaces/symmetric.rs b/crates/wasi-crypto/src/wiggle_interfaces/symmetric.rs index 881c3f5d65fc..6a65dfaa117b 100644 --- a/crates/wasi-crypto/src/wiggle_interfaces/symmetric.rs +++ b/crates/wasi-crypto/src/wiggle_interfaces/symmetric.rs @@ -35,7 +35,8 @@ impl super::wasi_ephemeral_crypto_symmetric::WasiEphemeralCryptoSymmetric for Wa ) -> Result<(), guest_types::CryptoErrno> { let key_id_buf = &mut *symmetric_key_id_ptr .as_array(symmetric_key_id_max_len) - .as_slice_mut()?; + .as_slice_mut()? + .expect("cannot use with shared memories; see https://github.com/bytecodealliance/wasmtime/issues/5235 (TODO)"); Ok((&*self).symmetric_key_store_managed( secrets_manager_handle.into(), symmetric_key_handle.into(), @@ -67,7 +68,8 @@ impl super::wasi_ephemeral_crypto_symmetric::WasiEphemeralCryptoSymmetric for Wa ) -> Result { let symmetric_key_id = &*symmetric_key_id_ptr .as_array(symmetric_key_id_len) - .as_slice()?; + .as_slice()? + .expect("cannot use with shared memories; see https://github.com/bytecodealliance/wasmtime/issues/5235 (TODO)"); Ok((&*self) .symmetric_key_from_id( secrets_manager_handle.into(), @@ -101,7 +103,10 @@ impl super::wasi_ephemeral_crypto_symmetric::WasiEphemeralCryptoSymmetric for Wa raw_len: guest_types::Size, ) -> Result { let alg_str = &*alg_str.as_str()?; - let raw = &*raw_ptr.as_array(raw_len).as_slice()?; + let raw = &*raw_ptr + .as_array(raw_len) + .as_slice()? + .expect("cannot use with shared memories; see https://github.com/bytecodealliance/wasmtime/issues/5235 (TODO)"); Ok((&*self).symmetric_key_import(alg_str, raw)?.into()) } @@ -122,7 +127,8 @@ impl super::wasi_ephemeral_crypto_symmetric::WasiEphemeralCryptoSymmetric for Wa ) -> Result<(guest_types::Size, guest_types::Version), guest_types::CryptoErrno> { let key_id_buf = &mut *symmetric_key_id_ptr .as_array(symmetric_key_id_max_len) - .as_slice_mut()?; + .as_slice_mut()? + .expect("cannot use with shared memories; see https://github.com/bytecodealliance/wasmtime/issues/5235 (TODO)"); let (key_id, version) = (&*self).symmetric_key_id(symmetric_key_handle.into())?; ensure!( key_id.len() <= key_id_buf.len(), @@ -173,7 +179,10 @@ impl super::wasi_ephemeral_crypto_symmetric::WasiEphemeralCryptoSymmetric for Wa value_max_len: guest_types::Size, ) -> Result { let name_str: &str = &*name_str.as_str()?; - let value = &mut *value_ptr.as_array(value_max_len).as_slice_mut()?; + let value = &mut *value_ptr + .as_array(value_max_len) + .as_slice_mut()? + .expect("cannot use with shared memories; see https://github.com/bytecodealliance/wasmtime/issues/5235 (TODO)"); Ok((&*self) .options_get(symmetric_state_handle.into(), name_str, value)? .try_into()?) @@ -201,7 +210,10 @@ impl super::wasi_ephemeral_crypto_symmetric::WasiEphemeralCryptoSymmetric for Wa data_ptr: &wiggle::GuestPtr<'_, u8>, data_len: guest_types::Size, ) -> Result<(), guest_types::CryptoErrno> { - let data = &*data_ptr.as_array(data_len).as_slice()?; + let data = &*data_ptr + .as_array(data_len) + .as_slice()? + .expect("cannot use with shared memories; see https://github.com/bytecodealliance/wasmtime/issues/5235 (TODO)"); Ok((&*self).symmetric_state_absorb(symmetric_state_handle.into(), data)?) } @@ -211,7 +223,10 @@ impl super::wasi_ephemeral_crypto_symmetric::WasiEphemeralCryptoSymmetric for Wa out_ptr: &wiggle::GuestPtr<'_, u8>, out_len: guest_types::Size, ) -> Result<(), guest_types::CryptoErrno> { - let out = &mut *out_ptr.as_array(out_len).as_slice_mut()?; + let out = &mut *out_ptr + .as_array(out_len) + .as_slice_mut()? + .expect("cannot use with shared memories; see https://github.com/bytecodealliance/wasmtime/issues/5235 (TODO)"); Ok((&*self).symmetric_state_squeeze(symmetric_state_handle.into(), out)?) } @@ -252,8 +267,14 @@ impl super::wasi_ephemeral_crypto_symmetric::WasiEphemeralCryptoSymmetric for Wa data_ptr: &wiggle::GuestPtr<'_, u8>, data_len: guest_types::Size, ) -> Result { - let out = &mut *out_ptr.as_array(out_len).as_slice_mut()?; - let data = &*data_ptr.as_array(data_len).as_slice()?; + let out = &mut *out_ptr + .as_array(out_len) + .as_slice_mut()? + .expect("cannot use with shared memories; see https://github.com/bytecodealliance/wasmtime/issues/5235 (TODO)"); + let data = &*data_ptr + .as_array(data_len) + .as_slice()? + .expect("cannot use with shared memories; see https://github.com/bytecodealliance/wasmtime/issues/5235 (TODO)"); Ok((&*self) .symmetric_state_encrypt(symmetric_state_handle.into(), out, data)? .try_into()?) @@ -267,8 +288,14 @@ impl super::wasi_ephemeral_crypto_symmetric::WasiEphemeralCryptoSymmetric for Wa data_ptr: &wiggle::GuestPtr<'_, u8>, data_len: guest_types::Size, ) -> Result { - let out = &mut *out_ptr.as_array(out_len).as_slice_mut()?; - let data = &*data_ptr.as_array(data_len).as_slice()?; + let out = &mut *out_ptr + .as_array(out_len) + .as_slice_mut()? + .expect("cannot use with shared memories; see https://github.com/bytecodealliance/wasmtime/issues/5235 (TODO)"); + let data = &*data_ptr + .as_array(data_len) + .as_slice()? + .expect("cannot use with shared memories; see https://github.com/bytecodealliance/wasmtime/issues/5235 (TODO)"); Ok((&*self) .symmetric_state_encrypt_detached(symmetric_state_handle.into(), out, data)? .into()) @@ -282,8 +309,14 @@ impl super::wasi_ephemeral_crypto_symmetric::WasiEphemeralCryptoSymmetric for Wa data_ptr: &wiggle::GuestPtr<'_, u8>, data_len: guest_types::Size, ) -> Result { - let out = &mut *out_ptr.as_array(out_len).as_slice_mut()?; - let data = &*data_ptr.as_array(data_len).as_slice()?; + let out = &mut *out_ptr + .as_array(out_len) + .as_slice_mut()? + .expect("cannot use with shared memories; see https://github.com/bytecodealliance/wasmtime/issues/5235 (TODO)"); + let data = &*data_ptr + .as_array(data_len) + .as_slice()? + .expect("cannot use with shared memories; see https://github.com/bytecodealliance/wasmtime/issues/5235 (TODO)"); Ok((&*self) .symmetric_state_decrypt(symmetric_state_handle.into(), out, data)? .try_into()?) @@ -299,9 +332,18 @@ impl super::wasi_ephemeral_crypto_symmetric::WasiEphemeralCryptoSymmetric for Wa raw_tag_ptr: &wiggle::GuestPtr<'_, u8>, raw_tag_len: guest_types::Size, ) -> Result { - let out = &mut *out_ptr.as_array(out_len).as_slice_mut()?; - let data = &*data_ptr.as_array(data_len).as_slice()?; - let raw_tag: &[u8] = &*raw_tag_ptr.as_array(raw_tag_len).as_slice()?; + let out = &mut *out_ptr + .as_array(out_len) + .as_slice_mut()? + .expect("cannot use with shared memories; see https://github.com/bytecodealliance/wasmtime/issues/5235 (TODO)"); + let data = &*data_ptr + .as_array(data_len) + .as_slice()? + .expect("cannot use with shared memories; see https://github.com/bytecodealliance/wasmtime/issues/5235 (TODO)"); + let raw_tag: &[u8] = &*raw_tag_ptr + .as_array(raw_tag_len) + .as_slice()? + .expect("cannot use with shared memories; see https://github.com/bytecodealliance/wasmtime/issues/5235 (TODO)"); Ok((&*self) .symmetric_state_decrypt_detached(symmetric_state_handle.into(), out, data, raw_tag)? .try_into()?) @@ -331,7 +373,10 @@ impl super::wasi_ephemeral_crypto_symmetric::WasiEphemeralCryptoSymmetric for Wa buf_ptr: &wiggle::GuestPtr<'_, u8>, buf_len: guest_types::Size, ) -> Result { - let buf = &mut *buf_ptr.as_array(buf_len).as_slice_mut()?; + let buf = &mut *buf_ptr + .as_array(buf_len) + .as_slice_mut()? + .expect("cannot use with shared memories; see https://github.com/bytecodealliance/wasmtime/issues/5235 (TODO)"); Ok((&*self) .symmetric_tag_pull(symmetric_tag_handle.into(), buf)? .try_into()?) @@ -343,7 +388,10 @@ impl super::wasi_ephemeral_crypto_symmetric::WasiEphemeralCryptoSymmetric for Wa expected_raw_ptr: &wiggle::GuestPtr<'_, u8>, expected_raw_len: guest_types::Size, ) -> Result<(), guest_types::CryptoErrno> { - let expected_raw = &*expected_raw_ptr.as_array(expected_raw_len).as_slice()?; + let expected_raw = &*expected_raw_ptr + .as_array(expected_raw_len) + .as_slice()? + .expect("cannot use with shared memories; see https://github.com/bytecodealliance/wasmtime/issues/5235 (TODO)"); Ok((&*self).symmetric_tag_verify(symmetric_tag_handle.into(), expected_raw)?) } diff --git a/crates/wasi-nn/src/impl.rs b/crates/wasi-nn/src/impl.rs index 85be8dd97c08..0f8da5247a7b 100644 --- a/crates/wasi-nn/src/impl.rs +++ b/crates/wasi-nn/src/impl.rs @@ -80,8 +80,11 @@ impl<'a> WasiEphemeralNn for WasiNnCtx { out_buffer: &GuestPtr<'_, u8>, out_buffer_max_size: u32, ) -> Result { - let mut destination = out_buffer.as_array(out_buffer_max_size).as_slice_mut()?; if let Some(exec_context) = self.executions.get_mut(exec_context_id) { + let mut destination = out_buffer + .as_array(out_buffer_max_size) + .as_slice_mut()? + .expect("cannot use with shared memories; see https://github.com/bytecodealliance/wasmtime/issues/5235 (TODO)"); Ok(exec_context.get_output(index, &mut destination)?) } else { Err(UsageError::InvalidGraphHandle.into()) diff --git a/crates/wasi-nn/src/openvino.rs b/crates/wasi-nn/src/openvino.rs index 89f043455ce5..fff9bf7e5cf1 100644 --- a/crates/wasi-nn/src/openvino.rs +++ b/crates/wasi-nn/src/openvino.rs @@ -31,8 +31,15 @@ impl Backend for OpenvinoBackend { // Read the guest array. let builders = builders.as_ptr(); - let xml = builders.read()?.as_slice()?; - let weights = builders.add(1)?.read()?.as_slice()?; + let xml = builders + .read()? + .as_slice()? + .expect("cannot use with shared memories; see https://github.com/bytecodealliance/wasmtime/issues/5235 (TODO)"); + let weights = builders + .add(1)? + .read()? + .as_slice()? + .expect("cannot use with shared memories; see https://github.com/bytecodealliance/wasmtime/issues/5235 (TODO)"); // Construct OpenVINO graph structures: `cnn_network` contains the graph // structure, `exec_network` can perform inference. @@ -78,6 +85,7 @@ impl BackendExecutionContext for OpenvinoExecutionContext { let dimensions = tensor .dimensions .as_slice()? + .expect("cannot use with shared memories; see https://github.com/bytecodealliance/wasmtime/issues/5235 (TODO)") .iter() .map(|d| *d as usize) .collect::>(); @@ -86,7 +94,10 @@ impl BackendExecutionContext for OpenvinoExecutionContext { // TODO There must be some good way to discover the layout here; this // should not have to default to NHWC. let desc = TensorDesc::new(Layout::NHWC, &dimensions, precision); - let data = tensor.data.as_slice()?; + let data = tensor + .data + .as_slice()? + .expect("cannot use with shared memories; see https://github.com/bytecodealliance/wasmtime/issues/5235 (TODO)"); let blob = openvino::Blob::new(&desc, &data)?; // Actually assign the blob to the request. diff --git a/crates/wiggle/src/lib.rs b/crates/wiggle/src/lib.rs index 79b02e4d3ab7..a03bc6e20ff1 100644 --- a/crates/wiggle/src/lib.rs +++ b/crates/wiggle/src/lib.rs @@ -513,90 +513,108 @@ impl<'a, T> GuestPtr<'a, [T]> { /// Attempts to create a [`GuestSlice<'_, T>`] from this pointer, performing /// bounds checks and type validation. The `GuestSlice` is a smart pointer - /// that can be used as a `&[T]` via the `Deref` trait. - /// The region of memory backing the slice will be marked as shareably - /// borrowed by the [`GuestMemory`] until the `GuestSlice` is dropped. - /// Multiple shareable borrows of the same memory are permitted, but only - /// one mutable borrow. + /// that can be used as a `&[T]` via the `Deref` trait. The region of memory + /// backing the slice will be marked as shareably borrowed by the + /// [`GuestMemory`] until the `GuestSlice` is dropped. Multiple shareable + /// borrows of the same memory are permitted, but only one mutable borrow. /// /// This function will return a `GuestSlice` into host memory if all checks - /// succeed (valid utf-8, valid pointers, memory is not borrowed, etc). If + /// succeed (valid utf-8, valid pointers, memory is not borrowed, etc.). If /// any checks fail then `GuestError` will be returned. - pub fn as_slice(&self) -> Result, GuestError> + /// + /// Additionally, because it is `unsafe` to have a `GuestSlice` of shared + /// memory, this function will return `None` in this case. + pub fn as_slice(&self) -> Result>, GuestError> where T: GuestTypeTransparent<'a>, { - let len = match self.pointer.1.checked_mul(T::guest_size()) { - Some(l) => l, - None => return Err(GuestError::PtrOverflow), - }; - let ptr = - self.mem - .validate_size_align(self.pointer.0, T::guest_align(), len)? as *mut T; - - let borrow = self.mem.shared_borrow(Region { - start: self.pointer.0, - len, - })?; - - // Validate all elements in slice. - // SAFETY: ptr has been validated by self.mem.validate_size_align - for offs in 0..self.pointer.1 { - T::validate(unsafe { ptr.add(offs as usize) })?; + match self.as_unsafe_slice_mut()?.shared_borrow() { + UnsafeBorrowResult::Ok(slice) => Ok(Some(slice)), + UnsafeBorrowResult::Shared(_) => Ok(None), + UnsafeBorrowResult::Err(e) => Err(e), } - - // SAFETY: iff there are no overlapping mut borrows it is valid to construct a &[T] - let ptr = unsafe { slice::from_raw_parts(ptr, self.pointer.1 as usize) }; - - Ok(GuestSlice { - ptr, - mem: self.mem, - borrow, - }) } - /// Attempts to create a [`GuestSliceMut<'_, T>`] from this pointer, performing - /// bounds checks and type validation. The `GuestSliceMut` is a smart pointer - /// that can be used as a `&[T]` or a `&mut [T]` via the `Deref` and `DerefMut` - /// traits. The region of memory backing the slice will be marked as borrowed - /// by the [`GuestMemory`] until the `GuestSlice` is dropped. + /// Attempts to create a [`GuestSliceMut<'_, T>`] from this pointer, + /// performing bounds checks and type validation. The `GuestSliceMut` is a + /// smart pointer that can be used as a `&[T]` or a `&mut [T]` via the + /// `Deref` and `DerefMut` traits. The region of memory backing the slice + /// will be marked as borrowed by the [`GuestMemory`] until the `GuestSlice` + /// is dropped. /// - /// This function will return a `GuestSliceMut` into host memory if all checks - /// succeed (valid utf-8, valid pointers, memory is not borrowed, etc). If - /// any checks fail then `GuestError` will be returned. - pub fn as_slice_mut(&self) -> Result, GuestError> + /// This function will return a `GuestSliceMut` into host memory if all + /// checks succeed (valid utf-8, valid pointers, memory is not borrowed, + /// etc). If any checks fail then `GuestError` will be returned. + /// + /// Additionally, because it is `unsafe` to have a `GuestSliceMut` of shared + /// memory, this function will return `None` in this case. + pub fn as_slice_mut(&self) -> Result>, GuestError> where T: GuestTypeTransparent<'a>, { - let len = match self.pointer.1.checked_mul(T::guest_size()) { - Some(l) => l, - None => return Err(GuestError::PtrOverflow), - }; + match self.as_unsafe_slice_mut()?.mut_borrow() { + UnsafeBorrowResult::Ok(slice) => Ok(Some(slice)), + UnsafeBorrowResult::Shared(_) => Ok(None), + UnsafeBorrowResult::Err(e) => Err(e), + } + } + + /// Similar to `as_slice_mut`, this function will attempt to create a smart + /// pointer to the WebAssembly linear memory. All validation and Wiggle + /// borrow checking is the same, but unlike `as_slice_mut`, the returned + /// `&mut` slice can point to WebAssembly shared memory. Though the Wiggle + /// borrow checker can guarantee no other Wiggle calls will access this + /// slice, it cannot guarantee that another thread is not modifying the + /// `&mut` slice in some other way. Thus, access to that slice is marked + /// `unsafe`. + pub fn as_unsafe_slice_mut(&self) -> Result, GuestError> + where + T: GuestTypeTransparent<'a>, + { + // Validate the bounds of the region in the original memory. + let len = self.checked_byte_len()?; let ptr = self.mem .validate_size_align(self.pointer.0, T::guest_align(), len)? as *mut T; - - let borrow = self.mem.mut_borrow(Region { + let region = Region { start: self.pointer.0, len, - })?; + }; - // Validate all elements in slice. - // SAFETY: ptr has been validated by self.mem.validate_size_align + // Validate all elements in slice. `T::validate` is expected to be a + // noop for `GuestTypeTransparent` so this check may not be entirely + // necessary (TODO). + // + // SAFETY: `ptr` has been validated by `self.mem.validate_size_align`. for offs in 0..self.pointer.1 { T::validate(unsafe { ptr.add(offs as usize) })?; } - // SAFETY: iff there are no overlapping borrows it is valid to construct a &mut [T] - let ptr = unsafe { slice::from_raw_parts_mut(ptr, self.pointer.1 as usize) }; - - Ok(GuestSliceMut { + Ok(UnsafeGuestSlice { ptr, + len: self.pointer.1 as usize, + region, mem: self.mem, - borrow, }) } + /// Copies the data in the guest region into a [`Vec`]. + /// + /// This is useful when one cannot use [`GuestPtr::as_slice`], e.g., when + /// pointing to a region of WebAssembly shared memory. + pub fn to_vec(&self) -> Result, GuestError> + where + T: GuestTypeTransparent<'a> + Copy + 'a, + { + let guest_slice = self.as_unsafe_slice_mut()?; + let mut vec = Vec::with_capacity(guest_slice.len); + for offs in 0..guest_slice.len { + let elem = self.get(offs as u32).expect("already validated the size"); + vec.push(elem.read()?); + } + Ok(vec) + } + /// Copies the data pointed to by `slice` into this guest region. /// /// This method is a *safe* method to copy data from the host to the guest. @@ -613,14 +631,25 @@ impl<'a, T> GuestPtr<'a, [T]> { where T: GuestTypeTransparent<'a> + Copy + 'a, { - // bounds check ... - let mut self_slice = self.as_slice_mut()?; + // Retrieve the slice of memory to copy to, performing the necessary + // bounds checks ... + let guest_slice = self.as_unsafe_slice_mut()?; // ... length check ... - if self_slice.len() != slice.len() { + if guest_slice.len != slice.len() { return Err(GuestError::SliceLengthsDiffer); } - // ... and copy! - self_slice.copy_from_slice(slice); + // ... and copy the bytes. + match guest_slice.mut_borrow() { + UnsafeBorrowResult::Ok(mut dst) => dst.copy_from_slice(slice), + UnsafeBorrowResult::Shared(guest_slice) => { + // SAFETY: in the shared memory case, we copy and accept that + // the guest data may be concurrently modified. TODO: audit that + // this use of `std::ptr::copy` is safe with shared memory + // (https://github.com/bytecodealliance/wasmtime/issues/4203) + unsafe { std::ptr::copy(slice.as_ptr(), guest_slice.ptr, guest_slice.len) }; + } + UnsafeBorrowResult::Err(e) => return Err(e), + } Ok(()) } @@ -664,6 +693,17 @@ impl<'a, T> GuestPtr<'a, [T]> { None } } + + /// Return the number of bytes necessary to represent the pointed-to value. + fn checked_byte_len(&self) -> Result + where + T: GuestTypeTransparent<'a>, + { + match self.pointer.1.checked_mul(T::guest_size()) { + Some(l) => Ok(l), + None => Err(GuestError::PtrOverflow), + } + } } impl<'a> GuestPtr<'a, str> { @@ -780,6 +820,7 @@ impl fmt::Debug for GuestPtr<'_, T> { } /// A smart pointer to an shareable slice in guest memory. +/// /// Usable as a `&'a [T]` via [`std::ops::Deref`]. pub struct GuestSlice<'a, T> { ptr: &'a [T], @@ -801,6 +842,7 @@ impl<'a, T> Drop for GuestSlice<'a, T> { } /// A smart pointer to a mutable slice in guest memory. +/// /// Usable as a `&'a [T]` via [`std::ops::Deref`] and as a `&'a mut [T]` via /// [`std::ops::DerefMut`]. pub struct GuestSliceMut<'a, T> { @@ -828,6 +870,108 @@ impl<'a, T> Drop for GuestSliceMut<'a, T> { } } +/// A smart pointer to an `unsafe` slice in guest memory. +/// +/// Accessing guest memory (e.g., WebAssembly linear memory) is inherently +/// `unsafe`. Even though this structure expects that we will have validated the +/// addresses, lengths, and alignment, we must be extra careful to maintain the +/// Rust borrowing guarantees if we hand out slices to the underlying memory. +/// This is done in two ways: +/// +/// - with shared memory (i.e., memory that may be accessed concurrently by +/// multiple threads), we have no guarantee that the underlying data will not +/// be changed; thus, we can only hand out slices `unsafe`-ly (TODO: +/// eventually with `UnsafeGuestSlice::as_slice`, +/// `UnsafeGuestSlice::as_slice_mut`) +/// - with non-shared memory, we _can_ maintain the Rust slice guarantees, but +/// only by manually performing borrow-checking of the underlying regions that +/// are accessed; this kind of borrowing is wrapped up in the [`GuestSlice`] +/// and [`GuestSliceMut`] smart pointers (see +/// [`UnsafeGuestSlice::shared_borrow`], [`UnsafeGuestSlice::mut_borrow`]). +pub struct UnsafeGuestSlice<'a, T> { + /// A raw pointer to the bytes in memory. + ptr: *mut T, + /// The (validated) number of items in the slice. + len: usize, + /// The (validated) address bounds of the slice in memory. + region: Region, + /// The original memory. + mem: &'a dyn GuestMemory, +} + +impl<'a, T> UnsafeGuestSlice<'a, T> { + /// Transform an `unsafe` guest slice to a [`GuestSliceMut`]. + /// + /// # Safety + /// + /// This function is safe if and only if: + /// - the memory is not shared (it will return `None` in this case) and + /// - there are no overlapping mutable borrows for this region. + fn shared_borrow(self) -> UnsafeBorrowResult, Self> { + if self.mem.is_shared_memory() { + UnsafeBorrowResult::Shared(self) + } else { + match self.mem.shared_borrow(self.region) { + Ok(borrow) => { + let ptr = unsafe { slice::from_raw_parts(self.ptr, self.len) }; + UnsafeBorrowResult::Ok(GuestSlice { + ptr, + mem: self.mem, + borrow, + }) + } + Err(e) => UnsafeBorrowResult::Err(e), + } + } + } + + /// Transform an `unsafe` guest slice to a [`GuestSliceMut`]. + /// + /// # Safety + /// + /// This function is safe if and only if: + /// - the memory is not shared (it will return `None` in this case) and + /// - there are no overlapping borrows of any kind (shared or mutable) for + /// this region. + fn mut_borrow(self) -> UnsafeBorrowResult, Self> { + if self.mem.is_shared_memory() { + UnsafeBorrowResult::Shared(self) + } else { + match self.mem.mut_borrow(self.region) { + Ok(borrow) => { + let ptr = unsafe { slice::from_raw_parts_mut(self.ptr, self.len) }; + UnsafeBorrowResult::Ok(GuestSliceMut { + ptr, + mem: self.mem, + borrow, + }) + } + Err(e) => UnsafeBorrowResult::Err(e), + } + } + } +} + +/// A three-way result type for expressing that borrowing from an +/// [`UnsafeGuestSlice`] could fail in multiple ways. Retaining the +/// [`UnsafeGuestSlice`] in the `Shared` case allows us to reuse it. +enum UnsafeBorrowResult { + /// The borrow succeeded. + Ok(T), + /// The borrow failed because the underlying memory was shared--we cannot + /// safely borrow in this case and return the original unsafe slice. + Shared(S), + /// The borrow failed for some other reason, e.g., the region was already + /// borrowed. + Err(GuestError), +} + +impl From for UnsafeBorrowResult { + fn from(e: GuestError) -> Self { + UnsafeBorrowResult::Err(e) + } +} + /// A smart pointer to an shareable `str` in guest memory. /// Usable as a `&'a str` via [`std::ops::Deref`]. pub struct GuestStr<'a> { diff --git a/crates/wiggle/tests/wasi.rs b/crates/wiggle/tests/wasi.rs index 9a0783c1555c..6f0b4880ff3c 100644 --- a/crates/wiggle/tests/wasi.rs +++ b/crates/wiggle/tests/wasi.rs @@ -147,7 +147,10 @@ impl<'a> crate::wasi_snapshot_preview1::WasiSnapshotPreview1 for WasiCtx<'a> { let len: u32 = iov.buf_len; let buf: GuestPtr<[u8]> = base.as_array(len); // GuestSlice will remain borrowed until dropped: - let slice = buf.as_slice().expect("borrow slice from iovec"); + let slice = buf + .as_slice() + .expect("borrow slice from iovec") + .expect("expected non-shared memory"); slices.push(slice); } println!("iovec slices: [");