Skip to content
Open
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
2 changes: 1 addition & 1 deletion archive-zip.c
Original file line number Diff line number Diff line change
Expand Up @@ -206,7 +206,7 @@ static void *zlib_deflate_raw(void *data, unsigned long size,
unsigned long *compressed_size)
{
git_zstream stream;
unsigned long maxsize;
size_t maxsize;
void *buffer;
int result;

Expand Down
6 changes: 4 additions & 2 deletions builtin/fast-import.c
Original file line number Diff line number Diff line change
Expand Up @@ -962,7 +962,7 @@ static int store_object(
struct object_entry *e;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Patrick Steinhardt wrote on the Git mailing list (how to reply to this email):

On Thu, Jul 09, 2026 at 04:49:33PM +0000, Johannes Schindelin via GitGitGadget wrote:
[snip]
> Note that GCC struggles a bit to figure out that `deltalen` is always
> initialized before it is used; To help it along, we initialize it to 0.
> This work-around will go away in a later patch series when `deltalen`
> can be widened to `size_t`.

Thanks for putting this note here, I was wondering about that part.

Patrick

unsigned char hdr[96];
struct object_id oid;
unsigned long hdrlen, deltalen;
unsigned long hdrlen, deltalen = 0;
struct git_hash_ctx c;
git_zstream s;
struct repo_config_values *cfg = repo_config_values(the_repository);
Expand Down Expand Up @@ -998,11 +998,13 @@ static int store_object(

if (last && last->data.len && last->data.buf && last->depth < max_depth
&& dat->len > the_hash_algo->rawsz) {
size_t deltalen_st;

delta_count_attempts_by_type[type]++;
delta = diff_delta(last->data.buf, last->data.len,
dat->buf, dat->len,
&deltalen, dat->len - the_hash_algo->rawsz);
&deltalen_st, dat->len - the_hash_algo->rawsz);
deltalen = cast_size_t_to_ulong(deltalen_st);
} else
delta = NULL;

Expand Down
30 changes: 16 additions & 14 deletions builtin/pack-objects.c
Original file line number Diff line number Diff line change
Expand Up @@ -260,8 +260,8 @@ static int exclude_promisor_objects_best_effort;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Patrick Steinhardt wrote on the Git mailing list (how to reply to this email):

On Thu, Jul 09, 2026 at 04:49:30PM +0000, Johannes Schindelin via GitGitGadget wrote:
> diff --git a/builtin/pack-objects.c b/builtin/pack-objects.c
> index e3760b3492..f89628a760 100644
> --- a/builtin/pack-objects.c
> +++ b/builtin/pack-objects.c
> @@ -260,8 +260,8 @@ static int exclude_promisor_objects_best_effort;
>  
>  static int use_delta_islands;
>  
> -static unsigned long delta_cache_size = 0;
> -static unsigned long max_delta_cache_size = DEFAULT_DELTA_CACHE_SIZE;
> +static size_t delta_cache_size = 0;
> +static size_t max_delta_cache_size = DEFAULT_DELTA_CACHE_SIZE;

The only other site that assigns `max_delta_cache_size` does so via
`git_config_int()`, so we happily accept negative values for
"pack.deltacachesize". This will cause a change in behaviour here, even
though arguably the behaviour both before and after this patch is broken
in the same way.

Ideally we'd have something like `git_config_size_t()`, or at least use
`git_config_uint()` here. But that could potentially break the case
where somebody mistakenly configured a negative value and took it as
"infinite", which was mostly true before.

In any case, our docs only mention positive values. So maybe this is
something we could fix while at it.

Patrick

static int use_delta_islands;

static unsigned long delta_cache_size = 0;
static unsigned long max_delta_cache_size = DEFAULT_DELTA_CACHE_SIZE;
static size_t delta_cache_size = 0;
static size_t max_delta_cache_size = DEFAULT_DELTA_CACHE_SIZE;
static unsigned long cache_max_small_delta_size = 1000;

static unsigned long window_memory_limit = 0;
Expand Down Expand Up @@ -353,7 +353,8 @@ static void index_commit_for_bitmap(struct commit *commit)

static void *get_delta(struct object_entry *entry)
{
unsigned long size, base_size, delta_size;
unsigned long size, base_size;
size_t delta_size;
void *buf, *base_buf, *delta_buf;
enum object_type type;
size_t size_st = 0, base_size_st = 0;
Expand Down Expand Up @@ -487,7 +488,7 @@ static void copy_pack_data(struct hashfile *f,
off_t len)
{
unsigned char *in;
unsigned long avail;
size_t avail;

while (len) {
in = use_pack(p, w_curs, offset, &avail);
Expand Down Expand Up @@ -2260,7 +2261,7 @@ static void check_object(struct object_entry *entry, uint32_t object_index)
struct object_id base_ref;
struct object_entry *base_entry;
unsigned long used, used_0;
unsigned long avail;
size_t avail;
off_t ofs;
unsigned char *buf, c;
enum object_type type;
Expand Down Expand Up @@ -2688,8 +2689,8 @@ struct unpacked {
unsigned depth;
};

static int delta_cacheable(unsigned long src_size, unsigned long trg_size,
unsigned long delta_size)
static int delta_cacheable(size_t src_size, size_t trg_size,
size_t delta_size)
{
if (max_delta_cache_size && delta_cache_size + delta_size > max_delta_cache_size)
return 0;
Expand Down Expand Up @@ -2772,8 +2773,8 @@ size_t oe_get_size_slow(struct packing_data *pack,
struct pack_window *w_curs;
unsigned char *buf;
enum object_type type;
unsigned long used, avail;
size_t size;
unsigned long used;
size_t avail, size;

if (e->type_ != OBJ_OFS_DELTA && e->type_ != OBJ_REF_DELTA) {
size_t sz;
Expand Down Expand Up @@ -2804,11 +2805,12 @@ size_t oe_get_size_slow(struct packing_data *pack,
}

static int try_delta(struct unpacked *trg, struct unpacked *src,
unsigned max_depth, unsigned long *mem_usage)
unsigned max_depth, size_t *mem_usage)
{
struct object_entry *trg_entry = trg->entry;
struct object_entry *src_entry = src->entry;
unsigned long trg_size, src_size, delta_size, sizediff, max_size, sz;
unsigned long trg_size, src_size, sizediff, max_size, sz;
size_t delta_size;
unsigned ref_depth;
enum object_type type;
void *delta_buf;
Expand Down Expand Up @@ -2972,9 +2974,9 @@ static unsigned int check_delta_limit(struct object_entry *me, unsigned int n)
return m;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Patrick Steinhardt wrote on the Git mailing list (how to reply to this email):

On Thu, Jul 09, 2026 at 04:49:31PM +0000, Johannes Schindelin via GitGitGadget wrote:
> From: Johannes Schindelin <johannes.schindelin@gmx.de>
> diff --git a/builtin/pack-objects.c b/builtin/pack-objects.c
> index f89628a760..4737a6a32c 100644
> --- a/builtin/pack-objects.c
> +++ b/builtin/pack-objects.c
> @@ -2972,9 +2972,9 @@ static unsigned int check_delta_limit(struct object_entry *me, unsigned int n)
>  	return m;
>  }
>  
> -static unsigned long free_unpacked(struct unpacked *n)
> +static size_t free_unpacked(struct unpacked *n)
>  {
> -	unsigned long freed_mem = sizeof_delta_index(n->index);
> +	size_t freed_mem = sizeof_delta_index(n->index);

Okay. As mentioned on a preceding patch, the function itself still
returns `unsigned long`, which should probably also be corrected in this
patch series.

Patrick

}

static unsigned long free_unpacked(struct unpacked *n)
static size_t free_unpacked(struct unpacked *n)
{
unsigned long freed_mem = sizeof_delta_index(n->index);
size_t freed_mem = sizeof_delta_index(n->index);
free_delta_index(n->index);
n->index = NULL;
if (n->data) {
Expand All @@ -2991,7 +2993,7 @@ static void find_deltas(struct object_entry **list, unsigned *list_size,
{
uint32_t i, idx = 0, count = 0;
struct unpacked *array;
unsigned long mem_usage = 0;
size_t mem_usage = 0;

CALLOC_ARRAY(array, window);

Expand Down
12 changes: 6 additions & 6 deletions delta.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ struct delta_index;
* using free_delta_index().
*/
struct delta_index *
create_delta_index(const void *buf, unsigned long bufsize);
create_delta_index(const void *buf, size_t bufsize);

/*
* free_delta_index: free the index created by create_delta_index()
Expand Down Expand Up @@ -42,8 +42,8 @@ unsigned long sizeof_delta_index(struct delta_index *index);
*/
void *
create_delta(const struct delta_index *index,
const void *buf, unsigned long bufsize,
unsigned long *delta_size, unsigned long max_delta_size);
const void *buf, size_t bufsize,
size_t *delta_size, size_t max_delta_size);

/*
* diff_delta: create a delta from source buffer to target buffer
Expand All @@ -54,9 +54,9 @@ create_delta(const struct delta_index *index,
* updated with its size. The returned buffer must be freed by the caller.
*/
static inline void *
diff_delta(const void *src_buf, unsigned long src_bufsize,
const void *trg_buf, unsigned long trg_bufsize,
unsigned long *delta_size, unsigned long max_delta_size)
diff_delta(const void *src_buf, size_t src_bufsize,
const void *trg_buf, size_t trg_bufsize,
size_t *delta_size, size_t max_delta_size)
{
struct delta_index *index = create_delta_index(src_buf, src_bufsize);
if (index) {
Expand Down
12 changes: 6 additions & 6 deletions diff-delta.c
Original file line number Diff line number Diff line change
Expand Up @@ -125,22 +125,22 @@ struct unpacked_index_entry {
};

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Patrick Steinhardt wrote on the Git mailing list (how to reply to this email):

On Thu, Jul 09, 2026 at 04:49:28PM +0000, Johannes Schindelin via GitGitGadget wrote:
> diff --git a/diff-delta.c b/diff-delta.c
> index 43c339f010..b6b65d7607 100644
> --- a/diff-delta.c
> +++ b/diff-delta.c
> @@ -125,9 +125,9 @@ struct unpacked_index_entry {
>  };
>  
>  struct delta_index {
> -	unsigned long memsize;
> +	size_t memsize;
>  	const void *src_buf;
> -	unsigned long src_size;
> +	size_t src_size;
>  	unsigned int hash_mask;
>  	struct index_entry *hash[FLEX_ARRAY];
>  };

`sizeof_delta_index` returns `index->memsize`, so we'll also have to
adapt that function's return value and its callers.

> @@ -140,7 +140,7 @@ struct delta_index * create_delta_index(const void *buf, unsigned long bufsize)

I was about to complain that the input parameter here uses `unsigned
long`, too. But the next patch addresses that.

>  	struct unpacked_index_entry *entry, **hash;
>  	struct index_entry *packed_entry, **packed_hash;
>  	void *mem;
> -	unsigned long memsize;
> +	size_t memsize;
>  
>  	if (!buf || !bufsize)
>  		return NULL;

Patrick


struct delta_index {
unsigned long memsize;
size_t memsize;
const void *src_buf;
unsigned long src_size;
size_t src_size;
unsigned int hash_mask;
struct index_entry *hash[FLEX_ARRAY];
};

struct delta_index * create_delta_index(const void *buf, unsigned long bufsize)
struct delta_index * create_delta_index(const void *buf, size_t bufsize)
{
unsigned int i, hsize, hmask, entries, prev_val, *hash_count;
const unsigned char *data, *buffer = buf;
struct delta_index *index;
struct unpacked_index_entry *entry, **hash;
struct index_entry *packed_entry, **packed_hash;
void *mem;
unsigned long memsize;
size_t memsize;

if (!buf || !bufsize)
return NULL;
Expand Down Expand Up @@ -318,8 +318,8 @@ unsigned long sizeof_delta_index(struct delta_index *index)

void *
create_delta(const struct delta_index *index,
const void *trg_buf, unsigned long trg_size,
unsigned long *delta_size, unsigned long max_size)
const void *trg_buf, size_t trg_size,
size_t *delta_size, size_t max_size)
{
unsigned int i, val;
off_t outpos, moff;
Expand Down
6 changes: 4 additions & 2 deletions diff.c
Original file line number Diff line number Diff line change
Expand Up @@ -3609,7 +3609,7 @@ static unsigned char *deflate_it(char *data,
unsigned long size,
unsigned long *result_size)
{
int bound;
size_t bound;
unsigned char *deflated;
git_zstream stream;
struct repo_config_values *cfg = repo_config_values(the_repository);
Expand Down Expand Up @@ -3647,9 +3647,11 @@ static void emit_binary_diff_body(struct diff_options *o,
delta = NULL;
deflated = deflate_it(two->ptr, two->size, &deflate_size);
if (one->size && two->size) {
size_t delta_size_st = 0;
delta = diff_delta(one->ptr, one->size,
two->ptr, two->size,
&delta_size, deflate_size);
&delta_size_st, deflate_size);
delta_size = cast_size_t_to_ulong(delta_size_st);
if (delta) {
void *to_free = delta;
orig_size = delta_size;
Expand Down
16 changes: 14 additions & 2 deletions git-zlib.c
Original file line number Diff line number Diff line change
Expand Up @@ -167,9 +167,21 @@ int git_inflate(git_zstream *strm, int flush)
return status;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Patrick Steinhardt wrote on the Git mailing list (how to reply to this email):

On Thu, Jul 09, 2026 at 04:49:39PM +0000, Johannes Schindelin via GitGitGadget wrote:
> From: Johannes Schindelin <johannes.schindelin@gmx.de>
> 
> All four `unsigned long`/`int`/`ssize_t` receivers across archive-zip,
> diff, http-push and t/helper/test-pack-deltas were widened to `size_t`
> in the prior commits, and remote-curl and fast-import were already
> there. With every caller prepared, both the parameter and the return
> type can now move without introducing any silent narrowing.

Nit, feel free to ignore: I feel like all of these patches could've been
squashed into a single one, as they're trivial enough.

> For inputs above zlib's `uLong` range (i.e. >4 GiB on platforms where
> `uLong` is 32-bit, notably 64-bit Windows), defer to zlib's stored-block
> formula (the same fallback it would itself use for an unknown stream
> state) plus the worst-case wrapper overhead. The existing path through
> `deflateBound()` is unchanged for inputs that fit.

A link or something like that to the formula would've helped here, as
I'm not familiar with this mechanism.

> diff --git a/git-zlib.c b/git-zlib.c
> index d21adb3bf5..ebbbcc6d1a 100644
> --- a/git-zlib.c
> +++ b/git-zlib.c
> @@ -167,9 +167,21 @@ int git_inflate(git_zstream *strm, int flush)
>  	return status;
>  }
>  
> -unsigned long git_deflate_bound(git_zstream *strm, unsigned long size)
> +size_t git_deflate_bound(git_zstream *strm, size_t size)
>  {
> -	return deflateBound(&strm->z, size);
> +#if SIZE_MAX > ULONG_MAX
> +	if (size > maximum_unsigned_value_of_type(uLong))
> +		/*
> +		 * deflateBound() takes uLong, which is 32-bit on
> +		 * Windows. For inputs above that range, return zlib's
> +		 * stored-block formula (the conservative path it would
> +		 * itself use for an unknown stream state) plus the
> +		 * worst-case wrapper overhead.
> +		 */
> +		return size + (size >> 5) + (size >> 7) + (size >> 11)
> +			+ 7 + 18;
> +#endif

So is the idea here that we estimate the highest number of bytes that
the deflated size could end up with?

Patrick

}

unsigned long git_deflate_bound(git_zstream *strm, unsigned long size)
size_t git_deflate_bound(git_zstream *strm, size_t size)
{
return deflateBound(&strm->z, size);
#if SIZE_MAX > ULONG_MAX
if (size > maximum_unsigned_value_of_type(uLong))
/*
* deflateBound() takes uLong, which is 32-bit on
* Windows. For inputs above that range, return zlib's
* stored-block formula (the conservative path it would
* itself use for an unknown stream state) plus the
* worst-case wrapper overhead.
*/
return size + (size >> 5) + (size >> 7) + (size >> 11)
+ 7 + 18;
#endif
return deflateBound(&strm->z, (uLong)size);
}

void git_deflate_init(git_zstream *strm, int level)
Expand Down
6 changes: 3 additions & 3 deletions git-zlib.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@

typedef struct git_zstream {
struct z_stream_s z;
unsigned long avail_in;
unsigned long avail_out;
size_t avail_in;
size_t avail_out;
size_t total_in;
size_t total_out;
unsigned char *next_in;
Expand All @@ -25,6 +25,6 @@ void git_deflate_end(git_zstream *);
int git_deflate_abort(git_zstream *);
int git_deflate_end_gently(git_zstream *);
int git_deflate(git_zstream *, int flush);
unsigned long git_deflate_bound(git_zstream *, unsigned long);
size_t git_deflate_bound(git_zstream *, size_t);

#endif /* GIT_ZLIB_H */
2 changes: 1 addition & 1 deletion http-push.c
Original file line number Diff line number Diff line change
Expand Up @@ -367,7 +367,7 @@ static void start_put(struct transfer_request *request)
void *unpacked;
size_t len;
int hdrlen;
ssize_t size;
size_t size;
git_zstream stream;
struct repo_config_values *cfg = repo_config_values(the_repository);

Expand Down
4 changes: 2 additions & 2 deletions pack-check.c
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ int check_pack_crc(struct packed_git *p, struct pack_window **w_curs,
uint32_t data_crc = crc32(0, NULL, 0);

do {
unsigned long avail;
size_t avail;
void *data = use_pack(p, w_curs, offset, &avail);
if (avail > len)
avail = len;
Expand Down Expand Up @@ -71,7 +71,7 @@ static int verify_packfile(struct repository *r,

r->hash_algo->init_fn(&ctx);
do {
unsigned long remaining;
size_t remaining;
unsigned char *in = use_pack(p, w_curs, offset, &remaining);
offset += remaining;
if (!pack_sig_ofs)
Expand Down
4 changes: 2 additions & 2 deletions packfile.c
Original file line number Diff line number Diff line change
Expand Up @@ -620,7 +620,7 @@ static int in_window(struct repository *r, struct pack_window *win,
unsigned char *use_pack(struct packed_git *p,
struct pack_window **w_cursor,
off_t offset,
unsigned long *left)
size_t *left)
{
struct pack_window *win = *w_cursor;

Expand Down Expand Up @@ -960,7 +960,7 @@ int unpack_object_header(struct packed_git *p,
size_t *sizep)
{
unsigned char *base;
unsigned long left;
size_t left;
unsigned long used;
enum object_type type;

Expand Down
3 changes: 2 additions & 1 deletion packfile.h
Original file line number Diff line number Diff line change
Expand Up @@ -240,7 +240,8 @@ uint32_t get_pack_fanout(struct packed_git *p, uint32_t value);

struct object_database;

unsigned char *use_pack(struct packed_git *, struct pack_window **, off_t, unsigned long *);
unsigned char *use_pack(struct packed_git *, struct pack_window **, off_t,
size_t *);
void close_pack_windows(struct packed_git *);
void close_pack(struct packed_git *);
void unuse_pack(struct pack_window **);
Expand Down
2 changes: 1 addition & 1 deletion t/helper/test-delta.c
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ int cmd__delta(int argc, const char **argv)
die_errno("unable to read '%s'", argv[3]);

if (argv[1][1] == 'd') {
unsigned long delta_size;
size_t delta_size;
out_buf = diff_delta(from.buf, from.len,
data.buf, data.len,
&delta_size, 0);
Expand Down
7 changes: 4 additions & 3 deletions t/helper/test-pack-deltas.c
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ static unsigned long do_compress(void **pptr, unsigned long size)
{
git_zstream stream;
void *in, *out;
unsigned long maxsize;
size_t maxsize;

git_deflate_init(&stream, 1);
maxsize = git_deflate_bound(&stream, size);
Expand All @@ -49,7 +49,7 @@ static void write_ref_delta(struct hashfile *f,
{
unsigned char header[MAX_PACK_OBJECT_HEADER];
unsigned long delta_size, compressed_size, hdrlen;
size_t size, base_size;
size_t size, base_size, delta_size_st = 0;
enum object_type type;
void *base_buf, *delta_buf;
void *buf = odb_read_object(the_repository->objects,
Expand All @@ -65,7 +65,8 @@ static void write_ref_delta(struct hashfile *f,
die("unable to read %s", oid_to_hex(base));

delta_buf = diff_delta(base_buf, base_size,
buf, size, &delta_size, 0);
buf, size, &delta_size_st, 0);
delta_size = cast_size_t_to_ulong(delta_size_st);

compressed_size = do_compress(&delta_buf, delta_size);

Expand Down
Loading