This is an automated email from the ASF dual-hosted git repository.
alamb pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/arrow-rs.git
The following commit(s) were added to refs/heads/main by this push:
new a8e826124b Prevent repeat slice length overflow (#9819)
a8e826124b is described below
commit a8e826124be6bcd842167292fcb3a68f1e43bba4
Author: Andrew Lamb <[email protected]>
AuthorDate: Sat Apr 25 11:19:49 2026 -0400
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 07ef965cb0..f4e532029b 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;
@@ -1474,6 +1480,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::<u64>() + 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