google / google/flatbuffers

Rust: Verifier::reset() does not reset apparent_size (duplicated num_tables assignment)

Open Beginner friendly
#9,189 0 comments 0 reactions 0 assignees View on GitHub
Dominant language
C++
Stars
26.5k
Forks
3.7k
PR merge metrics
No merged PRs in 30d

Description

### Summary

`Verifier::reset()` assigns `self.num_tables = 0` twice and never resets `self.apparent_size`. A `Verifier` reused via `reset()` therefore keeps accumulating `apparent_size` across uses, and once the running total exceeds `max_apparent_size` it rejects **every** subsequent buffer with `ApparentSizeTooLarge`, regardless of whether that buffer is valid.

https://github.com/google/flatbuffers/blob/81edeb17d9118143f2c81caf27edfb0df401279e/rust/flatbuffers/src/verifier.rs#L276-L282

```rust
/// Resets verifier internal state.
#[inline]
pub fn reset(&mut self) {
self.depth = 0;
self.num_tables = 0;
self.num_tables = 0; // <-- duplicated; `self.apparent_size = 0;` appears to be intended
}
```

`apparent_size` is initialized in `new()` and incremented in `range_in_buffer()`, but is never cleared anywhere:

```
274: Self { opts, buffer, depth: 0, num_tables: 0, apparent_size: 0 }
311: self.apparent_size += size;
312: if self.apparent_size > self.opts.max_apparent_size {
```

### Reproduction

Executed against the crate at `master` (`81edeb17`), version 25.12.19:

```rust
// rust/flatbuffers/tests/reset_apparent_size.rs
use flatbuffers::{InvalidFlatbuffer, Verifier, VerifierOptions};

#[test]
fn reset_should_clear_apparent_size() {
let opts = VerifierOptions { max_apparent_size: 100, ..Default::default() };
let buf = [0u8; 64];
let mut v = Verifier::new(&opts, &buf);

v.range_in_buffer(0, 60).expect("first range must fit");
v.reset();

match v.range_in_buffer(0, 60) {
Ok(()) => println!("reset() cleared apparent_size"),
Err(InvalidFlatbuffer::ApparentSizeTooLarge) => {
panic!("after reset(), apparent_size still held 60")
}
Err(e) => panic!("unexpected error: {e:?}"),
}
}
```

```
$ cargo test --test reset_apparent_size
thread 'reset_should_clear_apparent_size' panicked at:
after reset(), apparent_size still held 60
test result: FAILED. 0 passed; 1 failed
```

The second call is identical to the first and should succeed after a documented state reset; instead the running total reaches 120 against the 100-byte limit and is rejected.

### Impact

Correctness / availability, not a verification bypass — the effect is over-rejection of valid buffers, so it cannot cause malicious buffers to be accepted. Applications that reuse one `Verifier` across messages (which is what `reset()` exists for) will begin failing all verification once cumulative size passes `max_apparent_size` (default `1 << 31`).

### Suggested fix

```rust
pub fn reset(&mut self) {
self.depth = 0;
self.num_tables = 0;
self.apparent_size = 0;
}
```

Happy to send a PR if useful.

Contributor guide

Open the contributing guide

Research direction

Start in rust/flatbuffers/src/verifier.rs at Verifier::reset() and the apparent_size accounting in range_in_buffer(). Run the reproduction in rust/flatbuffers/tests/reset_apparent_size.rs; done means reset allows the identical range to pass again without triggering ApparentSizeTooLarge.

Written by the indexing model from the issue text.

Assessment

Tech stack
rust
Domain
backend
Issue type
Bug
Difficulty
1/5
Estimated time
Under an hour
Activity status
Quiet
Clarity
Clearly specified
Newbie friendliness
90/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.