From 24eefcc5b01dca9391bee5fe2efc94a69aba5ad4 Mon Sep 17 00:00:00 2001 From: Alan Somers Date: Fri, 25 Nov 2016 15:36:37 -0700 Subject: [PATCH] Fix use-after-free in select Also, fix the TimeSpec::cmp and TimeVal::cmp methods, and fix some formatting --- src/sys/select.rs | 2 +- src/sys/time.rs | 59 ++++++++++++++++++++++++++++++----------------- 2 files changed, 39 insertions(+), 22 deletions(-) diff --git a/src/sys/select.rs b/src/sys/select.rs index c9e925dd35..1d9a76c1d4 100644 --- a/src/sys/select.rs +++ b/src/sys/select.rs @@ -76,7 +76,7 @@ pub fn select(nfds: c_int, let readfds = readfds.map(|set| set as *mut FdSet).unwrap_or(null_mut()); let writefds = writefds.map(|set| set as *mut FdSet).unwrap_or(null_mut()); let errorfds = errorfds.map(|set| set as *mut FdSet).unwrap_or(null_mut()); - let timeout = timeout.map(|tv| &mut tv.timeval() as *mut timeval) + let timeout = timeout.map(|tv| tv as *mut TimeVal as *mut timeval) .unwrap_or(null_mut()); let res = unsafe { diff --git a/src/sys/time.rs b/src/sys/time.rs index 21eb87bbf3..9048a3ab41 100644 --- a/src/sys/time.rs +++ b/src/sys/time.rs @@ -10,14 +10,14 @@ pub trait TimeValLike: Sized { #[inline] fn hours(hours: i64) -> Self { let secs = hours.checked_mul(SECS_PER_HOUR) - .expect("TimeVal::hours ouf of bounds"); + .expect("TimeValLike::hours ouf of bounds"); Self::seconds(secs) } #[inline] fn minutes(minutes: i64) -> Self { let secs = minutes.checked_mul(SECS_PER_MINUTE) - .expect("TimeVal::minutes out of bounds"); + .expect("TimeValLike::minutes out of bounds"); Self::seconds(secs) } @@ -83,9 +83,9 @@ impl cmp::Ord for TimeSpec { // normalized. That is, tv_nsec must always be within [0, 1_000_000_000) fn cmp(&self, other: &TimeSpec) -> cmp::Ordering { if self.tv_sec() == other.tv_sec() { - self.tv_sec().cmp(&other.tv_sec()) - } else { self.tv_nsec().cmp(&other.tv_nsec()) + } else { + self.tv_sec().cmp(&other.tv_sec()) } } } @@ -99,7 +99,8 @@ impl cmp::PartialOrd for TimeSpec { impl TimeValLike for TimeSpec { #[inline] fn seconds(seconds: i64) -> TimeSpec { - assert!(seconds >= TS_MIN_SECONDS && seconds <= TS_MAX_SECONDS, "TimeSpec out of bounds; seconds={}", seconds); + assert!(seconds >= TS_MIN_SECONDS && seconds <= TS_MAX_SECONDS, + "TimeSpec out of bounds; seconds={}", seconds); TimeSpec(timespec {tv_sec: seconds as time_t, tv_nsec: 0 }) } @@ -124,7 +125,8 @@ impl TimeValLike for TimeSpec { #[inline] fn nanoseconds(nanoseconds: i64) -> TimeSpec { let (secs, nanos) = div_mod_floor_64(nanoseconds, NANOS_PER_SEC); - assert!(secs >= TS_MIN_SECONDS && secs <= TS_MAX_SECONDS, "TimeSpec out of bounds"); + assert!(secs >= TS_MIN_SECONDS && secs <= TS_MAX_SECONDS, + "TimeSpec out of bounds"); TimeSpec(timespec {tv_sec: secs as time_t, tv_nsec: nanos as c_long }) } @@ -161,10 +163,6 @@ impl TimeSpec { } } - pub fn timespec(&self) -> timespec{ - self.0 - } - pub fn tv_sec(&self) -> time_t { self.0.tv_sec } @@ -290,9 +288,9 @@ impl cmp::Ord for TimeVal { // normalized. That is, tv_usec must always be within [0, 1_000_000) fn cmp(&self, other: &TimeVal) -> cmp::Ordering { if self.tv_sec() == other.tv_sec() { - self.tv_sec().cmp(&other.tv_sec()) - } else { self.tv_usec().cmp(&other.tv_usec()) + } else { + self.tv_sec().cmp(&other.tv_sec()) } } } @@ -306,7 +304,8 @@ impl cmp::PartialOrd for TimeVal { impl TimeValLike for TimeVal { #[inline] fn seconds(seconds: i64) -> TimeVal { - assert!(seconds >= TV_MIN_SECONDS && seconds <= TV_MAX_SECONDS, "TimeVal out of bounds; seconds={}", seconds); + assert!(seconds >= TV_MIN_SECONDS && seconds <= TV_MAX_SECONDS, + "TimeVal out of bounds; seconds={}", seconds); TimeVal(timeval {tv_sec: seconds as time_t, tv_usec: 0 }) } @@ -322,7 +321,8 @@ impl TimeValLike for TimeVal { #[inline] fn microseconds(microseconds: i64) -> TimeVal { let (secs, micros) = div_mod_floor_64(microseconds, MICROS_PER_SEC); - assert!(secs >= TV_MIN_SECONDS && secs <= TV_MAX_SECONDS, "TimeVal out of bounds"); + assert!(secs >= TV_MIN_SECONDS && secs <= TV_MAX_SECONDS, + "TimeVal out of bounds"); TimeVal(timeval {tv_sec: secs as time_t, tv_usec: micros as suseconds_t }) } @@ -333,7 +333,8 @@ impl TimeValLike for TimeVal { fn nanoseconds(nanoseconds: i64) -> TimeVal { let microseconds = nanoseconds / 1000; let (secs, micros) = div_mod_floor_64(microseconds, MICROS_PER_SEC); - assert!(secs >= TV_MIN_SECONDS && secs <= TV_MAX_SECONDS, "TimeVal out of bounds"); + assert!(secs >= TV_MIN_SECONDS && secs <= TV_MAX_SECONDS, + "TimeVal out of bounds"); TimeVal(timeval {tv_sec: secs as time_t, tv_usec: micros as suseconds_t }) } @@ -370,10 +371,6 @@ impl TimeVal { } } - pub fn timeval(&self) -> timeval{ - self.0 - } - pub fn tv_sec(&self) -> time_t { self.0.tv_sec } @@ -492,7 +489,8 @@ mod test { #[test] pub fn test_timespec() { assert!(TimeSpec::seconds(1) != TimeSpec::zero()); - assert_eq!(TimeSpec::seconds(1) + TimeSpec::seconds(2), TimeSpec::seconds(3)); + assert_eq!(TimeSpec::seconds(1) + TimeSpec::seconds(2), + TimeSpec::seconds(3)); assert_eq!(TimeSpec::minutes(3) + TimeSpec::seconds(2), TimeSpec::seconds(182)); } @@ -505,6 +503,15 @@ mod test { assert_eq!(a, -b); } + #[test] + pub fn test_timespec_ord() { + assert!(TimeSpec::seconds(1) == TimeSpec::nanoseconds(1_000_000_000)); + assert!(TimeSpec::seconds(1) < TimeSpec::nanoseconds(1_000_000_001)); + assert!(TimeSpec::seconds(1) > TimeSpec::nanoseconds(999_999_999)); + assert!(TimeSpec::seconds(-1) < TimeSpec::nanoseconds(-999_999_999)); + assert!(TimeSpec::seconds(-1) > TimeSpec::nanoseconds(-1_000_000_001)); + } + #[test] pub fn test_timespec_fmt() { assert_eq!(TimeSpec::zero().to_string(), "0 seconds"); @@ -518,11 +525,21 @@ mod test { #[test] pub fn test_timeval() { assert!(TimeVal::seconds(1) != TimeVal::zero()); - assert_eq!(TimeVal::seconds(1) + TimeVal::seconds(2), TimeVal::seconds(3)); + assert_eq!(TimeVal::seconds(1) + TimeVal::seconds(2), + TimeVal::seconds(3)); assert_eq!(TimeVal::minutes(3) + TimeVal::seconds(2), TimeVal::seconds(182)); } + #[test] + pub fn test_timeval_ord() { + assert!(TimeVal::seconds(1) == TimeVal::microseconds(1_000_000)); + assert!(TimeVal::seconds(1) < TimeVal::microseconds(1_000_001)); + assert!(TimeVal::seconds(1) > TimeVal::microseconds(999_999)); + assert!(TimeVal::seconds(-1) < TimeVal::microseconds(-999_999)); + assert!(TimeVal::seconds(-1) > TimeVal::microseconds(-1_000_001)); + } + #[test] pub fn test_timeval_neg() { let a = TimeVal::seconds(1) + TimeVal::microseconds(123);