Skip to content

Commit 52906fb

Browse files
authored
Merge pull request #2059 from bradlarsen/main
gix-pack: delta application is a fallible operation
2 parents dd5f0a4 + 56ca4bf commit 52906fb

File tree

6 files changed

+31
-9
lines changed

6 files changed

+31
-9
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::apply::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: 22 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,21 @@
1+
///
2+
pub mod apply {
3+
/// Returned when failing to apply deltas.
4+
#[derive(thiserror::Error, Debug)]
5+
#[allow(missing_docs)]
6+
pub enum Error {
7+
#[error("Encountered unsupported command code: 0")]
8+
UnsupportedCommandCode,
9+
#[error("Delta copy from base: byte slices must match")]
10+
DeltaCopyBaseSliceMismatch,
11+
#[error("Delta copy data: byte slices must match")]
12+
DeltaCopyDataSliceMismatch,
13+
}
14+
}
15+
116
/// Given the decompressed pack delta `d`, decode a size in bytes (either the base object size or the result object size)
217
/// Equivalent to [this canonical git function](https://github.com/git/git/blob/311531c9de557d25ac087c1637818bd2aad6eb3a/delta.h#L89)
3-
pub fn decode_header_size(d: &[u8]) -> (u64, usize) {
18+
pub(crate) fn decode_header_size(d: &[u8]) -> (u64, usize) {
419
let mut i = 0;
520
let mut size = 0u64;
621
let mut consumed = 0;
@@ -15,7 +30,7 @@ pub fn decode_header_size(d: &[u8]) -> (u64, usize) {
1530
(size, consumed)
1631
}
1732

18-
pub fn apply(base: &[u8], mut target: &mut [u8], data: &[u8]) {
33+
pub(crate) fn apply(base: &[u8], mut target: &mut [u8], data: &[u8]) -> Result<(), apply::Error> {
1934
let mut i = 0;
2035
while let Some(cmd) = data.get(i) {
2136
i += 1;
@@ -55,16 +70,18 @@ pub fn apply(base: &[u8], mut target: &mut [u8], data: &[u8]) {
5570
}
5671
let ofs = ofs as usize;
5772
std::io::Write::write(&mut target, &base[ofs..ofs + size as usize])
58-
.expect("delta copy from base: byte slices must match");
73+
.map_err(|_e| apply::Error::DeltaCopyBaseSliceMismatch)?;
5974
}
60-
0 => panic!("encountered unsupported command code: 0"),
75+
0 => return Err(apply::Error::UnsupportedCommandCode),
6176
size => {
6277
std::io::Write::write(&mut target, &data[i..i + *size as usize])
63-
.expect("delta copy data: slice sizes to match up");
78+
.map_err(|_e| apply::Error::DeltaCopyDataSliceMismatch)?;
6479
i += *size as usize;
6580
}
6681
}
6782
}
6883
assert_eq!(i, data.len());
6984
assert_eq!(target.len(), 0);
85+
86+
Ok(())
7087
}

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::apply::Error),
2224
}
2325

2426
impl From<TryReserveError> for Error {

gix-pack/src/data/mod.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -128,4 +128,5 @@ impl File {
128128
}
129129
}
130130

131-
pub(crate) mod delta;
131+
///
132+
pub mod delta;

0 commit comments

Comments
 (0)