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

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions