1
Fork 0

Properly detect overflow in Instance +/- Duration.

Avoid unchecked cast from `u64` to `i64`. Use `try_into()` for checked
cast. (On Unix, cast to `time_t` instead of `i64`.)
This commit is contained in:
kennytm 2017-09-01 01:16:24 +08:00
parent a6a9d4c5fd
commit 8410ca6632
No known key found for this signature in database
GPG key ID: FEF6C8051D0E013C
5 changed files with 72 additions and 17 deletions

View file

@ -13,6 +13,7 @@ use libc;
use time::Duration;
pub use self::inner::{Instant, SystemTime, UNIX_EPOCH};
use convert::TryInto;
const NSEC_PER_SEC: u64 = 1_000_000_000;
@ -41,8 +42,12 @@ impl Timespec {
}
fn add_duration(&self, other: &Duration) -> Timespec {
let secs = (self.t.tv_sec as i64).checked_add(other.as_secs() as i64);
let mut secs = secs.expect("overflow when adding duration to time");
let mut secs = other
.as_secs()
.try_into() // <- target type would be `libc::time_t`
.ok()
.and_then(|secs| self.t.tv_sec.checked_add(secs))
.expect("overflow when adding duration to time");
// Nano calculations can't overflow because nanos are <1B which fit
// in a u32.
@ -54,16 +59,19 @@ impl Timespec {
}
Timespec {
t: libc::timespec {
tv_sec: secs as libc::time_t,
tv_sec: secs,
tv_nsec: nsec as libc::c_long,
},
}
}
fn sub_duration(&self, other: &Duration) -> Timespec {
let secs = (self.t.tv_sec as i64).checked_sub(other.as_secs() as i64);
let mut secs = secs.expect("overflow when subtracting duration \
from time");
let mut secs = other
.as_secs()
.try_into() // <- target type would be `libc::time_t`
.ok()
.and_then(|secs| self.t.tv_sec.checked_sub(secs))
.expect("overflow when subtracting duration from time");
// Similar to above, nanos can't overflow.
let mut nsec = self.t.tv_nsec as i32 - other.subsec_nanos() as i32;
@ -74,7 +82,7 @@ impl Timespec {
}
Timespec {
t: libc::timespec {
tv_sec: secs as libc::time_t,
tv_sec: secs,
tv_nsec: nsec as libc::c_long,
},
}