runes icon indicating copy to clipboard operation
runes copied to clipboard

Integer Underflow Vulnerability in load_prefix and save_prefix

Open lewismosciski opened this issue 2 months ago • 0 comments

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

lewismosciski avatar Oct 23 '25 14:10 lewismosciski