From 33afe873381b21db08fa65e0910fd3bb69fd739b Mon Sep 17 00:00:00 2001 From: Johannes Schindelin Date: Mon, 15 Jun 2026 11:52:24 +0000 Subject: [PATCH] patch-delta: use size_t for sizes `patch_delta()` takes the source and delta sizes by value and writes back the reconstructed target size through an `unsigned long *`. That datatype cannot represent a value that exceeds 4 GiB on systems where `unsigned long` is 32-bit (notably 64-bit Windows builds), though, even though the delta encoding itself, the on-disk layout, and the in-memory buffers happily carry such sizes. A `size_t` companion to `get_delta_hdr_size()`, `get_delta_hdr_size_sz()`, was introduced in 17fa077596 (delta, packfile: use size_t for delta header sizes, 2026-05-08) precisely so that `patch_delta()` could be widened without changing the on-the-wire decoding helper's signature. Widen `patch_delta()`'s three size parameters to `size_t` and switch its internal use of `get_delta_hdr_size()` to the `_sz` variant. Then propagate the wider type through the callers. Assisted-by: Opus 4.7 Signed-off-by: Johannes Schindelin Signed-off-by: Junio C Hamano --- apply.c | 2 +- builtin/index-pack.c | 4 ++-- builtin/unpack-objects.c | 2 +- delta.h | 6 +++--- packfile.c | 4 +--- patch-delta.c | 12 ++++++------ t/helper/test-delta.c | 10 ++++++---- 7 files changed, 20 insertions(+), 20 deletions(-) diff --git a/apply.c b/apply.c index 249248d4f2..3cf544e9a9 100644 --- a/apply.c +++ b/apply.c @@ -3232,7 +3232,7 @@ static int apply_binary_fragment(struct apply_state *state, struct patch *patch) { struct fragment *fragment = patch->fragments; - unsigned long len; + size_t len; void *dst; if (!fragment) diff --git a/builtin/index-pack.c b/builtin/index-pack.c index cf0bd8280d..3c4474e681 100644 --- a/builtin/index-pack.c +++ b/builtin/index-pack.c @@ -71,7 +71,7 @@ struct base_data { /* Not initialized by make_base(). */ struct list_head list; void *data; - unsigned long size; + size_t size; }; /* @@ -1048,7 +1048,7 @@ static struct base_data *resolve_delta(struct object_entry *delta_obj, { void *delta_data, *result_data; struct base_data *result; - unsigned long result_size; + size_t result_size; if (show_stat) { int i = delta_obj - objects; diff --git a/builtin/unpack-objects.c b/builtin/unpack-objects.c index 59e9b8711e..e7a50c493c 100644 --- a/builtin/unpack-objects.c +++ b/builtin/unpack-objects.c @@ -314,7 +314,7 @@ static void resolve_delta(unsigned nr, enum object_type type, void *delta, unsigned long delta_size) { void *result; - unsigned long result_size; + size_t result_size; result = patch_delta(base, base_size, delta, delta_size, diff --git a/delta.h b/delta.h index fad68cfc45..bb149dc82b 100644 --- a/delta.h +++ b/delta.h @@ -75,9 +75,9 @@ diff_delta(const void *src_buf, unsigned long src_bufsize, * *trg_bufsize is updated with its size. On failure a NULL pointer is * returned. The returned buffer must be freed by the caller. */ -void *patch_delta(const void *src_buf, unsigned long src_size, - const void *delta_buf, unsigned long delta_size, - unsigned long *dst_size); +void *patch_delta(const void *src_buf, size_t src_size, + const void *delta_buf, size_t delta_size, + size_t *dst_size); /* the smallest possible delta size is 4 bytes */ #define DELTA_SIZE_MIN 4 diff --git a/packfile.c b/packfile.c index 89366abfe3..e202f48837 100644 --- a/packfile.c +++ b/packfile.c @@ -1964,10 +1964,8 @@ void *unpack_entry(struct repository *r, struct packed_git *p, off_t obj_offset, (uintmax_t)curpos, p->pack_name); data = NULL; } else { - unsigned long sz; data = patch_delta(base, base_size, delta_data, - delta_size, &sz); - size = sz; + delta_size, &size); /* * We could not apply the delta; warn the user, but diff --git a/patch-delta.c b/patch-delta.c index b5c8594db6..44cda97994 100644 --- a/patch-delta.c +++ b/patch-delta.c @@ -12,13 +12,13 @@ #include "git-compat-util.h" #include "delta.h" -void *patch_delta(const void *src_buf, unsigned long src_size, - const void *delta_buf, unsigned long delta_size, - unsigned long *dst_size) +void *patch_delta(const void *src_buf, size_t src_size, + const void *delta_buf, size_t delta_size, + size_t *dst_size) { const unsigned char *data, *top; unsigned char *dst_buf, *out, cmd; - unsigned long size; + size_t size; if (delta_size < DELTA_SIZE_MIN) return NULL; @@ -27,12 +27,12 @@ void *patch_delta(const void *src_buf, unsigned long src_size, top = (const unsigned char *) delta_buf + delta_size; /* make sure the orig file size matches what we expect */ - size = get_delta_hdr_size(&data, top); + size = get_delta_hdr_size_sz(&data, top); if (size != src_size) return NULL; /* now the result size */ - size = get_delta_hdr_size(&data, top); + size = get_delta_hdr_size_sz(&data, top); dst_buf = xmallocz(size); out = dst_buf; diff --git a/t/helper/test-delta.c b/t/helper/test-delta.c index 52ea00c937..8223a60229 100644 --- a/t/helper/test-delta.c +++ b/t/helper/test-delta.c @@ -21,7 +21,7 @@ int cmd__delta(int argc, const char **argv) int fd; struct strbuf from = STRBUF_INIT, data = STRBUF_INIT; char *out_buf; - unsigned long out_size; + size_t out_size; if (argc != 5 || (strcmp(argv[1], "-d") && strcmp(argv[1], "-p"))) usage(usage_str); @@ -31,11 +31,13 @@ int cmd__delta(int argc, const char **argv) if (strbuf_read_file(&data, argv[3], 0) < 0) die_errno("unable to read '%s'", argv[3]); - if (argv[1][1] == 'd') + if (argv[1][1] == 'd') { + unsigned long delta_size; out_buf = diff_delta(from.buf, from.len, data.buf, data.len, - &out_size, 0); - else + &delta_size, 0); + out_size = delta_size; + } else out_buf = patch_delta(from.buf, from.len, data.buf, data.len, &out_size);