From 7f21a648c72c93b1db91f457964f9eb950b3a416 Mon Sep 17 00:00:00 2001 From: Hussenet Thomas <113238884+LeJamon@users.noreply.github.com> Date: Sat, 30 May 2026 15:38:25 +0200 Subject: [PATCH] fix(#172): reject 2^32 as out-of-range XRPL time XRPL time is an unsigned 32-bit seconds-since-Ripple-epoch value, so the maximum representable instant is 2^32 - 1. MAX_XRPL_TIME was 2^32 and the inclusive bound allowed exactly 2^32. Set MAX_XRPL_TIME to 2^32 - 1. --- src/utils/time_conversion.rs | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/src/utils/time_conversion.rs b/src/utils/time_conversion.rs index 6cf8d63d..30eabbac 100644 --- a/src/utils/time_conversion.rs +++ b/src/utils/time_conversion.rs @@ -10,8 +10,11 @@ use super::exceptions::XRPLUtilsResult; /// The "Ripple Epoch" of 2000-01-01T00:00:00 UTC pub const RIPPLE_EPOCH: i64 = 946684800; -/// The maximum time that can be expressed on the XRPL -pub const MAX_XRPL_TIME: i64 = i64::pow(2, 32); +/// The maximum time that can be expressed on the XRPL. +/// +/// XRPL time is an unsigned 32-bit seconds-since-Ripple-epoch value, so the +/// largest representable instant is `2^32 - 1`. +pub const MAX_XRPL_TIME: i64 = i64::pow(2, 32) - 1; /// Ensures time does not exceed max representable on XRPL. fn _ripple_check_max(time: i64, ok: T) -> XRPLUtilsResult { @@ -136,6 +139,15 @@ mod test { assert_eq!(posix_to_ripple_time(RIPPLE_EPOCH), Ok(0_i64)); } + /// XRPL time is an unsigned 32-bit value, so `2^32` is out of range while + /// `2^32 - 1` is the largest representable Ripple time. + #[test] + fn bug_5_24_max_xrpl_time_off_by_one() { + let out_of_range: i64 = 1i64 << 32; + assert!(ripple_time_to_posix(out_of_range).is_err()); + assert!(ripple_time_to_posix(out_of_range - 1).is_ok()); + } + #[test] fn accept_posix_round_trip() { let current_time: i64 = Utc::now().timestamp();