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
What happened?
Hey guys, I've been having fun with fuzzing and my fuzzer found that
FooterDeserializer::deserializetrusts 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_dtypeappears to slice with the untrusted offset/length verbatim:vortex/vortex-file/src/footer/deserializer.rs
Lines 232 to 234 in 3975895
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:
with that, on latest
develop:Environment
Latest
developbranch / verified on 3975895Additional context
Claude says that all of these slice
initial_readwith untrusted postscript offsets/lengths:parse_dtype— deserializer.rs:234 (this one)parse_file_statistics— deserializer.rs:249parse_footer— deserializer.rs:267 and :272Additionally on the same lines:
segment.offset - initial_offsetcan underflow (segment.offset < initial_offset)offset + (segment.length as usize)can overflow