Summary
SliceRingBuffer::reserve_capacity() (src/lib.rs:579) computes the mirrored-buffer length as 2 * new_capacity without a checked multiplication. When new_capacity ≥ 2^63, this wraps to zero, causing Buffer::uninitialized(0) to return a dangling empty buffer (ptr = NonNull::dangling()). If the deque already holds elements, the immediately following copy_nonoverlapping writes to the dangling pointer (SEGV). If the deque is empty, the copy is a no-op but subsequent extend_with / push_back writes to the zero-capacity buffer (heap corruption).
Confirmed on 0.3.4.
Proof of Concept
use slice_ring_buffer::SliceRingBuffer;
fn main() {
let mut deq: SliceRingBuffer<i32> = SliceRingBuffer::with_capacity(0);
let mut other: SliceRingBuffer<i32> = SliceRingBuffer::with_capacity(4);
other.push_back(1);
other.push_back(2);
other.push_back(3);
deq.append(&mut other);
deq.resize(9223372036854775808, 0i32); // 2^63
}
==1349962==ERROR: AddressSanitizer: SEGV on unknown address 0x000000000004
#0 memmove-vec-unaligned-erms.S:418
#1 __asan_memcpy
Summary
SliceRingBuffer::reserve_capacity()(src/lib.rs:579) computes the mirrored-buffer length as2 * new_capacitywithout a checked multiplication. Whennew_capacity ≥ 2^63, this wraps to zero, causingBuffer::uninitialized(0)to return a dangling empty buffer (ptr = NonNull::dangling()). If the deque already holds elements, the immediately followingcopy_nonoverlappingwrites to the dangling pointer (SEGV). If the deque is empty, the copy is a no-op but subsequentextend_with/push_backwrites to the zero-capacity buffer (heap corruption).Confirmed on 0.3.4.
Proof of Concept