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.
This commit is contained in:
Andrej Kolčin 2025-02-06 23:32:42 +03:00 committed by GitHub
parent 2f18b9c856
commit 2ce5de58e6
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

View File

@ -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<Item = (&str, Span)> { fn split_whitespace_indices(s: &str, span: Span) -> impl Iterator<Item = (&str, Span)> {
s.split_whitespace().map(move |sub| { 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())) (sub, Span::new(start_offset, start_offset + sub.len()))
}) })
} }