From 21be72b8d536c48ad7fb4cff56c4977ac61bdad6 Mon Sep 17 00:00:00 2001 From: Robert Kruszewski Date: Fri, 17 Jul 2026 17:01:46 +0100 Subject: [PATCH] Validate segment offsets when populating initial segments Signed-off-by: Robert Kruszewski --- vortex-file/src/open.rs | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/vortex-file/src/open.rs b/vortex-file/src/open.rs index 1bd42c7be41..fafeea6ea74 100644 --- a/vortex-file/src/open.rs +++ b/vortex-file/src/open.rs @@ -13,6 +13,7 @@ use vortex_buffer::ByteBuffer; use vortex_error::VortexError; use vortex_error::VortexExpect; use vortex_error::VortexResult; +use vortex_error::vortex_err; use vortex_io::VortexReadAt; use vortex_io::session::RuntimeSessionExt; use vortex_layout::segments::InstrumentedSegmentCache; @@ -326,7 +327,7 @@ impl VortexOpenOptions { // If the initial read happened to cover any segments, then we can populate the // segment cache let initial_offset = file_size - (deserializer.buffer().len() as u64); - self.populate_initial_segments(initial_offset, deserializer.buffer(), &footer); + self.populate_initial_segments(initial_offset, deserializer.buffer(), &footer)?; Ok(footer) } @@ -337,7 +338,7 @@ impl VortexOpenOptions { initial_offset: u64, initial_read: &ByteBuffer, footer: &Footer, - ) { + ) -> VortexResult<()> { let first_idx = footer .segment_map() .partition_point(|segment| segment.offset < initial_offset); @@ -349,12 +350,19 @@ impl VortexOpenOptions { let segment_id = SegmentId::from(u32::try_from(idx).vortex_expect("Invalid segment ID")); let offset = - usize::try_from(segment.offset - initial_offset).vortex_expect("Invalid offset"); - let buffer = initial_read - .slice(offset..offset + (segment.length as usize)) - .aligned(segment.alignment); + usize::try_from(segment.offset.checked_sub(initial_offset).ok_or_else(|| { + vortex_err!( + "Segment offset {} is smaller than file read offset {initial_offset}", + segment.offset + ) + })?)?; + let buffer = offset + .checked_add(segment.length as usize) + .map(|end| initial_read.slice(offset..end).aligned(segment.alignment)) + .ok_or_else(|| vortex_err!("Segment length exceeds usize {}", segment.length))?; initial_read_segments.insert(segment_id, buffer); } + Ok(()) } }