From 2ce5de58e69c0721a69b3186d63548a6348be8bd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrej=20Kol=C4=8Din?= Date: Thu, 6 Feb 2025 23:32:42 +0300 Subject: [PATCH] Fix an integer overflow bug in `into duration` (#15031) Fixes #15028 # Description The current implementation of `into duration` uses bare pointer arithmetic instead of wrapping one. This works fine on 64-bit platforms, since the pointers don't take up all of the 64 bits, but fails on 32 bit ones. # Tests + Formatting All of the affected tests pass on my end, but it's `x86_84`, so they were also passing before that. --- .../src/conversions/into/duration.rs | 20 +++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/crates/nu-command/src/conversions/into/duration.rs b/crates/nu-command/src/conversions/into/duration.rs index d11cfeffc2..3d11b83afb 100644 --- a/crates/nu-command/src/conversions/into/duration.rs +++ b/crates/nu-command/src/conversions/into/duration.rs @@ -170,16 +170,20 @@ fn into_duration( ) } -// convert string list of duration values to duration NS. -// technique for getting substrings and span based on: https://stackoverflow.com/a/67098851/2036651 -#[inline] -fn addr_of(s: &str) -> usize { - s.as_ptr() as usize -} - fn split_whitespace_indices(s: &str, span: Span) -> impl Iterator { s.split_whitespace().map(move |sub| { - let start_offset = span.start + addr_of(sub) - addr_of(s); + // Gets the offset of the `sub` substring inside the string `s`. + // `wrapping_` operations are necessary because the pointers can + // overflow on 32-bit platforms. The result will not overflow, because + // `sub` is within `s`, and the end of `s` has to be a valid memory + // address. + // + // XXX: this should be replaced with `str::substr_range` from the + // standard library when it's stabilized. + let start_offset = span + .start + .wrapping_add(sub.as_ptr() as usize) + .wrapping_sub(s.as_ptr() as usize); (sub, Span::new(start_offset, start_offset + sub.len())) }) }