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.
This commit is contained in:
Alex Crichton
2022-06-07 12:51:32 -05:00
committed by GitHub
parent 11ff9650e5
commit 479def00b9
2 changed files with 42 additions and 64 deletions

View File

@@ -712,11 +712,7 @@ macro_rules! integers {
unsafe impl Lift for $primitive {
#[inline]
fn lift(_store: &StoreOpaque, _options: &Options, src: &Self::Lower) -> Result<Self> {
// 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<Self> {
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<Self> {
match bytes[0] {
0 => Ok(false),
1 => Ok(true),
_ => bail!("invalid boolean value"),
_ => Ok(true),
}
}
}

View File

@@ -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(())