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..75a2fe0f 100644 --- a/src/features/impl_std.rs +++ b/src/features/impl_std.rs @@ -199,7 +199,10 @@ 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/std.rs b/tests/std.rs index 1da4aa2b..13056b8b 100644 --- a/tests/std.rs +++ b/tests/std.rs @@ -119,3 +119,18 @@ fn test_std_commons() { assert_eq!(path, decoded); assert_eq!(len, 21); } + +#[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), + } + ); +}