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

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions