diff --git a/src/tests/mod.rs b/src/tests/mod.rs index e07c3a8..3ad8ba8 100644 --- a/src/tests/mod.rs +++ b/src/tests/mod.rs @@ -17,6 +17,19 @@ fn assert_error_properties() { assert_std_err_impl::(); } +/// Test that converting an u32 (u64) that does not fit in an i32 (i64) +/// to a RuntimeValue and back works as expected and the number remains unchanged. +#[test] +fn unsigned_to_runtime_value() { + use super::RuntimeValue; + + let overflow_i32: u32 = ::std::i32::MAX as u32 + 1; + assert_eq!(RuntimeValue::from(overflow_i32).try_into::().unwrap(), overflow_i32); + + let overflow_i64: u64 = ::std::i64::MAX as u64 + 1; + assert_eq!(RuntimeValue::from(overflow_i64).try_into::().unwrap(), overflow_i64); +} + pub fn parse_wat(source: &str) -> Module { let wasm_binary = wabt::wat2wasm(source).expect("Failed to parse wat source"); Module::from_buffer(wasm_binary).expect("Failed to load parsed module") diff --git a/src/value.rs b/src/value.rs index 08cdff2..908829b 100644 --- a/src/value.rs +++ b/src/value.rs @@ -1,6 +1,7 @@ use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt}; use nan_preserving_float::{F32, F64}; use std::io; +use std::mem::transmute; use std::{f32, i32, i64, u32, u64}; use TrapKind; @@ -188,13 +189,13 @@ impl From for RuntimeValue { impl From for RuntimeValue { fn from(val: u32) -> Self { - RuntimeValue::I32(val as i32) + RuntimeValue::I32(val.transmute_into()) } } impl From for RuntimeValue { fn from(val: u64) -> Self { - RuntimeValue::I64(val as i64) + RuntimeValue::I64(val.transmute_into()) } } @@ -403,11 +404,8 @@ macro_rules! impl_transmute_into_as { } impl_transmute_into_as!(i8, u8); -impl_transmute_into_as!(u8, i8); impl_transmute_into_as!(i32, u32); -impl_transmute_into_as!(u32, i32); impl_transmute_into_as!(i64, u64); -impl_transmute_into_as!(u64, i64); macro_rules! impl_transmute_into_npf { ($npf:ident, $float:ident, $signed:ident, $unsigned:ident) => { @@ -468,6 +466,14 @@ impl TransmuteInto for i64 { fn transmute_into(self) -> f64 { f64::from_bits(self as u64) } } +impl TransmuteInto for u32 { + fn transmute_into(self) -> i32 { unsafe { transmute(self) } } +} + +impl TransmuteInto for u64 { + fn transmute_into(self) -> i64 { unsafe { transmute(self) } } +} + impl LittleEndianConvert for i8 { fn into_little_endian(self) -> Vec { vec![self as u8]