Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 18 additions & 1 deletion src/internal/pack/decode.rs
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,10 @@ impl Pack {
temp_path.pop();
}
let thread_num = thread_num.unwrap_or_else(num_cpus::get);
let cache_mem_size = mem_limit.map(|mem_limit| mem_limit * 4 / 5);
let cache_mem_size = mem_limit.map(|mem_limit| {
// Use wider math to avoid 32-bit overflow when computing 80%.
((mem_limit as u128) * 4 / 5) as usize
});
Pack {
number: 0,
signature: ObjectHash::default(),
Expand Down Expand Up @@ -838,6 +841,20 @@ mod tests {
}
}

#[test]
#[cfg(target_pointer_width = "32")]
fn test_pack_new_mem_limit_no_overflow_32bit() {
// In the old code, 1.2B * 4 produced an intermediate 4.8B value, which exceeds
// 32-bit usize::MAX (~4.29B) and overflowed before a later division; this test
// covers that former panic path.
let mem_limit = 1_200_000_000usize;
let tmp = PathBuf::from("/tmp/.cache_temp");
let result = std::panic::catch_unwind(|| {
let _p = Pack::new(Some(1), Some(mem_limit), Some(tmp), true);
});
assert!(result.is_ok(), "Pack::new should not panic on 32-bit");
}

/// Helper function to run decode tests without delta objects
fn run_decode_no_delta(rel_path: &str, kind: HashKind) {
let _guard = set_hash_kind(kind);
Expand Down
15 changes: 14 additions & 1 deletion src/internal/pack/encode.rs
Original file line number Diff line number Diff line change
Expand Up @@ -753,9 +753,22 @@ mod tests {

/// Check if the given data is a valid pack file format by attempting to decode it.
fn check_format(data: &Vec<u8>) {
// Use a smaller cap on 32-bit targets to avoid usize overflow.
let max_pack_size_u64 = if cfg!(target_pointer_width = "64") {
Comment thread
yueneiqi marked this conversation as resolved.
6u64 * 1024 * 1024 * 1024
} else {
2u64 * 1024 * 1024 * 1024
};
let max_pack_size = usize::try_from(max_pack_size_u64).unwrap_or_else(|_| {
panic!(
"internal assertion failed: pack size cap {} does not fit in usize on this \
target; this should be unreachable given the target_pointer_width configuration",
max_pack_size_u64
)
});
let mut p = Pack::new(
None,
Some(1024 * 1024 * 1024 * 6), // 6GB
Some(max_pack_size), // 6GB on 64-bit, 2GB on 32-bit
Some(PathBuf::from("/tmp/.cache_temp")),
true,
);
Expand Down