Skip to content

FlexBuffers Rust: panic from untrusted input in Reader::get_bool() #8923

@jrey8343

Description

@jrey8343

Summary

The FlexBuffers Rust crate panics when processing crafted input via the Reader API. The get_bool() function performs an unchecked buffer slice that causes a panic when the declared data width exceeds the actual buffer size.

Affected version: flexbuffers 25.12.19 (latest on crates.io)
File: rust/flexbuffers/src/reader/mod.rs:326

Reproduction

use flexbuffers::Reader;

fn main() {
    let data: &[u8] = &[0x5d, 0x79, 0x6b, 0x02];
    let reader = Reader::get_root(data).unwrap(); // succeeds
    let _ = reader.as_bool(); // panics
}

Panic output:

thread 'main' panicked at rust/flexbuffers/src/reader/mod.rs:326:23:
range end index 8 out of range for slice of length 4

Root Cause

get_bool() uses direct indexing instead of .get():

// Line 326 — panics on out-of-bounds
Ok(self.buffer[self.address..self.address + self.width.n_bytes()].iter().any(|&b| b != 0))

Compare with get_u64() (line 405) which correctly handles this:

let cursor = self.buffer.get(self.address..self.address + self.width.n_bytes());
// ... returns Err(Error::FlexbufferOutOfBounds)

The same unchecked indexing pattern exists in read_usize() (line 604, 606).

Impact

Any Rust application deserializing FlexBuffers from untrusted input crashes on this 4-byte payload. This is reachable through the serde API (flexbuffers::from_slice()).

Suggested Fix

Use .get() in get_bool(), matching the existing pattern:

pub fn get_bool(&self) -> Result<bool, Error> {
    self.expect_type(FlexBufferType::Bool)?;
    Ok(self.buffer
        .get(self.address..self.address + self.width.n_bytes())
        .ok_or(Error::FlexbufferOutOfBounds)?
        .iter()
        .any(|&b| b != 0))
}

And in read_usize():

fn read_usize(buffer: &[u8], address: usize, width: BitWidth) -> usize {
    let cursor = buffer.get(address..).unwrap_or_default();
    match width {
        BitWidth::W8 => cursor.first().copied().unwrap_or_default() as usize,
        // W16/W32/W64 already use .get()
    }
}

Found by fuzzing with cargo-fuzz.

Reporter: Jared Reyes (jaredreyespt@gmail.com)

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions