Skip to content

Commit fce7095

Browse files
committed
gix-pack: delta application is a fallible operation
1 parent dd5f0a4 commit fce7095

File tree

5 files changed

+25
-7
lines changed

5 files changed

+25
-7
lines changed

gix-pack/src/cache/delta/traverse/mod.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,8 @@ pub enum Error {
4141
},
4242
#[error("Failed to spawn thread when switching to work-stealing mode")]
4343
SpawnThread(#[from] std::io::Error),
44+
#[error(transparent)]
45+
Delta(#[from] crate::data::delta::Error),
4446
}
4547

4648
/// Additional context passed to the `inspect_object(…)` function of the [`Tree::traverse()`] method.

gix-pack/src/cache/delta/traverse/resolve.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -188,7 +188,7 @@ where
188188
header_ofs += consumed;
189189

190190
fully_resolved_delta_bytes.resize(result_size as usize, 0);
191-
data::delta::apply(&base_bytes, fully_resolved_delta_bytes, &delta_bytes[header_ofs..]);
191+
data::delta::apply(&base_bytes, fully_resolved_delta_bytes, &delta_bytes[header_ofs..])?;
192192

193193
// FIXME: this actually invalidates the "pack_offset()" computation, which is not obvious to consumers
194194
// at all
@@ -367,7 +367,7 @@ where
367367
&base_bytes,
368368
&mut fully_resolved_delta_bytes,
369369
&delta_bytes[header_ofs..],
370-
);
370+
)?;
371371

372372
// FIXME: this actually invalidates the "pack_offset()" computation, which is not obvious to consumers
373373
// at all

gix-pack/src/data/delta.rs

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,15 @@
1+
/// Returned by [`Tree::traverse()`]
2+
#[derive(thiserror::Error, Debug)]
3+
#[allow(missing_docs)]
4+
pub enum Error {
5+
#[error("Encountered unsupported command code: 0")]
6+
UnsupportedCommandCode,
7+
#[error("Delta copy from base: byte slices must match")]
8+
DeltaCopyBaseSliceMismatch,
9+
#[error("Delta copy data: byte slices must match")]
10+
DeltaCopyDataSliceMismatch,
11+
}
12+
113
/// Given the decompressed pack delta `d`, decode a size in bytes (either the base object size or the result object size)
214
/// Equivalent to [this canonical git function](https://github.com/git/git/blob/311531c9de557d25ac087c1637818bd2aad6eb3a/delta.h#L89)
315
pub fn decode_header_size(d: &[u8]) -> (u64, usize) {
@@ -15,7 +27,7 @@ pub fn decode_header_size(d: &[u8]) -> (u64, usize) {
1527
(size, consumed)
1628
}
1729

18-
pub fn apply(base: &[u8], mut target: &mut [u8], data: &[u8]) {
30+
pub fn apply(base: &[u8], mut target: &mut [u8], data: &[u8]) -> Result<(), Error> {
1931
let mut i = 0;
2032
while let Some(cmd) = data.get(i) {
2133
i += 1;
@@ -55,16 +67,18 @@ pub fn apply(base: &[u8], mut target: &mut [u8], data: &[u8]) {
5567
}
5668
let ofs = ofs as usize;
5769
std::io::Write::write(&mut target, &base[ofs..ofs + size as usize])
58-
.expect("delta copy from base: byte slices must match");
70+
.map_err(|_e| Error::DeltaCopyBaseSliceMismatch)?;
5971
}
60-
0 => panic!("encountered unsupported command code: 0"),
72+
0 => return Err(Error::UnsupportedCommandCode),
6173
size => {
6274
std::io::Write::write(&mut target, &data[i..i + *size as usize])
63-
.expect("delta copy data: slice sizes to match up");
75+
.map_err(|_e| Error::DeltaCopyDataSliceMismatch)?;
6476
i += *size as usize;
6577
}
6678
}
6779
}
6880
assert_eq!(i, data.len());
6981
assert_eq!(target.len(), 0);
82+
83+
Ok(())
7084
}

gix-pack/src/data/file/decode/entry.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -374,7 +374,7 @@ impl File {
374374
if delta_idx + 1 == chain_len {
375375
last_result_size = Some(result_size);
376376
}
377-
delta::apply(&source_buf[..base_size], &mut target_buf[..result_size], data);
377+
delta::apply(&source_buf[..base_size], &mut target_buf[..result_size], data)?;
378378
// use the target as source for the next delta
379379
std::mem::swap(&mut source_buf, &mut target_buf);
380380
}

gix-pack/src/data/file/decode/mod.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@ pub enum Error {
1919
EntryType(#[from] crate::data::entry::decode::Error),
2020
#[error("Entry too large to fit in memory")]
2121
OutOfMemory,
22+
#[error(transparent)]
23+
Delta(#[from] crate::data::delta::Error),
2224
}
2325

2426
impl From<TryReserveError> for Error {

0 commit comments

Comments
 (0)