Skip to content

Commit 9b98030

Browse files
andreeafloresculauralt
authored andcommitted
[rtc] fix potential overflow caused by offset
Since now the offset & LR can be set from outside of the Rtc implementation, we need to add a checked add when computing the value of the RTC. Added a test & fix for the overflow. Signed-off-by: Andreea Florescu <[email protected]>
1 parent 80921fb commit 9b98030

File tree

2 files changed

+25
-6
lines changed

2 files changed

+25
-6
lines changed

coverage_config_x86_64.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
{
2-
"coverage_score": 96.6,
2+
"coverage_score": 96.7,
33
"exclude_path": "",
44
"crate_features": ""
55
}

crates/vm-superio/src/rtc_pl031.rs

Lines changed: 24 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -247,11 +247,15 @@ impl<EV: RtcEvents> Rtc<EV> {
247247
// The RTC value is the time + offset as per:
248248
// https://developer.arm.com/documentation/ddi0224/c/Functional-overview/RTC-functional-description/Update-block
249249
//
250-
// The addition cannot fail because the current time can be maximum u32,
251-
// and the offset is always < u32::MAX. The addition is thus < u32::MAX * 2,
252-
// which fits in an i64.
253-
// In the unlikely case of the value not fitting in an u32, we just reset the time to 0.
254-
u32::try_from((get_current_time() as i64) + self.offset).unwrap_or(0)
250+
// In the unlikely case of the value not fitting in an u32, we just set the time to
251+
// the current time on the host.
252+
let current_host_time = get_current_time();
253+
u32::try_from(
254+
(current_host_time as i64)
255+
.checked_add(self.offset)
256+
.unwrap_or(current_host_time as i64),
257+
)
258+
.unwrap_or(current_host_time)
255259
}
256260

257261
/// Handles a write request from the driver at `offset` offset from the
@@ -956,4 +960,19 @@ mod tests {
956960
// Check that the restored `Rtc` keeps the state of the old `metrics` object.
957961
assert_eq!(rtc.events.invalid_write_count.count(), 1);
958962
}
963+
964+
#[test]
965+
fn test_overflow_offset() {
966+
// Test that an invalid offset (too big) does not cause an overflow.
967+
let rtc_state = RtcState {
968+
lr: 65535,
969+
offset: 9223372036854710636,
970+
mr: 0,
971+
imsc: 0,
972+
ris: 0,
973+
};
974+
let mut rtc = Rtc::from_state(&rtc_state, NoEvents);
975+
let mut data = [0u8; 4];
976+
rtc.read(RTCDR, &mut data);
977+
}
959978
}

0 commit comments

Comments
 (0)