diff options
author | Nora Widdecke <nora@sequoia-pgp.org> | 2021-02-25 23:25:09 +0100 |
---|---|---|
committer | Nora Widdecke <nora@sequoia-pgp.org> | 2021-03-05 13:32:42 +0100 |
commit | 7803b81158a536d465a958a4b9175dd27e08f35d (patch) | |
tree | 168f94dc6922322f6e134a3eaea2996e8bb77cf4 /openpgp/src/types | |
parent | cbef891e687717b2c41f300f39a9ed9d42459e3c (diff) |
openpgp: Fix SystemTime from Timestamp on 32bit.
- SystemTime's underlying datatype may be only `i32`, e.g. on 32bit Unix.
As OpenPGP's timestamp datatype is `u32`, there are timestamps (`i32::MAX + 1`
to `u32::MAX`) which are not representable on such systems.
- To keep the API stable, instead of making the conversion fallible,
clamp those too large values to i32::MAX.
Diffstat (limited to 'openpgp/src/types')
-rw-r--r-- | openpgp/src/types/timestamp.rs | 27 |
1 files changed, 26 insertions, 1 deletions
diff --git a/openpgp/src/types/timestamp.rs b/openpgp/src/types/timestamp.rs index a9374dcc..c253efbe 100644 --- a/openpgp/src/types/timestamp.rs +++ b/openpgp/src/types/timestamp.rs @@ -91,9 +91,15 @@ impl TryFrom<SystemTime> for Timestamp { } } +/// SystemTime's underlying datatype may be only `i32`, e.g. on 32bit Unix. +/// As OpenPGP's timestamp datatype is `u32`, there are timestamps (`i32::MAX + 1` +/// to `u32::MAX`) which are not representable on such systems. +/// +/// In this case, the result is clamped to `i32::MAX`. impl From<Timestamp> for SystemTime { fn from(t: Timestamp) -> Self { - UNIX_EPOCH + SystemDuration::new(t.0 as u64, 0) + UNIX_EPOCH.checked_add(SystemDuration::new(t.0 as u64, 0)) + .unwrap_or_else(|| UNIX_EPOCH + SystemDuration::new(i32::MAX as u64, 0)) } } @@ -661,4 +667,23 @@ mod tests { Ok(()) } + + // #668 + // Ensure that, on x86, Timestamps between i32::MAX + 1 and u32::MAX are + // clamped down to i32::MAX, and values below are not altered. + #[cfg(target_arch = "x86")] + #[test] + fn system_time_32_bit() -> Result<()> { + let t1 = Timestamp::from(u32::MAX); + let t2 = Timestamp::from(i32::MAX as u32 + 1); + assert_eq!(SystemTime::from(t1), + UNIX_EPOCH + SystemDuration::new(i32::MAX as u64, 0)); + assert_eq!(SystemTime::from(t2), + UNIX_EPOCH + SystemDuration::new(i32::MAX as u64, 0)); + + let t3 = Timestamp::from(i32::MAX as u32 - 1); + assert!(SystemTime::from(t3), + UNIX_EPOCH + SystemDuration::new(i32::MAX as u64 - 1, 0)); + Ok(()) + } } |