Skip to content

Commit 509eec1

Browse files
committed
Auto merge of rust-lang#3653 - tiif:bug/futex_ice, r=RalfJung
Fix futex with large timeout ICE Fixes rust-lang#3647. This PR changed the type of ``nanoseconds`` from ``u64`` to ``u128``. In ``duration_since``, nanoseconds is manually converted to second by dividing it with 1e9. But overflow is still possible.
2 parents de822dc + 40182be commit 509eec1

File tree

1 file changed

+20
-8
lines changed

1 file changed

+20
-8
lines changed

src/tools/miri/src/clock.rs

+20-8
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ use std::time::{Duration, Instant as StdInstant};
66
/// This number is pretty random, but it has been shown to approximately cause
77
/// some sample programs to run within an order of magnitude of real time on desktop CPUs.
88
/// (See `tests/pass/shims/time-with-isolation*.rs`.)
9-
const NANOSECONDS_PER_BASIC_BLOCK: u64 = 5000;
9+
const NANOSECONDS_PER_BASIC_BLOCK: u128 = 5000;
1010

1111
#[derive(Debug)]
1212
pub struct Instant {
@@ -16,7 +16,7 @@ pub struct Instant {
1616
#[derive(Debug)]
1717
enum InstantKind {
1818
Host(StdInstant),
19-
Virtual { nanoseconds: u64 },
19+
Virtual { nanoseconds: u128 },
2020
}
2121

2222
impl Instant {
@@ -25,9 +25,8 @@ impl Instant {
2525
InstantKind::Host(instant) =>
2626
instant.checked_add(duration).map(|i| Instant { kind: InstantKind::Host(i) }),
2727
InstantKind::Virtual { nanoseconds } =>
28-
u128::from(nanoseconds)
28+
nanoseconds
2929
.checked_add(duration.as_nanos())
30-
.and_then(|n| u64::try_from(n).ok())
3130
.map(|nanoseconds| Instant { kind: InstantKind::Virtual { nanoseconds } }),
3231
}
3332
}
@@ -39,7 +38,17 @@ impl Instant {
3938
(
4039
InstantKind::Virtual { nanoseconds },
4140
InstantKind::Virtual { nanoseconds: earlier },
42-
) => Duration::from_nanos(nanoseconds.saturating_sub(earlier)),
41+
) => {
42+
let duration = nanoseconds.saturating_sub(earlier);
43+
// `Duration` does not provide a nice constructor from a `u128` of nanoseconds,
44+
// so we have to implement this ourselves.
45+
// It is possible for second to overflow because u64::MAX < (u128::MAX / 1e9).
46+
// It will be saturated to u64::MAX seconds if the value after division exceeds u64::MAX.
47+
let seconds = u64::try_from(duration / 1_000_000_000).unwrap_or(u64::MAX);
48+
// It is impossible for nanosecond to overflow because u32::MAX > 1e9.
49+
let nanosecond = u32::try_from(duration.wrapping_rem(1_000_000_000)).unwrap();
50+
Duration::new(seconds, nanosecond)
51+
}
4352
_ => panic!("all `Instant` must be of the same kind"),
4453
}
4554
}
@@ -59,7 +68,7 @@ enum ClockKind {
5968
},
6069
Virtual {
6170
/// The "current virtual time".
62-
nanoseconds: Cell<u64>,
71+
nanoseconds: Cell<u128>,
6372
},
6473
}
6574

@@ -93,8 +102,11 @@ impl Clock {
93102
ClockKind::Host { .. } => std::thread::sleep(duration),
94103
ClockKind::Virtual { nanoseconds } => {
95104
// Just pretend that we have slept for some time.
96-
let nanos: u64 = duration.as_nanos().try_into().unwrap();
97-
nanoseconds.update(|x| x + nanos);
105+
let nanos: u128 = duration.as_nanos();
106+
nanoseconds.update(|x| {
107+
x.checked_add(nanos)
108+
.expect("Miri's virtual clock cannot represent an execution this long")
109+
});
98110
}
99111
}
100112
}

0 commit comments

Comments
 (0)