sparse: Fix u32 overflow when unpacking files with large holes

CHUNK_TYPE_RAW is the only chunk type that's guaranteed to not overflow
a u32 when its number of blocks is multiplied by the block size.
CHUNK_TYPE_FILL and CHUNK_TYPE_DONT_CARE require a u64.

Issue: #472

Signed-off-by: Andrew Gunnerson <accounts+github@chiller3.com>
This commit is contained in:
Andrew Gunnerson
2025-08-07 01:36:22 -04:00
parent 59cf37faaf
commit 2314c371a8
2 changed files with 8 additions and 5 deletions
+4 -4
View File
@@ -1,4 +1,4 @@
// SPDX-FileCopyrightText: 2024 Andrew Gunnerson
// SPDX-FileCopyrightText: 2024-2025 Andrew Gunnerson
// SPDX-License-Identifier: GPL-3.0-only
use std::{
@@ -317,11 +317,11 @@ fn unpack_subcommand(
})?;
}
ChunkData::Hole => {
// This cannot overflow.
let to_skip = chunk.bounds.len() * metadata.header.block_size;
// Unlike ChunkData::Data, this can overflow a u32.
let to_skip = i64::from(chunk.bounds.len()) * i64::from(metadata.header.block_size);
writer
.seek(SeekFrom::Current(to_skip.into()))
.seek(SeekFrom::Current(to_skip))
.with_context(|| format!("Failed to seek file: {:?}", cli.output))?;
}
ChunkData::Crc32(_) => {}
+4 -1
View File
@@ -1,4 +1,4 @@
// SPDX-FileCopyrightText: 2024 Andrew Gunnerson
// SPDX-FileCopyrightText: 2024-2025 Andrew Gunnerson
// SPDX-License-Identifier: GPL-3.0-only
use std::{
@@ -374,6 +374,9 @@ impl fmt::Debug for ChunkData {
/// metadata they contain.
#[derive(Clone, Copy, PartialEq, Eq)]
pub struct Chunk {
/// When [`Self::data`] is [`ChunkData::Data`], this is guaranteed to not
/// exceed the bounds of [`u32`] when multiplied by [`Header::block_size`].
/// For other types of data, a 64-bit signed or unsigned integer is needed.
pub bounds: ChunkBounds,
pub data: ChunkData,
}