diff --git a/src/error.rs b/src/error.rs index db8a9526..e24ba8b9 100644 --- a/src/error.rs +++ b/src/error.rs @@ -132,6 +132,13 @@ pub enum DecodeError { nanos: u32, }, + /// The decoder tried to decode a SystemTime and overflowed + InvalidSystemTime { + /// The duration which could not have been added to + /// [`UNIX_EPOCH`](std::time::SystemTime::UNIX_EPOCH) + duration: core::time::Duration, + }, + /// The decoder tried to decode a `CStr` or `CString`, but the incoming data contained a 0 byte #[cfg(feature = "std")] CStrNulError { diff --git a/src/features/impl_std.rs b/src/features/impl_std.rs index 9f4e1039..af33ad33 100644 --- a/src/features/impl_std.rs +++ b/src/features/impl_std.rs @@ -199,7 +199,12 @@ impl Encode for SystemTime { impl Decode for SystemTime { fn decode(decoder: D) -> Result { let duration = Duration::decode(decoder)?; - Ok(SystemTime::UNIX_EPOCH + duration) + match SystemTime::UNIX_EPOCH.checked_add(duration) { + Some(t) => Ok(t), + None => { + Err(DecodeError::InvalidSystemTime { duration }) + } + } } } diff --git a/tests/basic_types.rs b/tests/basic_types.rs index bc29ff3a..3226b734 100644 --- a/tests/basic_types.rs +++ b/tests/basic_types.rs @@ -257,3 +257,18 @@ fn test_duration_wrapping() { assert_eq!(result.subsec_nanos(), 294967295); } + +#[test] +fn test_system_time_out_of_range() { + let mut input = [0xfd, 0x90, 0x0c, 0xfd, 0xfd, 0x90, 0x0c, 0xfd, 0x90, 0x90]; + + let result: Result<(std::time::SystemTime, usize), _> = + bincode::decode_from_slice(&mut input, Configuration::standard()); + + assert_eq!( + result.unwrap_err(), + bincode::error::DecodeError::InvalidSystemTime { + duration: std::time::Duration::new(10447520527445462160, 144), + } + ); +}