about summary refs log tree commit diff
path: root/src/libstd/sys/windows
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2018-11-25 19:01:35 +0000
committerbors <bors@rust-lang.org>2018-11-25 19:01:35 +0000
commit6acbb5b65c06d82c867a94c54ce51dab4707ac61 (patch)
tree20692d5500836bc0d65c20e89d6b5c8d1c087629 /src/libstd/sys/windows
parent5bd451b26580de465d59ed5389209ed191b7dbdd (diff)
parentf2106d0746cdbd04ddad44c35b4e13eeced2a546 (diff)
downloadrust-6acbb5b65c06d82c867a94c54ce51dab4707ac61.tar.gz
rust-6acbb5b65c06d82c867a94c54ce51dab4707ac61.zip
Auto merge of #55527 - sgeisler:time-checked-add, r=sfackler
Implement checked_add_duration for SystemTime

[Original discussion on the rust user forum](https://users.rust-lang.org/t/std-systemtime-misses-a-checked-add-function/21785)

Since `SystemTime` is opaque there is no way to check if the result of an addition will be in bounds. That makes the `Add<Duration>` trait completely unusable with untrusted data. This is a big problem because adding a `Duration` to `UNIX_EPOCH` is the standard way of constructing a `SystemTime` from a unix timestamp.

This PR implements `checked_add_duration(&self, &Duration) -> Option<SystemTime>` for `std::time::SystemTime` and as a prerequisite also for all platform specific time structs. This also led to the refactoring of many `add_duration(&self, &Duration) -> SystemTime` functions to avoid redundancy (they now unwrap the result of `checked_add_duration`).

Some basic unit tests for the newly introduced function were added too.

I wasn't sure which stabilization attribute to add to the newly introduced function, so I just chose `#[stable(feature = "time_checked_add", since = "1.32.0")]` for now to make it compile. Please let me know how I should change it or if I violated any other conventions.

P.S.: I could only test on Linux so far, so I don't necessarily expect it to compile for all platforms.
Diffstat (limited to 'src/libstd/sys/windows')
-rw-r--r--src/libstd/sys/windows/time.rs16
1 files changed, 12 insertions, 4 deletions
diff --git a/src/libstd/sys/windows/time.rs b/src/libstd/sys/windows/time.rs
index 54bcbc76b1a..c809a0b98ac 100644
--- a/src/libstd/sys/windows/time.rs
+++ b/src/libstd/sys/windows/time.rs
@@ -128,9 +128,13 @@ impl SystemTime {
     }
 
     pub fn add_duration(&self, other: &Duration) -> SystemTime {
-        let intervals = self.intervals().checked_add(dur2intervals(other))
-                            .expect("overflow when adding duration to time");
-        SystemTime::from_intervals(intervals)
+        self.checked_add_duration(other).expect("overflow when adding duration to time")
+    }
+
+    pub fn checked_add_duration(&self, other: &Duration) -> Option<SystemTime> {
+        checked_dur2intervals(other)
+            .and_then(|d| self.intervals().checked_add(d))
+            .map(|i| SystemTime::from_intervals(i))
     }
 
     pub fn sub_duration(&self, other: &Duration) -> SystemTime {
@@ -180,11 +184,15 @@ impl Hash for SystemTime {
     }
 }
 
-fn dur2intervals(d: &Duration) -> i64 {
+fn checked_dur2intervals(d: &Duration) -> Option<i64> {
     d.as_secs()
         .checked_mul(INTERVALS_PER_SEC)
         .and_then(|i| i.checked_add(d.subsec_nanos() as u64 / 100))
         .and_then(|i| i.try_into().ok())
+}
+
+fn dur2intervals(d: &Duration) -> i64 {
+    checked_dur2intervals(d)
         .expect("overflow when converting duration to intervals")
 }