From 479def00b9e86c50bb55dc8f2edaa3bb40b4660e Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Tue, 7 Jun 2022 12:51:32 -0500 Subject: [PATCH] Update lifting for integers and bools (#4237) This commit updates lifting for integer types and boolean types to account for WebAssembly/component-model#35 where extra bits are now discarded instead of being validated as all zero. --- crates/wasmtime/src/component/func/typed.rs | 12 +-- tests/all/component_model/func.rs | 94 +++++++++------------ 2 files changed, 42 insertions(+), 64 deletions(-) diff --git a/crates/wasmtime/src/component/func/typed.rs b/crates/wasmtime/src/component/func/typed.rs index 97b337a55f..9356f6f656 100644 --- a/crates/wasmtime/src/component/func/typed.rs +++ b/crates/wasmtime/src/component/func/typed.rs @@ -712,11 +712,7 @@ macro_rules! integers { unsafe impl Lift for $primitive { #[inline] fn lift(_store: &StoreOpaque, _options: &Options, src: &Self::Lower) -> Result { - // Perform a lossless cast from our field storage to the - // destination type. Note that `try_from` here is load bearing - // which rejects conversions like `500u32` to `u8` because - // that's out-of-bounds for `u8`. - Ok($primitive::try_from(src.$get())?) + Ok(src.$get() as $primitive) } #[inline] @@ -852,8 +848,7 @@ unsafe impl Lift for bool { fn lift(_store: &StoreOpaque, _options: &Options, src: &Self::Lower) -> Result { match src.get_i32() { 0 => Ok(false), - 1 => Ok(true), - _ => bail!("invalid boolean value"), + _ => Ok(true), } } @@ -861,8 +856,7 @@ unsafe impl Lift for bool { fn load(_mem: &Memory<'_>, bytes: &[u8]) -> Result { match bytes[0] { 0 => Ok(false), - 1 => Ok(true), - _ => bail!("invalid boolean value"), + _ => Ok(true), } } } diff --git a/tests/all/component_model/func.rs b/tests/all/component_model/func.rs index 7043421fb1..220679e630 100644 --- a/tests/all/component_model/func.rs +++ b/tests/all/component_model/func.rs @@ -364,15 +364,12 @@ fn integers() -> Result<()> { 0 ); - // Returning -1 should fail for u8 and u16, but succeed for all other types. - let err = instance - .get_typed_func::<(), u8, _>(&mut store, "retm1-u8")? - .call(&mut store, ()) - .unwrap_err(); - assert!( - err.to_string().contains("out of range integral type"), - "{}", - err + // Returning -1 should reinterpret the bytes as defined by each type. + assert_eq!( + instance + .get_typed_func::<(), u8, _>(&mut store, "retm1-u8")? + .call(&mut store, ())?, + 0xff ); assert_eq!( instance @@ -380,14 +377,11 @@ fn integers() -> Result<()> { .call(&mut store, ())?, -1 ); - let err = instance - .get_typed_func::<(), u16, _>(&mut store, "retm1-u16")? - .call(&mut store, ()) - .unwrap_err(); - assert!( - err.to_string().contains("out of range integral type"), - "{}", - err + assert_eq!( + instance + .get_typed_func::<(), u16, _>(&mut store, "retm1-u16")? + .call(&mut store, ())?, + 0xffff ); assert_eq!( instance @@ -420,54 +414,43 @@ fn integers() -> Result<()> { -1 ); - // Returning 100000 should fail for small primitives but succeed for 32-bit. - let err = instance - .get_typed_func::<(), u8, _>(&mut store, "retbig-u8")? - .call(&mut store, ()) - .unwrap_err(); - assert!( - err.to_string().contains("out of range integral type"), - "{}", - err + // Returning 100000 should chop off bytes as necessary + let ret: u32 = 100000; + assert_eq!( + instance + .get_typed_func::<(), u8, _>(&mut store, "retbig-u8")? + .call(&mut store, ())?, + ret as u8, ); - let err = instance - .get_typed_func::<(), i8, _>(&mut store, "retbig-s8")? - .call(&mut store, ()) - .unwrap_err(); - assert!( - err.to_string().contains("out of range integral type"), - "{}", - err + assert_eq!( + instance + .get_typed_func::<(), i8, _>(&mut store, "retbig-s8")? + .call(&mut store, ())?, + ret as i8, ); - let err = instance - .get_typed_func::<(), u16, _>(&mut store, "retbig-u16")? - .call(&mut store, ()) - .unwrap_err(); - assert!( - err.to_string().contains("out of range integral type"), - "{}", - err + assert_eq!( + instance + .get_typed_func::<(), u16, _>(&mut store, "retbig-u16")? + .call(&mut store, ())?, + ret as u16, ); - let err = instance - .get_typed_func::<(), i16, _>(&mut store, "retbig-s16")? - .call(&mut store, ()) - .unwrap_err(); - assert!( - err.to_string().contains("out of range integral type"), - "{}", - err + assert_eq!( + instance + .get_typed_func::<(), i16, _>(&mut store, "retbig-s16")? + .call(&mut store, ())?, + ret as i16, ); assert_eq!( instance .get_typed_func::<(), u32, _>(&mut store, "retbig-u32")? .call(&mut store, ())?, - 100000 + ret, ); assert_eq!( instance .get_typed_func::<(), i32, _>(&mut store, "retbig-s32")? .call(&mut store, ())?, - 100000 + ret as i32, ); Ok(()) @@ -622,8 +605,7 @@ fn bools() -> Result<()> { assert_eq!(bool_to_u32.call(&mut store, (true,))?, 1); assert_eq!(u32_to_bool.call(&mut store, (0,))?, false); assert_eq!(u32_to_bool.call(&mut store, (1,))?, true); - let err = u32_to_bool.call(&mut store, (2,)).unwrap_err(); - assert!(err.to_string().contains("invalid boolean"), "{}", err); + assert_eq!(u32_to_bool.call(&mut store, (2,))?, true); Ok(()) } @@ -1305,7 +1287,9 @@ fn char_bool_memory() -> Result<()> { let ret = func.call(&mut store, (1, '🍰' as u32))?; assert_eq!(ret, (true, '🍰')); - assert!(func.call(&mut store, (2, 'a' as u32)).is_err()); + let ret = func.call(&mut store, (2, 'a' as u32))?; + assert_eq!(ret, (true, 'a')); + assert!(func.call(&mut store, (0, 0xd800)).is_err()); Ok(())