From bb7decdec017bd4491a0672c1f1ac9b38185c2b2 Mon Sep 17 00:00:00 2001 From: Andrew Lamb Date: Sat, 25 Apr 2026 11:19:49 -0400 Subject: [PATCH] Prevent repeat slice length overflow (#9819) # Which issue does this PR close? - None. # Rationale for this change MutableBuffer repeated slices used unchecked usize arithmetic when calculating the number of bytes to reserve. In optimized builds, very large repeat counts could wrap the capacity calculation before copying repeated bytes. # What changes are included in this PR? This adds checked arithmetic for repeated slice byte length validation before reserving capacity and copying repeated data. # Are these changes tested? Yes. This adds regression coverage for overflowing repeated slice length calculations. # Are there any user-facing changes? Invalid repeat counts whose requested byte length cannot be represented without overflow now panic consistently. There are no API changes. --- arrow-buffer/src/buffer/mutable.rs | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/arrow-buffer/src/buffer/mutable.rs b/arrow-buffer/src/buffer/mutable.rs index 75f77242b9e1..4c22c00409cc 100644 --- a/arrow-buffer/src/buffer/mutable.rs +++ b/arrow-buffer/src/buffer/mutable.rs @@ -284,9 +284,15 @@ impl MutableBuffer { } let bytes_to_repeat = size_of_val(slice_to_repeat); + let repeated_bytes = repeat_count + .checked_mul(bytes_to_repeat) + .expect("repeated slice byte length overflow"); + self.len + .checked_add(repeated_bytes) + .expect("mutable buffer length overflow"); // Ensure capacity - self.reserve(repeat_count * bytes_to_repeat); + self.reserve(repeated_bytes); // Save the length before we do all the copies to know where to start from let length_before = self.len; @@ -1340,6 +1346,21 @@ mod tests { test_repeat_count(0, &[1i32, 2, 3]); } + #[test] + #[should_panic(expected = "repeated slice byte length overflow")] + fn test_repeat_slice_count_multiply_overflow() { + let mut buffer = MutableBuffer::new(0); + buffer.repeat_slice_n_times(&[0_u64], usize::MAX / mem::size_of::() + 1); + } + + #[test] + #[should_panic(expected = "mutable buffer length overflow")] + fn test_repeat_slice_count_len_overflow() { + let mut buffer = MutableBuffer::new(0); + buffer.push(0_u8); + buffer.repeat_slice_n_times(&[0_u8], usize::MAX); + } + #[test] fn test_small_repeats_counts() { // test any special implementation for small repeat counts