Skip to content

fix(flexbuffers): prevent Reader panics from crafted input (get_bool, get_key_len, read_usize)#8980

Open
canuk40 wants to merge 1 commit intogoogle:masterfrom
canuk40:fix/flexbuffers-reader-oob-panics
Open

fix(flexbuffers): prevent Reader panics from crafted input (get_bool, get_key_len, read_usize)#8980
canuk40 wants to merge 1 commit intogoogle:masterfrom
canuk40:fix/flexbuffers-reader-oob-panics

Conversation

@canuk40
Copy link

@canuk40 canuk40 commented Mar 15, 2026

fix(flexbuffers): prevent panics in Reader from crafted input (3 locations)

Closes #8923. Extends the approach in #8924 to cover additional panic vectors.

Summary

Three sites in rust/flexbuffers/src/reader/mod.rs use direct slice indexing that panics when processing crafted FlexBuffer input. Any Rust application deserializing FlexBuffers from untrusted sources is affected — including via the serde API (flexbuffers::from_slice()).

Location Panic trigger
get_bool() line 326 self.buffer[self.address..self.address + self.width.n_bytes()] — panics when address + n_bytes > buffer.len()
get_key_len() line 335 self.buffer[self.address..] — panics when self.address > buffer.len()
read_usize() line 604, 607 &buffer[address..] and cursor[0] — panics when address >= buffer.len()

Reproduction

use flexbuffers::Reader;

// Panics before this fix — 4-byte crafted payload
let data: &[u8] = &[0x5d, 0x79, 0x6b, 0x02];
let reader = Reader::get_root(data).unwrap();
let _ = reader.as_bool(); // thread panicked: range end index 8 out of range for slice of length 4

Root Cause

get_bool(), get_key_len(), and read_usize() used Rust's panicking index operator ([]) instead of the .get() method used by the rest of the Reader.

Notably, read_usize() was inconsistent within itself — the W16/W32/W64 arms already used .get() safely, but the W8 arm used cursor[0], and the &buffer[address..] slicing at the top of the function was unguarded for all widths.

Fix

Replace all three sites with .get()-based indexing that returns Err(Error::FlexbufferOutOfBounds) or a safe default (0) instead of panicking. The fix follows the pattern already used throughout the rest of the codebase.

get_bool() — now returns Err(FlexbufferOutOfBounds) on invalid input instead of panicking.

get_key_len() — now returns Err(FlexbufferOutOfBounds) on invalid input instead of panicking.

read_usize() — now returns 0 (the same as the existing unwrap_or_default() behavior in the W16/W32/W64 arms) instead of panicking.

Tests

Four regression tests added to reader::tests in mod.rs:

Cargo-Fuzz Harness

Added rust/flexbuffers/fuzz/ with two targets:

  • fuzz_reader — exercises every public Reader accessor on arbitrary input
  • fuzz_roundtrip — ensures parseable inputs never trigger panics

Run with:

cargo +nightly fuzz run fuzz_reader -- -max_len=256

Relation to #8924

PR #8924 fixes the overflow arithmetic in map.rs and vector.rs index calculations and partially fixes mod.rs. This PR:

Happy to coordinate with #8924 if the maintainers prefer to consolidate.

@canuk40 canuk40 requested a review from dbaileychess as a code owner March 15, 2026 15:19
@google-cla
Copy link

google-cla bot commented Mar 15, 2026

Thanks for your pull request! It looks like this may be your first contribution to a Google open source project. Before we can look at your pull request, you'll need to sign a Contributor License Agreement (CLA).

View this failed invocation of the CLA check for more information.

For the most up to date status, view the checks section at the bottom of the pull request.

@github-actions github-actions bot added the rust label Mar 15, 2026
Three direct-index slice panics in rust/flexbuffers/src/reader/mod.rs
are reachable from untrusted FlexBuffer input:

1. get_bool(): buffer[address..address+n_bytes] panics when OOB
2. get_key_len(): buffer[address..] panics when address > len
3. read_usize(): &buffer[address..] and cursor[0] panic when OOB
   (W16/W32/W64 arms already used .get() safely; W8 did not)

Fix: replace all three with .get()-based indexing that returns
Err(FlexbufferOutOfBounds) or 0 instead of panicking.

Repro (from issue google#8923):
  let data = &[0x5d, 0x79, 0x6b, 0x02];
  let r = flexbuffers::Reader::get_root(data).unwrap();
  let _ = r.as_bool(); // panicked before this fix

Also adds:
- 4 regression tests in reader::tests
- cargo-fuzz harness with fuzz_reader and fuzz_roundtrip targets

Closes google#8923. Extends google#8924 to cover read_usize() and adds fuzzing.

Signed-off-by: canuk40 <258483010+canuk40@users.noreply.github.com>
@canuk40 canuk40 force-pushed the fix/flexbuffers-reader-oob-panics branch from 74c1a9a to f6dce03 Compare March 15, 2026 15:38
Copy link
Author

@canuk40 canuk40 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

looks good

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

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

1 participant