summaryrefslogtreecommitdiff
path: root/git-zlib.c
AgeCommit message (Collapse)AuthorFilesLines
2026-08-13git-zlib: widen `git_deflate_bound()` to `size_t`Johannes Schindelin1-2/+14
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. 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, see https://github.com/madler/zlib/blob/v1.3.2/deflate.c#L832-L928 keeping in mind that for large sizes, the `storelen` would be relevant, also compare with https://github.com/madler/zlib/issues/549 for a fuller story) plus the worst-case wrapper overhead. The existing path through `deflateBound()` is unchanged for inputs that fit. Assisted-by: Opus 4.7 Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-08-13packfile, git-zlib: widen `use_pack()` and zstream avail fields to `size_t`Johannes Schindelin1-1/+1
Bundling the two widenings: four call sites pass `&stream.avail_in` directly to `use_pack()`, and widening either type fencepost alone would force a bridge variable at each. Doing both together is the simpler end state and is the prerequisite for the `do_compress()` widening in the next commit, which is what lets `write_no_reuse_object()` lose its last `cast_size_t_to_ulong()` shim. The unsigned-long locals widened at the other `use_pack()` callers (avail / remaining / left) hold pack-window sizes bounded by `core.packedGitWindowSize`, so the change is type consistency rather than a new >4GB capability. `git_zstream.avail_in`/`avail_out` likewise reach zlib's `uInt` fields only after `zlib_buf_cap()`'s 1 GiB cap, so the wrapper already accepted `size_t`-shaped inputs in practice. Assisted-by: Opus 4.7 Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-06-18zlib: properly clamp to uLongJohannes Schindelin1-4/+9
On platforms where `unsigned long` and `size_t` differ in bit size, we want to clamp the buffers we pass to zlib to the former's size, as per d05d666977 (git-zlib: handle data streams larger than 4GB, 2026-05-08). The logic introduced in that commit performs a clamping to the bits, though, which fails to do what is needed here: If too many bytes are available in the buffers, we need to clamp to the maximum value of an `unsigned long`. Otherwise, we ask zlib to use too small buffers, in the worst case using 0 as the size (think: a value whose 32 lowest bits are all zero). Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-05-09git-zlib: handle data streams larger than 4GBJohannes Schindelin1-8/+17
On Windows, zlib's `uLong` type is 32-bit even on 64-bit systems. When processing data streams larger than 4GB, the `total_in` and `total_out` fields in zlib's `z_stream` structure wrap around, which caused the sanity checks in `zlib_post_call()` to trigger `BUG()` assertions. The git_zstream wrapper now tracks its own 64-bit totals rather than copying them from zlib. The sanity checks compare only the low bits, using `maximum_unsigned_value_of_type(uLong)` to mask appropriately for the platform's `uLong` size. This is based on work by LordKiRon in git-for-windows#6076. Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2025-04-15Merge branch 'jk/zlib-inflate-fixes'Junio C Hamano1-11/+16
Fix our use of zlib corner cases. * jk/zlib-inflate-fixes: unpack_loose_rest(): rewrite return handling for clarity unpack_loose_rest(): simplify error handling unpack_loose_rest(): never clean up zstream unpack_loose_rest(): avoid numeric comparison of zlib status unpack_loose_header(): avoid numeric comparison of zlib status git_inflate(): skip zlib_post_call() sanity check on Z_NEED_DICT unpack_loose_header(): fix infinite loop on broken zlib input unpack_loose_header(): report headers without NUL as "bad" unpack_loose_header(): simplify next_out assignment loose_object_info(): BUG() on inflating content with unknown type
2025-02-25git_inflate(): skip zlib_post_call() sanity check on Z_NEED_DICTJeff King1-11/+16
This fixes a case where malformed object input can cause us to hit a BUG() call in the git-zlib.c code. The zlib format allows the use of preset dictionaries to reduce the size of deflated data. The checksum of the dictionary is computed by the deflate code and goes into the stream. On the inflating side, zlib sees the dictionary checksum and returns Z_NEED_DICT, asking the caller to provide the dictionary data via inflateSetDictionary(). This should never happen in Git, because we never provide a dictionary for deflating (and if we get a stream that mentions a dictionary, we have no idea how to provide it). So normally Z_NEED_DICT is a hard error for us. But something interesting happens if we _do_ happen to see it (e.g., because of a corrupt or malicious input). In git_inflate() as we loop over calls to zlib's inflate(), we translate between our large-integer git_zstream values and zlib's native z_stream types, copying in and out with zlib_pre_call() and zlib_post_call(). In zlib_post_call() we have a few sanity checks, including one that checks that the number of bytes consumed by zlib (as measured by it moving the "next_in" pointer) is equal to the movement of its "total_in" count. But these do not correspond when we see Z_NEED_DICT! Zlib consumes the bytes from the input buffer but it does not increment total_in. And so we hit the BUG("total_in mismatch") call. There are a few options here: - We could ditch that BUG() check. It is making too many assumptions about how zlib updates these values. But it does have value in most cases as a sanity check on the values we're copying. - We could skip the zlib_post_call() entirely when we see Z_NEED_DICT. We know that it's hard error for us, so we should just send the status up the stack and let the caller bail. The downside is that if we ever did want to support dictionaries, we couldn't (the git_zstream will be out of sync, since we never copied its values back from the z_stream). - We could continue to call zlib_post_call(), but skip just that BUG() check if the status is Z_NEED_DICT. This keeps git_inflate() as a thin wrapper around inflate(), and would let us later support dictionaries for some calls if we wanted to. This patch uses the third approach. It seems like the least-surprising thing to keep git_inflate() a close to inflate() as possible. And while it makes the diff a bit larger (since we have to pass the status down to to the zlib_post_call() function), it's a static local function, and every caller by definition will have just made a zlib call (and so will have a status integer). Co-authored-by: Taylor Blau <me@ttaylorr.com> Signed-off-by: Jeff King <peff@peff.net> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2025-01-28git-zlib: cast away potential constness of `next_in` pointerPatrick Steinhardt1-1/+2
The `struct git_zstream::next_in` variable points to the input data and is used in combination with `struct z_stream::next_in`. While that latter field is not marked as a constant in zlib, it is marked as such in zlib-ng. This causes a couple of compiler errors when we try to assign these fields to one another due to mismatching constness. Fix the issue by casting away the potential constness of `next_in`. Signed-off-by: Patrick Steinhardt <ps@pks.im> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2025-01-28compat/zlib: provide `deflateBound()` shim centrallyPatrick Steinhardt1-4/+0
The `deflateBound()` function has only been introduced with zlib 1.2.0. When linking against a zlib version older than that we thus provide our own compatibility shim. Move this shim into "compat/zlib.h" so that we can adapt it based on whether or not we use zlib-ng in a subsequent commit. Signed-off-by: Patrick Steinhardt <ps@pks.im> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2023-04-11git-zlib: move declarations for git-zlib functions from cache.hElijah Newren1-0/+274
Move functions from cache.h for zlib.c into a new header file. Since adding a "zlib.h" would cause issues with the real zlib, rename zlib.c to git-zlib.c while we are at it. Signed-off-by: Elijah Newren <newren@gmail.com> Acked-by: Calvin Wan <calvinwan@google.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>