Skip to content

Undefined Behavior in Vec::insert with out-of-bounds index #47

@shinmao

Description

@shinmao

The Vec::insert method can trigger undefined behavior when called with an out-of-bounds index that is significantly larger than the vector's length. The method performs pointer arithmetic with the unchecked index before validating that index <= len, leading to an out-of-bounds pointer offset.

Vulnerability Details

Location: src/vec/mod.rs lines 1447-1469
Affected Code:

allocator-api2/src/vec/mod.rs

Lines 1447 to 1469 in 1644e70

pub fn insert(&mut self, index: usize, element: T) {
#[cold]
#[inline(never)]
fn assert_failed(index: usize, len: usize) -> ! {
panic!(
"insertion index (is {}) should be <= len (is {})",
index, len
);
}
let len = self.len();
// space for the new element
if len == self.buf.capacity() {
self.reserve(1);
}
unsafe {
// infallible
// The spot to put the new value
{
let p = self.as_mut_ptr().add(index);
match cmp::Ord::cmp(&index, &len) {

Root Cause

The bounds check (index <= len) is performed after the unsafe pointer arithmetic operation self.as_mut_ptr().add(index). When index is larger than the allocation size, this causes undefined behavior before the validation can panic.

Proof of Concept

fn main() {
    let mut v: Vec<u8> = Vec::new();
    v.push(1);

    let idx = v.capacity().saturating_mul(4).saturating_add(1);
    v.insert(idx, 2);
}

Miri Output

error: Undefined Behavior: in-bounds pointer arithmetic failed: attempting to offset pointer by 33 bytes, but got alloc230 which is only 8 bytes from the end of the allocation
    --> /home/usr/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/allocator-api2-0.4.0/src/vec/mod.rs:1468:25
     |
1468 |                 let p = self.as_mut_ptr().add(index);
     |                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Undefined Behavior occurred here

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions