summaryrefslogtreecommitdiffstats
path: root/openpgp/src/types/timestamp.rs
diff options
context:
space:
mode:
authorNora Widdecke <nora@sequoia-pgp.org>2021-02-25 23:25:09 +0100
committerNora Widdecke <nora@sequoia-pgp.org>2021-03-05 13:32:42 +0100
commit7803b81158a536d465a958a4b9175dd27e08f35d (patch)
tree168f94dc6922322f6e134a3eaea2996e8bb77cf4 /openpgp/src/types/timestamp.rs
parentcbef891e687717b2c41f300f39a9ed9d42459e3c (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/timestamp.rs')
-rw-r--r--openpgp/src/types/timestamp.rs27
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(())
+ }
}