From a580c0b437b8b7118ca1c67c81f7d895acd321a9 Mon Sep 17 00:00:00 2001 From: DualFroz Date: Sat, 10 Oct 2026 12:30:25 +0200 Subject: [PATCH] fmt: fix buffer sizes when printing durations The ISO 8601 buffer for durations was sized for `SignedDuration::MIN`, but the longest output is a negative duration with 16 digits of hours and two digit minutes and seconds, e.g., `-PT2562047788015214H59M59.999999999S`, which is 36 bytes. Similarly, the friendly format buffer for `std::time::Duration` didn't account for the `+` prefix written by `Direction::ForceSign`. Fixes #654 --- CHANGELOG.md | 10 ++++++++++ crates/jiff/src/fmt/friendly/printer.rs | 11 +++++++++-- crates/jiff/src/fmt/temporal/printer.rs | 21 ++++++++++++++++++--- 3 files changed, 37 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 14dc7fe..98ab476 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,15 @@ # CHANGELOG +0.2.39 (TBD) +============ +TODO + +Bug fixes: + +* [#654](https://github.com/BurntSushi/jiff/issues/654): +Fixes a panic when printing some very large durations. + + 0.2.38 (2026-10-06) =================== This release updates Jiff's bundled copy of the [IANA Time Zone Database] diff --git a/crates/jiff/src/fmt/friendly/printer.rs b/crates/jiff/src/fmt/friendly/printer.rs index c34d8f4..aa74a6d 100644 --- a/crates/jiff/src/fmt/friendly/printer.rs +++ b/crates/jiff/src/fmt/friendly/printer.rs @@ -50,8 +50,9 @@ const MAX_SIGNED_DURATION_LEN: usize = 194; /// /// Note that this is shorter than `MAX_SIGNED_DURATION` because one cannot /// get a negative formatted duration from a `std::time::Duration`. So there's -/// no way to get an ` ago` suffix (or a `-` prefix). -const MAX_UNSIGNED_DURATION_LEN: usize = 190; +/// no way to get an ` ago` suffix (or a `-` prefix). It can still get a `+` +/// prefix with `Direction::ForceSign` though, which is counted here. +const MAX_UNSIGNED_DURATION_LEN: usize = 191; /// Configuration for [`SpanPrinter::designator`]. /// @@ -4169,5 +4170,11 @@ mod tests { p.unsigned_duration_to_string(&udur), @"00005124095576030430 hours, 00000000000000000059 minutes, 00000000000000000059 seconds, 00000000000000000999 milliseconds, 00000000000000000999 microseconds, 00000000000000000999 nanoseconds", ); + + let p = p.direction(Direction::ForceSign); + insta::assert_snapshot!( + p.unsigned_duration_to_string(&udur), + @"+00005124095576030430 hours, 00000000000000000059 minutes, 00000000000000000059 seconds, 00000000000000000999 milliseconds, 00000000000000000999 microseconds, 00000000000000000999 nanoseconds", + ); } } diff --git a/crates/jiff/src/fmt/temporal/printer.rs b/crates/jiff/src/fmt/temporal/printer.rs index cf728ac..abe63b2 100644 --- a/crates/jiff/src/fmt/temporal/printer.rs +++ b/crates/jiff/src/fmt/temporal/printer.rs @@ -134,9 +134,11 @@ const MAX_SPAN_LEN: usize = 78; /// Defines the maximum possible length (in bytes) of a duration printed in the /// Temporal ISO 8601 format. /// -/// This applies to both signed and unsigned durations. Unsigned durations have -/// one more digit, but signed durations can have a negative sign. -const MAX_DURATION_LEN: usize = 35; +/// This applies to both signed and unsigned durations. The longest one isn't +/// at either extreme. It's a negative duration with 16 digits of hours and +/// two digit minutes and seconds, e.g., +/// `-PT2562047788015214H59M59.999999999S`. +const MAX_DURATION_LEN: usize = 36; #[derive(Clone, Debug)] pub(super) struct DateTimePrinter { @@ -1897,6 +1899,15 @@ mod tests { p(i64::MAX, 999_999_999), @"PT2562047788015215H30M7.999999999S", ); + + insta::assert_snapshot!( + p(-(2_562_047_788_015_214 * 3_600 + 3_599), -999_999_999), + @"-PT2562047788015214H59M59.999999999S", + ); + insta::assert_snapshot!( + p(2_562_047_788_015_214 * 3_600 + 3_599, 999_999_999), + @"PT2562047788015214H59M59.999999999S", + ); } #[cfg(not(miri))] @@ -1929,5 +1940,9 @@ mod tests { p(u64::MAX, 999_999_999), @"PT5124095576030431H15.999999999S", ); + insta::assert_snapshot!( + p(5_124_095_576_030_430 * 3_600 + 3_599, 999_999_999), + @"PT5124095576030430H59M59.999999999S", + ); } }