diff --git a/block/src/formats/vhdx/internal/header.rs b/block/src/formats/vhdx/internal/header.rs index db7de7433..d6aa7e93b 100644 --- a/block/src/formats/vhdx/internal/header.rs +++ b/block/src/formats/vhdx/internal/header.rs @@ -72,6 +72,8 @@ pub enum VhdxHeaderError { ReadRegionTableHeader(#[source] io::Error), #[error("Failed to read region entries")] RegionEntryCollectionFailed, + #[error("Region entry file offset ({0}) and length ({1}) overflow u64")] + RegionEntryOverflow(u64 /* start */, usize /* length */), #[error("Overlapping regions found")] RegionOverlap, #[error("Reserved region has non-zero value")] @@ -264,7 +266,9 @@ impl RegionInfo { offset += size_of::(); let start = entry.file_offset; - let end = start + entry.length as u64; + let end = start.checked_add(entry.length as u64).ok_or( + VhdxHeaderError::RegionEntryOverflow(start, entry.length as usize), + )?; for (region_ent_start, region_ent_end) in region_entries.iter() { if ranges_overlap(start, end, *region_ent_start, *region_ent_end) { @@ -272,7 +276,7 @@ impl RegionInfo { } } - region_entries.insert(entry.file_offset, entry.file_offset + entry.length as u64); + region_entries.insert(start, end); if entry.guid == BAT_GUID { if bat_entry.is_none() { @@ -560,4 +564,26 @@ mod tests { "expected RegionOverlap for an overlapping region table" ); } + + #[test] + fn test_region_info_rejects_overflowing_region() { + // A region whose file offset plus length wraps past u64::MAX must be + // rejected rather than silently producing a small end offset that + // could mask a genuine overlap. + let region_start = REGION_TABLE_1_START; + let entries_at = region_start + size_of::() as u64; + + let temp = TempFile::new().unwrap(); + let f = temp.into_file(); + f.set_len(entries_at + 64 * 1024).unwrap(); + f.write_all_at(®ion_entry(BAT_GUID, u64::MAX, 0x1000), entries_at) + .unwrap(); + + let af = AlignedFile::new(f, false); + let res = RegionInfo::new(&af, region_start, 1); + assert!( + matches!(res, Err(VhdxHeaderError::RegionEntryOverflow(..))), + "expected RegionEntryOverflow for a wrapping region entry" + ); + } }