Skip to content

Commit f462312

Browse files
committed
std: respect the bounds of the platform's data structures when performing time arithmetic
1 parent 5b9007b commit f462312

File tree

10 files changed

+220
-176
lines changed

10 files changed

+220
-176
lines changed

library/std/src/sys/fs/wasi.rs

Lines changed: 2 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -536,17 +536,9 @@ impl File {
536536
}
537537

538538
pub fn set_times(&self, times: FileTimes) -> io::Result<()> {
539-
let to_timestamp = |time: Option<SystemTime>| match time {
540-
Some(time) if let Some(ts) = time.to_wasi_timestamp() => Ok(ts),
541-
Some(_) => Err(io::const_error!(
542-
io::ErrorKind::InvalidInput,
543-
"timestamp is too large to set as a file time",
544-
)),
545-
None => Ok(0),
546-
};
547539
self.fd.filestat_set_times(
548-
to_timestamp(times.accessed)?,
549-
to_timestamp(times.modified)?,
540+
times.accessed.map_or(0, SystemTime::to_wasi_timestamp),
541+
times.modified.map_or(0, SystemTime::to_wasi_timestamp),
550542
times.accessed.map_or(0, |_| wasi::FSTFLAGS_ATIM)
551543
| times.modified.map_or(0, |_| wasi::FSTFLAGS_MTIM),
552544
)

library/std/src/sys/pal/sgx/abi/usercalls/mod.rs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -266,9 +266,8 @@ pub fn send(event_set: u64, tcs: Option<Tcs>) -> IoResult<()> {
266266

267267
/// Usercall `insecure_time`. See the ABI documentation for more information.
268268
#[unstable(feature = "sgx_platform", issue = "56975")]
269-
pub fn insecure_time() -> Duration {
270-
let t = unsafe { raw::insecure_time().0 };
271-
Duration::new(t / 1_000_000_000, (t % 1_000_000_000) as _)
269+
pub fn insecure_time() -> u64 {
270+
unsafe { raw::insecure_time().0 }
272271
}
273272

274273
/// Usercall `alloc`. See the ABI documentation for more information.

library/std/src/sys/pal/sgx/time.rs

Lines changed: 27 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -2,45 +2,61 @@ use super::abi::usercalls;
22
use crate::time::Duration;
33

44
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug, Hash)]
5-
pub struct Instant(Duration);
5+
pub struct Instant {
6+
nanos: u64,
7+
}
68

79
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug, Hash)]
8-
pub struct SystemTime(Duration);
10+
pub struct SystemTime {
11+
nanos: u64,
12+
}
913

10-
pub const UNIX_EPOCH: SystemTime = SystemTime(Duration::from_secs(0));
14+
pub const UNIX_EPOCH: SystemTime = SystemTime { nanos: 0 };
1115

1216
impl Instant {
1317
pub fn now() -> Instant {
14-
Instant(usercalls::insecure_time())
18+
Instant { nanos: usercalls::insecure_time() }
1519
}
1620

1721
pub fn checked_sub_instant(&self, other: &Instant) -> Option<Duration> {
18-
self.0.checked_sub(other.0)
22+
let nanos = self.nanos.checked_sub(other.nanos)?;
23+
Some(Duration::from_nanos(nanos))
1924
}
2025

2126
pub fn checked_add_duration(&self, other: &Duration) -> Option<Instant> {
22-
Some(Instant(self.0.checked_add(*other)?))
27+
let to_add = other.as_nanos().try_into().ok()?;
28+
let nanos = self.nanos.checked_add(to_add)?;
29+
Some(Instant { nanos })
2330
}
2431

2532
pub fn checked_sub_duration(&self, other: &Duration) -> Option<Instant> {
26-
Some(Instant(self.0.checked_sub(*other)?))
33+
let to_sub = other.as_nanos().try_into().ok()?;
34+
let nanos = self.nanos.checked_sub(to_sub)?;
35+
Some(Instant { nanos })
2736
}
2837
}
2938

3039
impl SystemTime {
3140
pub fn now() -> SystemTime {
32-
SystemTime(usercalls::insecure_time())
41+
SystemTime { nanos: usercalls::insecure_time() }
3342
}
3443

3544
pub fn sub_time(&self, other: &SystemTime) -> Result<Duration, Duration> {
36-
self.0.checked_sub(other.0).ok_or_else(|| other.0 - self.0)
45+
self.nanos
46+
.checked_sub(other.nanos)
47+
.map(Duration::from_nanos)
48+
.ok_or_else(|| Duration::from_nanos(other.nanos - self.nanos))
3749
}
3850

3951
pub fn checked_add_duration(&self, other: &Duration) -> Option<SystemTime> {
40-
Some(SystemTime(self.0.checked_add(*other)?))
52+
let to_add = other.as_nanos().try_into().ok()?;
53+
let nanos = self.nanos.checked_add(to_add)?;
54+
Some(SystemTime { nanos })
4155
}
4256

4357
pub fn checked_sub_duration(&self, other: &Duration) -> Option<SystemTime> {
44-
Some(SystemTime(self.0.checked_sub(*other)?))
58+
let to_sub = other.as_nanos().try_into().ok()?;
59+
let nanos = self.nanos.checked_sub(to_sub)?;
60+
Some(SystemTime { nanos })
4561
}
4662
}

