diff --git a/block/src/formats/qcow/internal/header.rs b/block/src/formats/qcow/internal/header.rs index 22a5492b1..030815438 100644 --- a/block/src/formats/qcow/internal/header.rs +++ b/block/src/formats/qcow/internal/header.rs @@ -332,6 +332,18 @@ impl QcowHeader { return Err(Error::BackingFileTooLong(header.backing_file_size as usize)); } if header.backing_file_offset != 0 { + let cluster_size = 1u64 + .checked_shl(header.cluster_bits) + .ok_or(Error::InvalidClusterSize)?; + if header.backing_file_offset >= cluster_size + || header.backing_file_offset + u64::from(header.backing_file_size) > cluster_size + { + return Err(Error::BackingFileOutsideFirstCluster( + header.backing_file_offset, + header.backing_file_size, + cluster_size, + )); + } f.seek(SeekFrom::Start(header.backing_file_offset)) .map_err(Error::ReadingHeader)?; let mut backing_file_name_bytes = vec![0u8; header.backing_file_size as usize]; diff --git a/block/src/formats/qcow/internal/mod.rs b/block/src/formats/qcow/internal/mod.rs index bb695e815..a2da14318 100644 --- a/block/src/formats/qcow/internal/mod.rs +++ b/block/src/formats/qcow/internal/mod.rs @@ -68,6 +68,10 @@ pub enum Error { BackingFileIo(String /* path */, #[source] io::Error), #[error("Backing file open error: {0}")] BackingFileOpen(String /* path */, #[source] Box), + #[error( + "Backing file name at offset {0:#x} length {1:#x} lies outside first cluster of {2:#x}" + )] + BackingFileOutsideFirstCluster(u64, u32, u64), #[error("Backing file support is disabled")] BackingFilesDisabled, #[error("Backing file name is too long: {0} bytes over")]