Skip to content

Panic (out-of-bounds slice) with malformed file in FooterDeserializer #8814

Description

@lorenzhs

What happened?

Hey guys, I've been having fun with fuzzing and my fuzzer found that FooterDeserializer::deserialize trusts the segment offset/length values read from the postscript and uses them to slice the in-memory read buffer without bounds-checking them. I suppose this should return a VortexError rather than panicking?

parse_dtype appears to slice with the untrusted offset/length verbatim:

let offset = usize::try_from(segment.offset - initial_offset)?;
let sliced_buffer =
FlatBuffer::copy_from(&initial_read[offset..offset + (segment.length as usize)]);

The "read more data" logic (lines 129-148) only guards the lower bound (read_more_offset < initial_offset), so offsets past the end of the file are never caught and fall straight into the panicking slice.

Steps to reproduce

Base64-encoded repro, because GitHub doesn't let me attach it:

VlRYRgBwYWNrAAAAAAAAtNMBAAMAAAAUAAAAAAAAAAwAFgAEAAgADAAQAAwAAAB0AAAAUAAAACwA
AAAQAAAAAAAKABgADAAIAAcACgAAAAAAAANoBAAAsNgBAAAAAAAAAAAA6v///wAAAAMgAwAAkNUB
AAAAAAAAAAoAFgAMAAgABwAKAAAAAAAAAzAAAABg1QEAAAAAAAAACgAUAAwACAAHAAoAAAAAAAAD
pAEAALzTAQAAAAAAAQCgAFZUWEY=

with that, on latest develop:

$ RUST_BACKTRACE=full ./target/release/vx browse fuzz.vortex

thread 'main' (110252) panicked at vortex-file/src/footer/deserializer.rs:234:48:
range start index 119740 out of range for slice of length 191
...
  13:     ...  - vortex_file::footer::deserializer::FooterDeserializer::deserialize
  14:     ...  - vortex_file::open::VortexOpenOptions::open::{{closure}}
  15:     ...  - vortex_file::open::VortexOpenOptions::open_path::{{closure}}
  16:     ...  - vortex_tui::native_cli::launch_from::{{closure}}
  17:     ...  - vx::main::{{closure}}

Environment

Latest develop branch / verified on 3975895

Additional context

Claude says that all of these slice initial_read with untrusted postscript offsets/lengths:

  • parse_dtype — deserializer.rs:234 (this one)
  • parse_file_statistics — deserializer.rs:249
  • parse_footer — deserializer.rs:267 and :272

Additionally on the same lines:

  • segment.offset - initial_offset can underflow (segment.offset < initial_offset)
  • offset + (segment.length as usize) can overflow

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugA bug issue

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions