diff --git a/src/de/impls.rs b/src/de/impls.rs index b53e7ff..b7dfecc 100644 --- a/src/de/impls.rs +++ b/src/de/impls.rs @@ -172,10 +172,15 @@ impl Decode for usize { IntEncoding::Fixed => { let mut bytes = [0u8; 8]; decoder.reader().read(&mut bytes)?; - Ok(match D::C::ENDIAN { + + let value = match D::C::ENDIAN { Endian::Little => u64::from_le_bytes(bytes), Endian::Big => u64::from_be_bytes(bytes), - } as usize) + }; + + value + .try_into() + .map_err(|_| DecodeError::OutsideUsizeRange(value)) } } } diff --git a/src/de/mod.rs b/src/de/mod.rs index b107336..a25d372 100644 --- a/src/de/mod.rs +++ b/src/de/mod.rs @@ -149,7 +149,8 @@ pub trait Decoder: Sealed { /// # } /// impl Decode for Container { /// fn decode(decoder: &mut D) -> Result { - /// let len = u64::decode(decoder)? as usize; + /// let len = u64::decode(decoder)?; + /// let len: usize = len.try_into().map_err(|_| DecodeError::OutsideUsizeRange(len))?; /// // Make sure we don't allocate too much memory /// decoder.claim_bytes_read(len * core::mem::size_of::()); /// @@ -236,5 +237,7 @@ pub(crate) fn decode_option_variant( /// Decodes the length of any slice, container, etc from the decoder #[inline] pub(crate) fn decode_slice_len(decoder: &mut D) -> Result { - u64::decode(decoder).map(|v| v as usize) + let v = u64::decode(decoder)?; + + v.try_into().map_err(|_| DecodeError::OutsideUsizeRange(v)) } diff --git a/src/error.rs b/src/error.rs index 9262c41..17fee05 100644 --- a/src/error.rs +++ b/src/error.rs @@ -116,6 +116,14 @@ pub enum DecodeError { found: usize, }, + /// The encoded value is outside of the range of the target usize type. + /// + /// This can happen if an usize was encoded on an architecture with a larger + /// usize type and then decoded on an architecture with a smaller one. For + /// example going from a 64 bit architecture to a 32 or 16 bit one may + /// cause this error. + OutsideUsizeRange(u64), + /// Tried to decode an enum with no variants EmptyEnum { /// The type that was being decoded