-
Notifications
You must be signed in to change notification settings - Fork 3.5k
Description
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)