Skip to content

Integer Underflow Vulnerability in load_prefix and save_prefix #3

@lewismosciski

Description

@lewismosciski

Hi there!

While developing a static analyzer for Rust, we discovered another soundness issue in runes::utils related to integer underflow. We noticed issue #2 addresses padding bytes, and we'd like to report a different vulnerability.

Issue

The load_prefix and save_prefix functions perform unchecked subtraction that underflows when ignored >= size_of::<T>():

pub fn load_prefix<T>(obj: &mut T, ignored: usize, reader: &mut dyn Read) -> bool {
    let len = size_of::<T>() - ignored; 
    match reader.read(unsafe {
        from_raw_parts_mut(transmute::<*mut T, *mut u8>(obj as *mut T), len)
    }) {
        // ...
    }
}

When ignored >= size_of::<T>(), the subtraction underflows to a massive value (e.g., usize::MAX - 3), causing from_raw_parts_mut to create an out-of-bounds slice.

Minimal Reproduction

use runes::utils::{load_prefix, Read};

struct TestReader {
    data: Vec<u8>,
    pos: usize,
}

impl Read for TestReader {
    fn read(&mut self, buf: &mut [u8]) -> Option<usize> {
        let remaining = self.data.len() - self.pos;
        let to_read = buf.len().min(remaining);
        buf[..to_read].copy_from_slice(&self.data[self.pos..self.pos + to_read]);
        self.pos += to_read;
        Some(to_read)
    }
}

fn main() {
    #[repr(C)]
    struct Small { value: u32 }  // 4 bytes
    
    let mut obj = Small { value: 0 };
    let mut reader = TestReader { data: vec![0xff; 1000], pos: 0 };
    
    // ignored=8, size=4 => len underflows to usize::MAX-3
    load_prefix(&mut obj, 8, &mut reader);
}

Miri output:

error: Undefined Behavior: invalid metadata in wide pointer: slice is bigger than largest supported object
  --> /home/ccuu/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/runes-0.2.5/src/utils.rs:72:9
   |
72 |         from_raw_parts_mut(transmute::<*mut T, *mut u8>(obj as *mut T), len)
   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Undefined Behavior occurred here
   |
   = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
   = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
}

We appreciate your work on this crate! We'd be happy to submit a PR that addresses both this issue and #2 (padding bytes) if that would be helpful.

Best regards

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