library/std/src/sys/pal/unsupported/time.rs

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
use crate::time::Duration;
22

33
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug, Hash)]
4-
pub struct Instant(Duration);
4+
#[allow(unreachable_code)] // Generated by the PartialEq derive.
5+
pub struct Instant(!);
56

67
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug, Hash)]
78
pub struct SystemTime(Duration);
@@ -13,16 +14,16 @@ impl Instant {
1314
panic!("time not implemented on this platform")
1415
}
1516

16-
pub fn checked_sub_instant(&self, other: &Instant) -> Option<Duration> {
17-
self.0.checked_sub(other.0)
17+
pub fn checked_sub_instant(&self, _other: &Instant) -> Option<Duration> {
18+
self.0
1819
}
1920

20-
pub fn checked_add_duration(&self, other: &Duration) -> Option<Instant> {
21-
Some(Instant(self.0.checked_add(*other)?))
21+
pub fn checked_add_duration(&self, _other: &Duration) -> Option<Instant> {
22+
self.0
2223
}
2324

24-
pub fn checked_sub_duration(&self, other: &Duration) -> Option<Instant> {
25-
Some(Instant(self.0.checked_sub(*other)?))
25+
pub fn checked_sub_duration(&self, _other: &Duration) -> Option<Instant> {
26+
self.0
2627
}
2728
}
2829

library/std/src/sys/pal/vexos/time.rs

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,23 +6,30 @@ mod unsupported_time;
66
pub use unsupported_time::{SystemTime, UNIX_EPOCH};
77

88
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug, Hash)]
9-
pub struct Instant(Duration);
9+
pub struct Instant {
10+
micros: u64,
11+
}
1012

1113
impl Instant {
1214
pub fn now() -> Instant {
1315
let micros = unsafe { vex_sdk::vexSystemHighResTimeGet() };
14-
Self(Duration::from_micros(micros))
16+
Self { micros }
1517
}
1618

1719
pub fn checked_sub_instant(&self, other: &Instant) -> Option<Duration> {
18-
self.0.checked_sub(other.0)
20+
let micros = self.micros.checked_sub(other.micros)?;
21+
Some(Duration::from_micros(micros))
1922
}
2023

2124
pub fn checked_add_duration(&self, other: &Duration) -> Option<Instant> {
22-
Some(Instant(self.0.checked_add(*other)?))
25+
let to_add = other.as_micros().try_into().ok()?;
26+
let micros = self.micros.checked_add(to_add)?;
27+
Some(Instant { micros })
2328
}
2429

2530
pub fn checked_sub_duration(&self, other: &Duration) -> Option<Instant> {
26-
Some(Instant(self.0.checked_sub(*other)?))
31+
let to_sub = other.as_micros().try_into().ok()?;
32+
let micros = self.micros.checked_sub(to_sub)?;
33+
Some(Instant { micros })
2734
}
2835
}

library/std/src/sys/pal/wasip1/time.rs

Lines changed: 33 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -3,63 +3,78 @@
33
use crate::time::Duration;
44

55
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug, Hash)]
6-
pub struct Instant(Duration);
6+
pub struct Instant {
7+
nanos: wasi::Timestamp,
8+
}
79

810
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug, Hash)]
9-
pub struct SystemTime(Duration);
11+
pub struct SystemTime {
12+
nanos: wasi::Timestamp,
13+
}
1014

11-
pub const UNIX_EPOCH: SystemTime = SystemTime(Duration::from_secs(0));
15+
pub const UNIX_EPOCH: SystemTime = SystemTime { nanos: 0 };
1216

13-
fn current_time(clock: wasi::Clockid) -> Duration {
14-
let ts = unsafe {
17+
fn current_time(clock: wasi::Clockid) -> wasi::Timestamp {
18+
unsafe {
1519
wasi::clock_time_get(
1620
clock, 1, // precision... seems ignored though?
1721
)
1822
.unwrap()
19-
};
20-
Duration::new((ts / 1_000_000_000) as u64, (ts % 1_000_000_000) as u32)
23+
}
2124
}
2225

2326
impl Instant {
2427
pub fn now() -> Instant {
25-
Instant(current_time(wasi::CLOCKID_MONOTONIC))
28+
Instant { nanos: current_time(wasi::CLOCKID_MONOTONIC) }
2629
}
2730

2831
pub fn checked_sub_instant(&self, other: &Instant) -> Option<Duration> {
29-
self.0.checked_sub(other.0)
32+
let nanos = self.nanos.checked_sub(other.nanos)?;
33+
Some(Duration::from_nanos(nanos))
3034
}
3135

3236
pub fn checked_add_duration(&self, other: &Duration) -> Option<Instant> {
33-
Some(Instant(self.0.checked_add(*other)?))
37+
let to_add = other.as_nanos().try_into().ok()?;
38+
let nanos = self.nanos.checked_add(to_add)?;
39+
Some(Instant { nanos })
3440
}
3541

3642
pub fn checked_sub_duration(&self, other: &Duration) -> Option<Instant> {
37-
Some(Instant(self.0.checked_sub(*other)?))
43+
let to_sub = other.as_nanos().try_into().ok()?;
44+
let nanos = self.nanos.checked_sub(to_sub)?;
45+
Some(Instant { nanos })
3846
}
3947
}
4048

4149
impl SystemTime {
4250
pub fn now() -> SystemTime {
43-
SystemTime(current_time(wasi::CLOCKID_REALTIME))
51+
SystemTime { nanos: current_time(wasi::CLOCKID_REALTIME) }
4452
}
4553

4654
pub fn from_wasi_timestamp(ts: wasi::Timestamp) -> SystemTime {
47-
SystemTime(Duration::from_nanos(ts))
55+
SystemTime { nanos: ts }
4856
}
4957

50-
pub fn to_wasi_timestamp(&self) -> Option<wasi::Timestamp> {
51-
self.0.as_nanos().try_into().ok()
58+
pub fn to_wasi_timestamp(self) -> wasi::Timestamp {
59+
self.nanos
5260
}
5361

5462
pub fn sub_time(&self, other: &SystemTime) -> Result<Duration, Duration> {
55-
self.0.checked_sub(other.0).ok_or_else(|| other.0 - self.0)
63+
self.nanos
64+
.checked_sub(other.nanos)
65+
.map(Duration::from_nanos)
66+
.ok_or_else(|| Duration::from_nanos(other.nanos - self.nanos))
5667
}
5768

5869
pub fn checked_add_duration(&self, other: &Duration) -> Option<SystemTime> {
59-
Some(SystemTime(self.0.checked_add(*other)?))
70+
let to_add = other.as_nanos().try_into().ok()?;
71+
let nanos = self.nanos.checked_add(to_add)?;
72+
Some(SystemTime { nanos })
6073
}
6174

6275
pub fn checked_sub_duration(&self, other: &Duration) -> Option<SystemTime> {
63-
Some(SystemTime(self.0.checked_sub(*other)?))
76+
let to_sub = other.as_nanos().try_into().ok()?;
77+
let nanos = self.nanos.checked_sub(to_sub)?;
78+
Some(SystemTime { nanos })
6479
}
6580
}

library/std/src/sys/pal/wasip2/time.rs

Lines changed: 21 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,32 +1,41 @@
11
use crate::time::Duration;
22

33
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug, Hash)]
4-
pub struct Instant(Duration);
4+
pub struct Instant {
5+
nanos: wasip2::clocks::monotonic_clock::Instant,
6+
}
57

8+
// WASIp2's datetime is identical to our `Duration` in terms of its representable
9+
// range, so use `Duration` to simplify the implementation below.
610
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug, Hash)]
711
pub struct SystemTime(Duration);
812

913
pub const UNIX_EPOCH: SystemTime = SystemTime(Duration::from_secs(0));
1014

1115
impl Instant {
1216
pub fn now() -> Instant {
13-
Instant(Duration::from_nanos(wasip2::clocks::monotonic_clock::now()))
17+
Instant { nanos: wasip2::clocks::monotonic_clock::now() }
18+
}
19+
20+
pub fn to_wasi_instant(self) -> wasip2::clocks::monotonic_clock::Instant {
21+
self.nanos
1422
}
1523

1624
pub fn checked_sub_instant(&self, other: &Instant) -> Option<Duration> {
17-
self.0.checked_sub(other.0)
25+
let nanos = self.nanos.checked_sub(other.nanos)?;
26+
Some(Duration::from_nanos(nanos))
1827
}
1928

2029
pub fn checked_add_duration(&self, other: &Duration) -> Option<Instant> {
21-
Some(Instant(self.0.checked_add(*other)?))
30+
let to_add = other.as_nanos().try_into().ok()?;
31+
let nanos = self.nanos.checked_add(to_add)?;
32+
Some(Instant { nanos })
2233
}
2334

2435
pub fn checked_sub_duration(&self, other: &Duration) -> Option<Instant> {
25-
Some(Instant(self.0.checked_sub(*other)?))
26-
}
27-
28-
pub(crate) fn as_duration(&self) -> &Duration {
29-
&self.0
36+
let to_sub = other.as_nanos().try_into().ok()?;
37+
let nanos = self.nanos.checked_sub(to_sub)?;
38+
Some(Instant { nanos })
3039
}
3140
}
3241

@@ -40,8 +49,9 @@ impl SystemTime {
4049
SystemTime(Duration::from_nanos(ts))
4150
}
4251

43-
pub fn to_wasi_timestamp(&self) -> Option<wasi::Timestamp> {
44-
self.0.as_nanos().try_into().ok()
52+
pub fn to_wasi_timestamp(self) -> wasi::Timestamp {
53+
// FIXME: use the WASIp2 filesystem proposal, which accepts a WASIp2 datetime.
54+
self.0.as_nanos().try_into().expect("error converting WASIp2 datetime to WASIp1 timestamp")
4555
}
4656

4757
pub fn sub_time(&self, other: &SystemTime) -> Result<Duration, Duration> {

0 commit comments

Comments
 (0)