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
Open
fix(flexbuffers): prevent Reader panics from crafted input (get_bool, get_key_len, read_usize)#8980canuk40 wants to merge 1 commit intogoogle:masterfrom
canuk40 wants to merge 1 commit intogoogle:masterfrom
Conversation
|
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. |
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>
74c1a9a to
f6dce03
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
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.rsuse 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()).get_bool()line 326self.buffer[self.address..self.address + self.width.n_bytes()]— panics whenaddress + n_bytes > buffer.len()get_key_len()line 335self.buffer[self.address..]— panics whenself.address > buffer.len()read_usize()line 604, 607&buffer[address..]andcursor[0]— panics whenaddress >= buffer.len()Reproduction
Root Cause
get_bool(),get_key_len(), andread_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 usedcursor[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 returnsErr(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 returnsErr(FlexbufferOutOfBounds)on invalid input instead of panicking.get_key_len()— now returnsErr(FlexbufferOutOfBounds)on invalid input instead of panicking.read_usize()— now returns0(the same as the existingunwrap_or_default()behavior in the W16/W32/W64 arms) instead of panicking.Tests
Four regression tests added to
reader::testsinmod.rs:read_usize_w8_address_at_end_does_not_panic— PoC payload from FlexBuffers Rust: panic from untrusted input in Reader::get_bool() #8923read_usize_address_past_end_does_not_panic— address > buffer.len()read_usize_w8_returns_zero_on_oob— unit test for W8 safe defaultread_usize_past_end_returns_zero— unit test for OOB address safe defaultCargo-Fuzz Harness
Added
rust/flexbuffers/fuzz/with two targets:fuzz_reader— exercises every public Reader accessor on arbitrary inputfuzz_roundtrip— ensures parseable inputs never trigger panicsRun with:
Relation to #8924
PR #8924 fixes the overflow arithmetic in
map.rsandvector.rsindex calculations and partially fixesmod.rs. This PR:get_bool()andget_key_len()(same as fix(flexbuffers): harden Rust Reader against panics from untrusted input #8924)read_usize()(not addressed in fix(flexbuffers): harden Rust Reader against panics from untrusted input #8924)Happy to coordinate with #8924 if the maintainers prefer to consolidate.