From 2e4ba41ce971976d5c7f9ba3d98665144f5e278c Mon Sep 17 00:00:00 2001 From: Julian Ganz Date: Tue, 12 Dec 2023 14:18:44 +0100 Subject: [PATCH] impl: make Arbitrary::arbitrary for SystemTime not panic Arbitrary `SystemTime`s are generated based on arbitrary `Duration`s by adding or subtracting from `UNIX_EPOCH`. If we happen to generate big `Duration`s, this could cause an overflow. This change avoids this problem by resorting to ever smaller durations in case of an overflow. --- src/arbitrary.rs | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/src/arbitrary.rs b/src/arbitrary.rs index 897641a..d47ab78 100644 --- a/src/arbitrary.rs +++ b/src/arbitrary.rs @@ -5,7 +5,7 @@ use std::collections::{ use std::env; use std::ffi::{CString, OsString}; use std::hash::{BuildHasher, Hash}; -use std::iter::{empty, once}; +use std::iter::{empty, once, successors}; use std::net::{ IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr, SocketAddrV4, SocketAddrV6, }; @@ -1186,11 +1186,16 @@ impl Arbitrary for SystemTime { fn arbitrary(rng: &mut Gen) -> Self { let after_epoch = bool::arbitrary(rng); let duration = Duration::arbitrary(rng); - if after_epoch { - UNIX_EPOCH + duration - } else { - UNIX_EPOCH - duration - } + successors(Some(duration), |d| Some(*d / 2)) + .take_while(|d| !d.is_zero()) + .find_map(|d| { + if after_epoch { + UNIX_EPOCH.checked_add(d) + } else { + UNIX_EPOCH.checked_sub(d) + } + }) + .unwrap_or(UNIX_EPOCH) } fn shrink(&self) -> Box> {