]> git.99rst.org Git - git.git/log
git.git
2 weeks agoMerge branch 'ps/reftable-hardening'
Junio C Hamano [Sun, 19 Jul 2026 17:42:14 +0000 (10:42 -0700)]
Merge branch 'ps/reftable-hardening'

The 'reftable' code has been hardened against corrupted tables by
fixing out-of-bounds writes, out-of-bounds reads, and abort calls
during parsing.

* ps/reftable-hardening:
  reftable/table: fix OOB read on truncated table
  reftable/table: fix NULL pointer access when seeking to bogus offsets
  reftable/block: fix OOB read with bogus restart offset
  reftable/block: fix use of uninitialized memory when binsearch fails
  reftable/block: fix OOB read with bogus restart count
  reftable/block: fix OOB read with bogus block size
  reftable/block: fix OOB write with bogus inflated log size
  t/unit-tests: introduce test helper to write reftable blocks
  reftable/record: don't abort when decoding invalid ref value type
  reftable/basics: fix OOB read on binary search of empty range
  oss-fuzz: add fuzzer for parsing reftables
  meson: support building fuzzers with libFuzzer

2 weeks agoThe 4th batch for Git 2.56
Junio C Hamano [Fri, 17 Jul 2026 04:31:50 +0000 (21:31 -0700)]
The 4th batch for Git 2.56

Signed-off-by: Junio C Hamano <redacted>
2 weeks agoMerge branch 'mm/sideband-ansi-sgr-colon-fix'
Junio C Hamano [Fri, 17 Jul 2026 06:05:48 +0000 (23:05 -0700)]
Merge branch 'mm/sideband-ansi-sgr-colon-fix'

The sideband demultiplexer has been updated to recognize ANSI SGR
escape sequences that use colon-separated subfields (e.g., for
256-color or true-color codes).

* mm/sideband-ansi-sgr-colon-fix:
  sideband: allow ANSI SGR with colon-separated subfields

2 weeks agoMerge branch 'jk/git-hash-cleanups'
Junio C Hamano [Fri, 17 Jul 2026 06:05:48 +0000 (23:05 -0700)]
Merge branch 'jk/git-hash-cleanups'

The 'git_hash_*()' wrappers have been updated to be used consistently
across the codebase instead of direct calls to members of 'struct
git_hash_algo', and 'git_hash_discard()' has been made idempotent to
simplify cleanups.

* jk/git-hash-cleanups:
  hash: check ctx->active flag in all wrapper functions
  http: use idempotent git_hash_discard()
  csum-file: use idempotent git_hash_discard()
  hash: make git_hash_discard() idempotent
  hash: document function pointers and wrappers
  hash: convert remaining direct function calls
  hash: use git_hash_init() consistently

2 weeks agoMerge branch 'ih/precompose-flex-array'
Junio C Hamano [Fri, 17 Jul 2026 06:05:47 +0000 (23:05 -0700)]
Merge branch 'ih/precompose-flex-array'

The UTF-8 precomposition wrapper on macOS has been updated to use a
flexible array member to represent the name of a directory entry,
preventing fortified libc checks from failing when the name is
reallocated to be larger than 'NAME_MAX' bytes.

* ih/precompose-flex-array:
  precompose_utf8: use a flex array for d_name

2 weeks agoMerge branch 'ps/t-fixes-for-git-test-long'
Junio C Hamano [Fri, 17 Jul 2026 06:05:47 +0000 (23:05 -0700)]
Merge branch 'ps/t-fixes-for-git-test-long'

Various test scripts have been updated to clean up large temporary
files and repositories, reducing peak disk usage during testing.
Also, expensive tests have been disabled on platforms that lack
sufficient resources (like 32-bit platforms and Windows CI runners),
and the long test suite has been enabled in GitLab CI.

* ps/t-fixes-for-git-test-long:
  gitlab-ci: enable "GIT_TEST_LONG"
  gitlab-ci: disable RAM disk on macOS jobs
  t: use `test_bool_env` to parse GIT_TEST_LONG
  t7900: clean up large EXPENSIVE repository
  t7508: skip EXPENSIVE test that is broken without SIZE_T_IS_64BIT
  t5608: reduce maximum disk usage
  t4141: fix inefficient use of dd(1)
  t0021: skip EXPENSIVE test that is broken without SIZE_T_IS_64BIT
  README: add GitLab CI badge to make it more discoverable

2 weeks agoMerge branch 'js/ci-dockerized-pid-limit'
Junio C Hamano [Fri, 17 Jul 2026 06:05:47 +0000 (23:05 -0700)]
Merge branch 'js/ci-dockerized-pid-limit'

Dockerized CI jobs running in private GitHub repositories have been
adjusted to use explicit process and file limits, preventing resource
exhaustion errors on private runners.

* js/ci-dockerized-pid-limit:
  ci(dockerized): raise the PID limit for private repositories

2 weeks agoMerge branch 'js/coverity-fixes'
Junio C Hamano [Fri, 17 Jul 2026 06:05:47 +0000 (23:05 -0700)]
Merge branch 'js/coverity-fixes'

Various resource leaks, invalid file descriptor closures, and process
handle ownership issues flagged by Coverity have been fixed.

* js/coverity-fixes:
  mingw: make `exit_process()` own the process handle on all paths
  fsmonitor: plug token-data leak on early daemon-startup failures
  reftable/table: release filter on error path
  imap-send: avoid leaking the IMAP upload buffer
  worktree: fix resource leaks when branch creation fails
  submodule: fix cwd leak in `get_superproject_working_tree()`
  dir: free allocations on parse-error paths in `read_one_dir()`
  line-log: avoid redundant copy that leaks in process_ranges
  run-command: avoid `close(-1)` in `start_command()` error paths
  download_https_uri_to_file(): do not leak fd upon failure
  loose: avoid closing invalid fd on error path
  load_one_loose_object_map(): fix resource leak

2 weeks agoMerge branch 'jk/hash-algo-leak-fixes'
Junio C Hamano [Fri, 17 Jul 2026 06:05:46 +0000 (23:05 -0700)]
Merge branch 'jk/hash-algo-leak-fixes'

Various code paths that initialize a cryptographic hash context but
bail out or finish without calling 'git_hash_final()' have been taught
to call 'git_hash_discard()' to release allocated resources, fixing
memory leaks when Git is built with non-default backends like
'OpenSSL' or 'libgcrypt'.

* jk/hash-algo-leak-fixes:
  hash: add platform-specific discard functions
  hash: fix memory leak copying sha256 gcrypt handles
  http: discard hash in dumb-http http_object_request
  check_stream_oid(): discard hash on read error
  patch-id: discard hash when done
  csum-file: provide a function to release checkpoints
  csum-file: always finalize or discard hash
  hash: add discard primitive
  csum-file: drop discard_hashfile()

2 weeks agoMerge branch 'js/wincred-fixes'
Junio C Hamano [Fri, 17 Jul 2026 06:05:46 +0000 (23:05 -0700)]
Merge branch 'js/wincred-fixes'

The wincred credential helper has been updated to avoid memory
corruption when erasing credentials and to prevent silent
credential loss when storing OAuth tokens, by correcting buffer
allocations and arguments passed to safe-CRT APIs.

* js/wincred-fixes:
  wincred: prevent silent credential loss when storing OAuth tokens
  wincred: avoid memory corruption when erasing a credential

2 weeks agowincred: prevent silent credential loss when storing OAuth tokens
Johannes Schindelin [Thu, 16 Jul 2026 14:27:51 +0000 (14:27 +0000)]
wincred: prevent silent credential loss when storing OAuth tokens

When `git credential approve` hands the wincred helper a password
together with an `oauth_refresh_token`, the OAuth branch of
`store_credential()` writes one WCHAR past the allocation while
formatting both fields into a single `CredentialBlob`. On Windows
this trips heap verification and tears the helper down with status
`0xC0000374`; `approve` masks the failure, so the credential the
user meant to save never reaches `CredWriteW()` and the next
session prompts for it again.

The bug has the same shape as the one fixed in the previous commit:
the allocation leaves no room for the terminating NUL, and the
`sizeOfBuffer` argument to `_snwprintf_s()` is a byte count where
the API expects a WCHAR count, which lets the safe-CRT runtime
write the terminator out of bounds.

Apply the same remedy d22a488482 (wincred: avoid memory corruption,
2025-11-17) applied in `get_credential()`: allocate `(wlen + 1) *
sizeof(WCHAR)` bytes and pass `wlen + 1` as the destination
capacity in WCHARs.

This closes the second of the two heap writes tracked under
GHSA-rxqw-wxqg-g7hw.

Assisted-by: Opus 4.7
Signed-off-by: Johannes Schindelin <redacted>
Signed-off-by: Junio C Hamano <redacted>
2 weeks agowincred: avoid memory corruption when erasing a credential
Johannes Schindelin [Thu, 16 Jul 2026 14:27:50 +0000 (14:27 +0000)]
wincred: avoid memory corruption when erasing a credential

The earlier d22a488482 (wincred: avoid memory corruption, 2025-11-17)
repaired only get_credential(); match_cred_password() has the same
defect and is reached on `git credential reject`. When Git asks the
helper to erase a stored credential whose password was supplied by
the caller, the helper copies the candidate's password into a freshly
allocated buffer for comparison. That copy overruns the allocation
by one WCHAR of NUL, which on uninstrumented Windows manifests as
process termination with status 0xC0000374. Because the helper can
die before reaching CredDeleteW(), `git credential reject` masks the
failure and the rejected credential remains stored.

CredentialBlobSize is documented as a byte count, so for an N-WCHAR
blob it equals N * sizeof(WCHAR). The pre-fix code allocated that
many bytes and asked wcsncpy_s to copy N wide characters, but
wcsncpy_s always appends a terminating NUL WCHAR, writing one WCHAR
past the allocation. The destination-capacity argument was also
passed in bytes rather than in WCHAR elements as the API requires,
so the safe-CRT runtime never rejected the copy.

See GHSA-rxqw-wxqg-g7hw.

Assisted-by: Opus 4.7
Signed-off-by: Johannes Schindelin <redacted>
Signed-off-by: Junio C Hamano <redacted>
2 weeks agoMerge branch 'master' of https://github.com/j6t/git-gui
Junio C Hamano [Thu, 16 Jul 2026 17:48:52 +0000 (10:48 -0700)]
Merge branch 'master' of https://github.com/j6t/git-gui

* 'master' of https://github.com/j6t/git-gui:
  git-gui: allow larger width for the commit message field
  git-gui: reduce complexity of the quiet msgfmt rule
  git-gui: drop msgfmt --statistics output
  git-gui i18n: Update Bulgarian translation (562t)

2 weeks agoMerge branch 'master' of https://github.com/j6t/gitk
Junio C Hamano [Thu, 16 Jul 2026 17:47:40 +0000 (10:47 -0700)]
Merge branch 'master' of https://github.com/j6t/gitk

* 'master' of https://github.com/j6t/gitk:
  gitk: make "make -s" silent
  gitk i18n: Update Bulgarian translation (329t)
  gitk: spanish translations

2 weeks agoMerge branch 'master' of github.com:alshopov/git-gui
Johannes Sixt [Thu, 16 Jul 2026 09:05:03 +0000 (11:05 +0200)]
Merge branch 'master' of github.com:alshopov/git-gui

* 'master' of github.com:alshopov/git-gui:
  git-gui: allow larger width for the commit message field

Signed-off-by: Johannes Sixt <redacted>
2 weeks agoMerge branch 'hn/silence-make-s'
Johannes Sixt [Thu, 16 Jul 2026 09:02:20 +0000 (11:02 +0200)]
Merge branch 'hn/silence-make-s'

* hn/silence-make-s:
  git-gui: reduce complexity of the quiet msgfmt rule
  git-gui: drop msgfmt --statistics output

2 weeks agoMerge branch 'spanish_pr_bis' of github.com:basuradeluis/gitkbis
Johannes Sixt [Thu, 16 Jul 2026 08:53:01 +0000 (10:53 +0200)]
Merge branch 'spanish_pr_bis' of github.com:basuradeluis/gitkbis

* 'spanish_pr_bis' of github.com:basuradeluis/gitkbis:
  gitk: spanish translations

Signed-off-by: Johannes Sixt <redacted>
2 weeks agoThe 3rd batch for Git 2.56
Junio C Hamano [Wed, 15 Jul 2026 20:24:06 +0000 (13:24 -0700)]
The 3rd batch for Git 2.56

Signed-off-by: Junio C Hamano <redacted>
2 weeks agoMerge branch 'rs/blame-abbrev-marks'
Junio C Hamano [Wed, 15 Jul 2026 20:24:19 +0000 (13:24 -0700)]
Merge branch 'rs/blame-abbrev-marks'

The alignment of commit object name abbreviations in 'git blame'
output has been optimized to reserve a column for marks (caret,
question mark, or asterisk) only when such marks are actually shown.

* rs/blame-abbrev-marks:
  blame: reserve mark column only if necessary

2 weeks agoMerge branch 'mg/meson-hook-list-buildfix'
Junio C Hamano [Wed, 15 Jul 2026 20:24:19 +0000 (13:24 -0700)]
Merge branch 'mg/meson-hook-list-buildfix'

A racy build failure under Meson has been corrected by ensuring that
the generated header file 'hook-list.h' is built before compiling
files in 'builtin_sources' that depend on it.

* mg/meson-hook-list-buildfix:
  meson: restore hook-list.h to builtin_sources

2 weeks agoMerge branch 'jk/bloom-leak-fixes'
Junio C Hamano [Wed, 15 Jul 2026 20:24:19 +0000 (13:24 -0700)]
Merge branch 'jk/bloom-leak-fixes'

Various memory leaks in the Bloom-filter code paths that are exposed
when running tests with the 'GIT_TEST_COMMIT_GRAPH_CHANGED_PATHS=1'
environment variable have been plugged.

* jk/bloom-leak-fixes:
  line-log: drop extra copy of range with bloom filters
  revision: avoid leaking bloom keyvecs with multiple traversals
  bloom: make bloom-filter slab initialization idempotent

2 weeks agoMerge branch 'ps/history-drop'
Junio C Hamano [Wed, 15 Jul 2026 20:24:18 +0000 (13:24 -0700)]
Merge branch 'ps/history-drop'

The experimental 'git history' command has been taught a new 'drop'
subcommand to remove a commit, with its descendants replayed onto its
parent.

* ps/history-drop:
  builtin/history: implement "drop" subcommand
  builtin/history: split handling of ref updates into two phases
  replay: expose `replay_result_queue_update()`
  reset: stop assuming that the caller passes in a clean index
  reset: allow the caller to specify the current HEAD object
  reset: introduce ability to skip updating HEAD
  reset: introduce dry-run mode
  reset: modernize flags passed to `reset_working_tree()`
  reset: rename `reset_head()`
  reset: drop `USE_THE_REPOSITORY_VARIABLE`
  read-cache: split out function to drop unmerged entries to stage 0

2 weeks agoMerge branch 'ps/odb-drop-whence'
Junio C Hamano [Wed, 15 Jul 2026 20:24:18 +0000 (13:24 -0700)]
Merge branch 'ps/odb-drop-whence'

The 'whence' field in 'struct object_info' has been removed.  The
backend-specific object information retrieval has been refactored into
an opt-in 'struct object_info_source' structure.

* ps/odb-drop-whence:
  odb: document object info fields
  odb: drop `whence` field from object info
  treewide: convert users of `whence` to the new source field
  odb: add `source` field to struct object_info_source
  odb: make backend-specific fields optional
  packfile: thread odb_source_packed through packed_object_info()

2 weeks agoMerge branch 'ps/refs-writing-subcommands'
Junio C Hamano [Wed, 15 Jul 2026 20:24:18 +0000 (13:24 -0700)]
Merge branch 'ps/refs-writing-subcommands'

The 'git refs' toolbox has been extended with new 'create', 'delete',
'update', and 'rename' subcommands to create, delete, update, and
rename references, respectively.

* ps/refs-writing-subcommands:
  builtin/refs: add "rename" subcommand
  builtin/refs: add "create" subcommand
  builtin/refs: add "update" subcommand
  builtin/refs: add "delete" subcommand
  builtin/refs: drop `the_repository`

2 weeks agoMerge branch 'jc/history-message-prep-fix'
Junio C Hamano [Wed, 15 Jul 2026 20:24:18 +0000 (13:24 -0700)]
Merge branch 'jc/history-message-prep-fix'

A write file stream resource leak has been fixed as part of a code
cleanup.

* jc/history-message-prep-fix:
  history: streamline message preparation and plug file stream leak

3 weeks agoThe 2nd batch for Git 2.56
Junio C Hamano [Mon, 13 Jul 2026 15:27:08 +0000 (08:27 -0700)]
The 2nd batch for Git 2.56

Signed-off-by: Junio C Hamano <redacted>
3 weeks agoMerge branch 'ps/odb-generalize-prepare'
Junio C Hamano [Mon, 13 Jul 2026 15:27:27 +0000 (08:27 -0700)]
Merge branch 'ps/odb-generalize-prepare'

The 'reprepare()' callback for object database sources has been
generalized into a 'prepare()' callback with an optional flush cache
flag, and a new 'odb_prepare()' wrapper has been introduced to allow
pre-opening object database sources.

* ps/odb-generalize-prepare:
  odb: introduce `odb_prepare()`
  odb/source: generalize `reprepare()` callback

3 weeks agoMerge branch 'kk/prio-queue-get-put-fusion'
Junio C Hamano [Mon, 13 Jul 2026 15:27:27 +0000 (08:27 -0700)]
Merge branch 'kk/prio-queue-get-put-fusion'

The lazy priority queue optimization pattern (deferring actual removal
in 'prio_queue_get()' to allow get+put fusion) has been folded
directly into 'prio_queue' itself, speeding up commit traversal
workflows and simplifying callers.

* kk/prio-queue-get-put-fusion:
  prio-queue: fold lazy_queue into prio_queue for automatic get+put fusion
  prio-queue: rename .nr to .nr_ and add accessor helpers

3 weeks agoMerge branch 'hn/branch-push-slip-advice'
Junio C Hamano [Mon, 13 Jul 2026 15:27:27 +0000 (08:27 -0700)]
Merge branch 'hn/branch-push-slip-advice'

When 'git push origin/main' or 'git branch origin main' is run, the
command is now recognized as a potential typo, and advice has been
added to offer a typo fix.

* hn/branch-push-slip-advice:
  push: suggest <remote> <branch> for a slash slip
  branch: suggest <remote>/<branch> on upstream slip

3 weeks agoMerge branch 'jk/format-patch-leakfix'
Junio C Hamano [Mon, 13 Jul 2026 15:27:26 +0000 (08:27 -0700)]
Merge branch 'jk/format-patch-leakfix'

A memory leak in the '--base' handling of 'git format-patch' has been
plugged, and the leak reporting of the test suite when running under a
TAP harness has been improved.

* jk/format-patch-leakfix:
  format-patch: fix leak of rev_info in prepare_bases()
  t: move LSan errors from stdout to stderr

3 weeks agoMerge branch 'jk/reftable-leakfix'
Junio C Hamano [Mon, 13 Jul 2026 15:27:26 +0000 (08:27 -0700)]
Merge branch 'jk/reftable-leakfix'

A memory leak in the 'reftable_writer_new()' initialization function
has been fixed by delaying the allocation of 'struct reftable_writer'
until after input options are validated.

* jk/reftable-leakfix:
  reftable: fix unlikely leak on API error

3 weeks agoMerge branch 'ad/gpg-strip-cr-before-lf'
Junio C Hamano [Mon, 13 Jul 2026 15:27:26 +0000 (08:27 -0700)]
Merge branch 'ad/gpg-strip-cr-before-lf'

The GPG and SSH signature parsing code has been corrected to strip
carriage return characters only when they immediately precede line
feeds, instead of unconditionally stripping all carriage returns.

* ad/gpg-strip-cr-before-lf:
  gpg-interface: fix strip_cr_before_lf to only remove CR before LF

3 weeks agomailmap: map Taylor Blau's work address
Taylor Blau [Thu, 9 Jul 2026 02:26:20 +0000 (19:26 -0700)]
mailmap: map Taylor Blau's work address

Signed-off-by: Taylor Blau <redacted>
Signed-off-by: Junio C Hamano <redacted>
3 weeks agohash: check ctx->active flag in all wrapper functions
Jeff King [Wed, 8 Jul 2026 03:53:05 +0000 (23:53 -0400)]
hash: check ctx->active flag in all wrapper functions

It only makes sense to call git_hash_update(), etc, on a hash context
that has been initialized but not yet finalized or discarded. This is an
unlikely error to make, but it's easy for us to catch it and complain.

It's especially important because it would quietly "work" for many hash
backends (like sha1dc, which is just manipulating some bytes) but would
cause undefined behavior with others (like OpenSSL, which puts the
context onto the heap). Checking the flag lets us catch problems
consistently on every build.

Note that we can't do the same for git_hash_init(). Even though it would
cause a leak to call it twice (without an intervening final/discard),
the point of the function is that the contents of the struct are
undefined before the call. But calling it twice is an even less likely
error to make, so not covering it is OK.

We leave git_hash_discard() alone, as its idempotent behavior is
convenient for callers. We _could_ try to do something similar for
git_hash_final(), allowing:

  git_hash_final(result, &ctx);
  git_hash_final(other_result, &ctx);

but it does not make much sense. After the first final() call we have
thrown away the state, so we cannot produce the same output. We could
come up with some sensible output (the null hash, or the empty hash),
but double-calls like this are more likely a bug, so our best bet is to
complain loudly (whereas the current code produces either nonsense
output or undefined behavior, depending on the backend).

Signed-off-by: Jeff King <redacted>
Signed-off-by: Junio C Hamano <redacted>
3 weeks agohttp: use idempotent git_hash_discard()
Jeff King [Wed, 8 Jul 2026 03:53:02 +0000 (23:53 -0400)]
http: use idempotent git_hash_discard()

Now that it is OK to call git_hash_discard() even after finalizing the
hash, we no longer need the ctx_valid bool added by a2d8ea5a76 (http:
discard hash in dumb-http http_object_request, 2026-07-02).

Signed-off-by: Jeff King <redacted>
Signed-off-by: Junio C Hamano <redacted>
3 weeks agocsum-file: use idempotent git_hash_discard()
Jeff King [Wed, 8 Jul 2026 03:53:00 +0000 (23:53 -0400)]
csum-file: use idempotent git_hash_discard()

Now that it is safe to call git_hash_discard() even after finalizing it,
we can simplify our cleanup logic a bit. This is mostly undoing a few
bits of 64337aecde (csum-file: always finalize or discard hash,
2026-07-02):

  - We no longer need a separate free_hashfile_memory() function for
    finalize_hashfile(). It can just call free_hashfile(), which will
    now discard (or not) the hash as appropriate.

  - When f->skip_hash is set, we don't need to discard; we can rely on
    free_hashfile() to do it.

Signed-off-by: Jeff King <redacted>
Signed-off-by: Junio C Hamano <redacted>
3 weeks agohash: make git_hash_discard() idempotent
Jeff King [Wed, 8 Jul 2026 03:52:57 +0000 (23:52 -0400)]
hash: make git_hash_discard() idempotent

You must always either finalize or discard a hash context to release any
resources, but you must call only one such function. This creates extra
work for some callers, since their cleanup code paths need to know
whether they got there via their happy path (and the finalization
happened) or due to an error (in which case they need to discard).

Let's add an "active" flag that turns a redundant discard into a noop.
That lets you safely do this:

    git_hash_init(&ctx, algo);
    ...
    if (some_error)
            goto out;
    ...
    git_hash_final(result, &ctx);

  out:
    git_hash_discard(&ctx);

This should avoid future errors, and will also let us simplify a few
existing callers (in future patches).

Signed-off-by: Jeff King <redacted>
Signed-off-by: Junio C Hamano <redacted>
3 weeks agohash: document function pointers and wrappers
Jeff King [Wed, 8 Jul 2026 03:52:55 +0000 (23:52 -0400)]
hash: document function pointers and wrappers

We want people to use the git_hash_*() wrappers rather than the bare
function pointers in the git_hash_algo struct. Let's document them
rather than the bare pointers, and warn people away from the pointers.
Coccinelle will eventually force the use of the wrappers, but it's
helpful to lead readers in the right direction from the start.

While we're here we can document a few other bits of wisdom I've turned
up while working in this area:

  - You have to initialize the destination of a git_hash_clone(). This
    is something we may eventually change for efficiency, but we should
    definitely document the requirement for now.

  - You must eventually finalize or discard a hash, since some backends
    may allocate resources during initialization.

Signed-off-by: Jeff King <redacted>
Signed-off-by: Junio C Hamano <redacted>
3 weeks agohash: convert remaining direct function calls
Jeff King [Wed, 8 Jul 2026 03:52:53 +0000 (23:52 -0400)]
hash: convert remaining direct function calls

The previous patch added a coccinelle rule to make sure callers always
use git_hash_init() rather than direct function pointers from the algo
struct.

Let's do the same for the rest of the git_hash_*() wrappers. I split
these out because they're a bit different: they implicitly use the algop
pointer in the git_hash_ctx. So when we convert:

  -algo->update_fn(&ctx, buf, len);
  +git_hash_update(&ctx, buf, len);

we drop the reference to algo entirely! But this is always going to be
the right thing. If "algo" does not match what is in ctx.algop, then
we'd already be invoking undefined behavior.

So in addition to making it possible to add more logic to the
git_hash_*() functions, we're avoiding the need to pass around the extra
algo pointer and make sure that it matches what's in "ctx".

The rest of the patch is the mechanical application of that coccinelle
patch, plus a minor cleanup in test-synthesize.c to drop a now-unused
function parameter (since we don't have to pass around the algo
separately anymore).

Signed-off-by: Jeff King <redacted>
Signed-off-by: Junio C Hamano <redacted>
3 weeks agohash: use git_hash_init() consistently
Jeff King [Wed, 8 Jul 2026 03:52:49 +0000 (23:52 -0400)]
hash: use git_hash_init() consistently

We'd like to add more logic to git_hash_init(), but many callers skip it
and call algop->init_fn() directly. Let's make sure we're consistently
using the wrapper by adding a coccinelle rule.

Besides the coccinelle file itself, this is a purely mechanical
conversion based on the patch it generates. There should be no bare
init_fn() calls left (except for the one in the wrapper).

Signed-off-by: Jeff King <redacted>
Signed-off-by: Junio C Hamano <redacted>
3 weeks agosideband: allow ANSI SGR with colon-separated subfields
Mantas MikulÄ—nas [Wed, 13 May 2026 07:08:03 +0000 (10:08 +0300)]
sideband: allow ANSI SGR with colon-separated subfields

The SGR values used for 256-color formatting are officially defined to
be a single field with :-separated subfields (e.g. "\e[1;38:5:XX;40m")
despite the more common but kludgy use of separate values (which then
become context-dependent and lead to misinterpretation by incompatible
terminals).

Signed-off-by: Mantas MikulÄ—nas <redacted>
Acked-by: Johannes Schindelin <redacted>
Signed-off-by: Junio C Hamano <redacted>
3 weeks agoMerge branch 'jk/hash-algo-leak-fixes' into jk/git-hash-cleanups
Junio C Hamano [Tue, 7 Jul 2026 17:52:48 +0000 (10:52 -0700)]
Merge branch 'jk/hash-algo-leak-fixes' into jk/git-hash-cleanups

* jk/hash-algo-leak-fixes:
  hash: add platform-specific discard functions
  hash: fix memory leak copying sha256 gcrypt handles
  http: discard hash in dumb-http http_object_request
  check_stream_oid(): discard hash on read error
  patch-id: discard hash when done
  csum-file: provide a function to release checkpoints
  csum-file: always finalize or discard hash
  hash: add discard primitive
  csum-file: drop discard_hashfile()

4 weeks agoStart Git 2.56 cycle
Junio C Hamano [Mon, 6 Jul 2026 22:49:17 +0000 (15:49 -0700)]
Start Git 2.56 cycle

This time, do not forget to update GIT-VERSION-GEN to say 2.55.GIT

Signed-off-by: Junio C Hamano <redacted>
4 weeks agoMerge branch 'sg/t3420-do-not-grep-in-missing-file'
Junio C Hamano [Mon, 6 Jul 2026 22:50:25 +0000 (15:50 -0700)]
Merge branch 'sg/t3420-do-not-grep-in-missing-file'

A test checking interactions between git rebase --quit and
autostash in t3420-rebase-autostash.sh has been corrected to use
test_path_is_missing instead of ! grep on a file that shouldn't
exist in the conflicted state.

* sg/t3420-do-not-grep-in-missing-file:
  t3420-rebase-autostash: don't try to grep non-existing files

4 weeks agoMerge branch 'ps/connected-generic-promisor-checks'
Junio C Hamano [Mon, 6 Jul 2026 22:50:24 +0000 (15:50 -0700)]
Merge branch 'ps/connected-generic-promisor-checks'

The connectivity check has been refactored to search for promisor
objects in a generic way using the object database interface,
rather than iterating packfiles directly. This allows connectivity
checks to work properly in repositories that do not use packfiles.

* ps/connected-generic-promisor-checks:
  connected: search promisor objects generically
  connected: split out promisor-based connectivity check
  odb/source-packed: support flags when iterating an object prefix
  odb/source-packed: extract logic to skip certain packs

4 weeks agoMerge branch 'ps/refs-onbranch-fixes'
Junio C Hamano [Mon, 6 Jul 2026 22:50:24 +0000 (15:50 -0700)]
Merge branch 'ps/refs-onbranch-fixes'

Reference backend configuration has been updated to load lazily to
avoid recursive calls during repository initialization when 'onbranch'
configuration conditions are evaluated. This has also fixed a memory
leak and allowed the unused `chdir_notify_reparent()` machinery to be
dropped.

* ps/refs-onbranch-fixes:
  refs: protect against chicken-and-egg recursion
  refs/reftable: lazy-load configuration to fix chicken-and-egg
  reftable: split up write options
  refs/files: lazy-load configuration to fix chicken-and-egg
  refs: move parsing of "core.logAllRefUpdates" back into ref stores
  repository: free main reference database
  chdir-notify: drop unused `chdir_notify_reparent()`
  refs: unregister reference stores from "chdir_notify"
  setup: don't apply "GIT_REFERENCE_BACKEND" without a repository
  setup: stop applying repository format twice
  setup: inline `check_and_apply_repository_format()`

4 weeks agoMerge branch 'wy/doc-clarify-review-replies'
Junio C Hamano [Mon, 6 Jul 2026 22:50:23 +0000 (15:50 -0700)]
Merge branch 'wy/doc-clarify-review-replies'

Documentation on community contribution guidelines has been updated to
encourage replying to review comments before rerolling, and to advise
a default limit of at most one reroll per day to give reviewers across
different time zones enough time to participate.

* wy/doc-clarify-review-replies:
  doc: advise batching patch rerolls
  doc: encourage review replies before rerolling

4 weeks agoMerge branch 'jk/repo-info-path-keys'
Junio C Hamano [Mon, 6 Jul 2026 22:50:23 +0000 (15:50 -0700)]
Merge branch 'jk/repo-info-path-keys'

The "git repo info" command has been taught new keys to output both
absolute and relative paths for "gitdir" and "commondir", supported by
a new path-formatting helper extracted from "git rev-parse".

* jk/repo-info-path-keys:
  repo: add path.gitdir with absolute and relative suffix formatting
  repo: add path.commondir with absolute and relative suffix formatting
  path: extract format_path() and use in rev-parse

4 weeks agoMerge branch 'mv/log-follow-mergy'
Junio C Hamano [Mon, 6 Jul 2026 22:50:23 +0000 (15:50 -0700)]
Merge branch 'mv/log-follow-mergy'

"git log --follow" has been updated to better handle non-linear
history, in which the path being tracked gets renamed differently in
multiple history lines.

* mv/log-follow-mergy:
  log: improve --follow following renames for non-linear history

4 weeks agoMerge branch 'pw/status-rebase-todo'
Junio C Hamano [Mon, 6 Jul 2026 22:50:23 +0000 (15:50 -0700)]
Merge branch 'pw/status-rebase-todo'

The display of the rebase todo list in "git status" has been
improved to correctly abbreviate object IDs for more commands and
avoid misinterpreting refs as object IDs.

* pw/status-rebase-todo:
  status: improve rebase todo list parsing
  sequencer: factor out parsing of todo commands

4 weeks agoMerge branch 'tb/pack-path-walk-bitmap-delta-islands'
Junio C Hamano [Mon, 6 Jul 2026 22:50:22 +0000 (15:50 -0700)]
Merge branch 'tb/pack-path-walk-bitmap-delta-islands'

The pack-objects command has been updated to support reachability
bitmaps and delta-islands concurrently with the `--path-walk` option,
allowing faster packaging by falling back to path-walk when bitmaps
cannot fully satisfy the request.

* tb/pack-path-walk-bitmap-delta-islands:
  pack-objects: support `--delta-islands` with `--path-walk`
  pack-objects: extract `record_tree_depth()` helper
  pack-objects: support reachability bitmaps with `--path-walk`
  t/perf: drop p5311's lookup-table permutation

4 weeks agoMerge branch 'jc/submittingpatches-design-critiques'
Junio C Hamano [Mon, 6 Jul 2026 22:50:22 +0000 (15:50 -0700)]
Merge branch 'jc/submittingpatches-design-critiques'

The documentation in SubmittingPatches has been updated to clarify how
patch contributors should respond to design and viability critiques,
and how the resolution of such critiques should be recorded in the
final commit messages.

* jc/submittingpatches-design-critiques:
  SubmittingPatches: address design critiques

4 weeks agoMerge branch 'kh/submittingpatches-trailers'
Junio C Hamano [Mon, 6 Jul 2026 22:50:22 +0000 (15:50 -0700)]
Merge branch 'kh/submittingpatches-trailers'

The trailer sections in SubmittingPatches have been updated to
encourage use of standard trailers.

* kh/submittingpatches-trailers:
  SubmittingPatches: note that trailer order matters
  SubmittingPatches: be consistent with trailer markup
  SubmittingPatches: document Based-on-patch-by trailer
  SubmittingPatches: discourage common Linux trailers
  SubmittingPatches: encourage trailer use for substantial help

4 weeks agoMerge branch 'mh/fetch-follow-remote-head-config'
Junio C Hamano [Mon, 6 Jul 2026 22:50:22 +0000 (15:50 -0700)]
Merge branch 'mh/fetch-follow-remote-head-config'

The `fetch.followRemoteHEAD` configuration variable has been added to
provide a default for the per-remote `remote.<name>.followRemoteHEAD`
setting.

* mh/fetch-follow-remote-head-config:
  fetch: fixup a misaligned comment
  fetch: add configuration variable fetch.followRemoteHEAD
  fetch: refactor do_fetch handling of followRemoteHEAD
  fetch: return 0 on known git_fetch_config
  fetch: rename function report_set_head
  t5510: cleanup remote in followRemoteHEAD dangling ref test
  doc: explain fetchRemoteHEADWarn advice
  fetch: fixup set_head advice for warn-if-not-branch

4 weeks agoMerge branch 'po/hash-object-size-t'
Junio C Hamano [Mon, 6 Jul 2026 22:50:21 +0000 (15:50 -0700)]
Merge branch 'po/hash-object-size-t'

Support for hashing loose or packed objects larger than 4GB on Windows
and other LLP64 platforms has been improved by converting object header
buffers and data-handling functions from 'unsigned long' to 'size_t'.

* po/hash-object-size-t:
  hash-object: add a >4GB/LLP64 test case using filtered input
  hash-object: add another >4GB/LLP64 test case
  hash-object --stdin: verify that it works with >4GB/LLP64
  hash algorithms: use size_t for section lengths
  object-file.c: use size_t for header lengths
  hash-object: demonstrate a >4GB/LLP64 problem

4 weeks agoMerge branch 'ty/move-protect-hfs-ntfs'
Junio C Hamano [Mon, 6 Jul 2026 22:50:21 +0000 (15:50 -0700)]
Merge branch 'ty/move-protect-hfs-ntfs'

The global configuration variables protect_hfs and protect_ntfs have
been migrated into struct repo_config_values to tie them to
per-repository configuration state.

* ty/move-protect-hfs-ntfs:
  environment: use 'repo->initialized' for repo_protect_hfs() and repo_protect_ntfs()
  environment: move 'protect_hfs' and 'protect_ntfs' into 'repo_config_values'

4 weeks agoMerge branch 'ps/odb-source-packed'
Junio C Hamano [Mon, 6 Jul 2026 22:50:21 +0000 (15:50 -0700)]
Merge branch 'ps/odb-source-packed'

The packed object source has been refactored into a proper struct
odb_source.

* ps/odb-source-packed:
  odb/source-packed: drop pointer to "files" parent source
  midx: refactor interfaces to work on "packed" source
  odb/source-packed: stub out remaining functions
  odb/source-packed: wire up `freshen_object()` callback
  odb/source-packed: wire up `find_abbrev_len()` callback
  odb/source-packed: wire up `count_objects()` callback
  odb/source-packed: wire up `for_each_object()` callback
  odb/source-packed: wire up `read_object_stream()` callback
  odb/source-packed: wire up `read_object_info()` callback
  packfile: use higher-level interface to implement `has_object_pack()`
  odb/source-packed: wire up `reprepare()` callback
  odb/source-packed: wire up `close()` callback
  odb/source-packed: start converting to a proper `struct odb_source`
  odb/source-packed: store pointer to "files" instead of generic source
  packfile: move packed source into "odb/" subsystem
  packfile: split out packfile list logic
  packfile: rename `struct packfile_store` to `odb_source_packed`

4 weeks agoMerge branch 'td/ref-filter-restore-prefix-iteration'
Junio C Hamano [Mon, 6 Jul 2026 22:50:20 +0000 (15:50 -0700)]
Merge branch 'td/ref-filter-restore-prefix-iteration'

Commands that list branches and tags (like git branch and git tag)
have been optimized to pass the namespace prefix when initializing
their ref iterator, avoiding a loose-ref scaling regression in
repositories with many unrelated loose references.

* td/ref-filter-restore-prefix-iteration:
  ref-filter: restore prefix-scoped iteration

4 weeks agoMerge branch 'en/ort-harden-against-corrupt-trees'
Junio C Hamano [Mon, 6 Jul 2026 22:50:20 +0000 (15:50 -0700)]
Merge branch 'en/ort-harden-against-corrupt-trees'

The 'ort' merge backend has been hardened against corrupt trees by
ensuring it aborts under appropriate error conditions.

* en/ort-harden-against-corrupt-trees:
  cache-tree: fix verify_cache() to catch non-adjacent D/F conflicts
  merge-ort: abort merge when trees have duplicate entries
  merge-ort: free diff pairs queue in clear_or_reinit_internal_opts()
  merge-ort: drop unnecessary show_all_errors from collect_merge_info()
  merge-ort: propagate callback errors from traverse_trees_wrapper()

4 weeks agoMerge branch 'jk/setup-gitfile-diag-fix'
Junio C Hamano [Mon, 6 Jul 2026 22:50:20 +0000 (15:50 -0700)]
Merge branch 'jk/setup-gitfile-diag-fix'

A regression in the error diagnosis code for invalid .git files has
been fixed, avoiding a potential NULL-pointer crash when reporting
that a .git file does not point to a valid repository.

* jk/setup-gitfile-diag-fix:
  read_gitfile(): simplify NOT_A_REPO error message

4 weeks agoMerge branch 'rs/cat-file-default-format-optim'
Junio C Hamano [Mon, 6 Jul 2026 22:50:20 +0000 (15:50 -0700)]
Merge branch 'rs/cat-file-default-format-optim'

The default format path of git cat-file --batch has been optimized
to use strbuf_add_oid_hex() and strbuf_add_uint() instead of
strbuf_addf(), yielding a noticeable speedup.

* rs/cat-file-default-format-optim:
  cat-file: speed up default format

4 weeks agoMerge branch 'ps/doc-recommend-b4'
Junio C Hamano [Mon, 6 Jul 2026 22:50:19 +0000 (15:50 -0700)]
Merge branch 'ps/doc-recommend-b4'

Project-specific configuration for b4 has been introduced, and the
documentation has been updated to recommend using it as a
streamlined method for submitting patches.

* ps/doc-recommend-b4:
  b4: introduce configuration for the Git project
  MyFirstContribution: recommend the use of b4
  MyFirstContribution: recommend shallow threading of cover letters

4 weeks agoMerge branch 'ps/setup-drop-global-state'
Junio C Hamano [Mon, 6 Jul 2026 22:50:19 +0000 (15:50 -0700)]
Merge branch 'ps/setup-drop-global-state'

The refactoring of 'setup.c' has been continued to drop remaining
global state (`git_work_tree_cfg`, `is_bare_repository_cfg`), updating
`is_bare_repository()` to no longer implicitly rely on
`the_repository`.

* ps/setup-drop-global-state:
  treewide: drop USE_THE_REPOSITORY_VARIABLE
  environment: stop using `the_repository` in `is_bare_repository()`
  environment: split up concerns of `is_bare_repository_cfg`
  builtin/init: stop modifying `is_bare_repository_cfg`
  setup: remove global `git_work_tree_cfg` variable
  builtin/init: simplify logic to configure worktree
  builtin/init: stop modifying global `git_work_tree_cfg` variable

4 weeks agoMerge branch 'cc/promisor-auto-config-url-more'
Junio C Hamano [Mon, 6 Jul 2026 22:50:19 +0000 (15:50 -0700)]
Merge branch 'cc/promisor-auto-config-url-more'

The handling of promisor-remote protocol capability has been updated
to allow the other side to add to the list of promisor remotes via the
'promisor.acceptFromServerURL' configuration variable.

* cc/promisor-auto-config-url-more:
  doc: promisor: improve acceptFromServer entry
  promisor-remote: auto-configure unknown remotes
  promisor-remote: trust known remotes matching acceptFromServerUrl
  promisor-remote: introduce promisor.acceptFromServerUrl
  promisor-remote: add 'local_name' to 'struct promisor_info'
  urlmatch: add url_normalize_pattern() helper
  urlmatch: change 'allow_globs' arg to bool
  t5710: simplify 'mkdir X' followed by 'git -C X init'

4 weeks agoMerge branch 'hn/status-pull-advice-qualified'
Junio C Hamano [Mon, 6 Jul 2026 22:50:18 +0000 (15:50 -0700)]
Merge branch 'hn/status-pull-advice-qualified'

Advice shown by "git status" when the local branch is behind or has
diverged from its push branch has been updated to suggest "git pull
<remote> <branch>".

* hn/status-pull-advice-qualified:
  remote: qualify "git pull" advice for non-upstream compareBranches

4 weeks agobuiltin/refs: add "rename" subcommand
Patrick Steinhardt [Mon, 6 Jul 2026 13:27:08 +0000 (15:27 +0200)]
builtin/refs: add "rename" subcommand

Add a "rename" subcommand to git-refs(1) with the syntax:

  $ git refs rename <oldref> <newref>

It renames <oldref> together with its reflog to <newref>; even when used
on a local branch ref, the current value and the reflog of the ref are
the only things that are renamed. Document it and redirect casual users
to "git branch -m" if that is what they wanted to do.

Co-authored-by: Junio C Hamano <redacted>
Signed-off-by: Patrick Steinhardt <redacted>
Signed-off-by: Junio C Hamano <redacted>
4 weeks agobuiltin/refs: add "create" subcommand
Patrick Steinhardt [Mon, 6 Jul 2026 13:27:07 +0000 (15:27 +0200)]
builtin/refs: add "create" subcommand

The "update" subcommand cannot only update an existing reference, but it
can also create new branches and delete existing branches by specifying
the all-zeroes object ID as either old or new value. Despite that, we
already have the "delete" subcommand as a handy shortcut so that a user
can easily delete a branch. This relieves them of needing to understand
the more arcane uses of the "update" command, and of counting the number
of zeroes they need to pass.

But while we have a "delete" subcommand, we don't have an equivalent
that would allow the user to create a new branch, which creates a
certain asymmetry.

Add a new "create" subcommand to plug this gap.

Signed-off-by: Patrick Steinhardt <redacted>
Signed-off-by: Junio C Hamano <redacted>
4 weeks agobuiltin/refs: add "update" subcommand
Patrick Steinhardt [Mon, 6 Jul 2026 13:27:06 +0000 (15:27 +0200)]
builtin/refs: add "update" subcommand

Add a new "update" subcommand which mirrors `git update-ref <refname>
<oldoid> <newoid>`. This follows the same reasoning as the preceding
commit.

Signed-off-by: Patrick Steinhardt <redacted>
Signed-off-by: Junio C Hamano <redacted>
4 weeks agobuiltin/refs: add "delete" subcommand
Patrick Steinhardt [Mon, 6 Jul 2026 13:27:05 +0000 (15:27 +0200)]
builtin/refs: add "delete" subcommand

Reference-related functionality in Git is currently spread across many
different commands: git-update-ref(1), git-for-each-ref(1),
git-show-ref(1), git-pack-refs(1) and git-symbolic-ref(1). This makes it
hard for users to discover what functionality we have available to work
with references.

We have thus started to consolidate this functionality into git-refs(1),
which is a toolbox of everything related to references. Until now, the
command doesn't handle functionality of git-update-ref(1).

Fix this gap by introducing a new "delete" subcommand, which is the
equivalent of `git update-ref -d`.

Note that we're intentionally not using a generic "write" subcommand
with a "-d" flag. This is rather harder to discover, and subcommands
that are implmented as flags tend to be hard to reason about in the code
as we'd have to handle mutually-exclusive flags that stem from the other
subcommand-like modes.

Signed-off-by: Patrick Steinhardt <redacted>
Signed-off-by: Junio C Hamano <redacted>
4 weeks agobuiltin/refs: drop `the_repository`
Patrick Steinhardt [Mon, 6 Jul 2026 13:27:04 +0000 (15:27 +0200)]
builtin/refs: drop `the_repository`

We still have a couple of uses of `the_repository` in "builtin/refs.c".
All of those are trivial to convert though as the command always
requires a repository to exist.

Convert them to use the passed-in repository and drop
`USE_THE_REPOSITORY_VARIABLE`.

Signed-off-by: Patrick Steinhardt <redacted>
Signed-off-by: Junio C Hamano <redacted>
4 weeks agoblame: reserve mark column only if necessary
René Scharfe [Mon, 6 Jul 2026 08:38:25 +0000 (10:38 +0200)]
blame: reserve mark column only if necessary

git blame prepends commit hashes of boundary commits with "^", ignored
commits with "?" and unblamable commits with "*" and reserves one column
for them by extending the hash abbreviation, to avoid showing ambiguous
hashes.

This reserved column wastes precious screen space, which can be
especially irritating when using the option -b to blank out boundary
commit hashes and not ignoring any commits.  Reserve it only as needed,
i.e. if any of those cases are actually shown.

Pointed-out-by: Laszlo Ersek <redacted>
Signed-off-by: René Scharfe <redacted>
Signed-off-by: Junio C Hamano <redacted>
4 weeks agogitlab-ci: enable "GIT_TEST_LONG"
Patrick Steinhardt [Mon, 6 Jul 2026 06:24:04 +0000 (08:24 +0200)]
gitlab-ci: enable "GIT_TEST_LONG"

Starting with 7a094d68a2 (ci: run expensive tests on push builds to
integration branches, 2026-05-08) we run expensive tests in our CI for
certain events. So far, this has only been wired up for GitHub Workflows
though, which creates a test gap for GitLab CI.

Plug this gap by also making this work for the latter.

Note that these tests cannot be run on the Windows runners, as they only
have 7.5GB of RAM. This is insufficient for some of the EXPENSIVE tests,
so we explicitly disable "GIT_TEST_LONG" on these jobs.

Signed-off-by: Patrick Steinhardt <redacted>
Signed-off-by: Junio C Hamano <redacted>
4 weeks agogitlab-ci: disable RAM disk on macOS jobs
Patrick Steinhardt [Mon, 6 Jul 2026 06:24:03 +0000 (08:24 +0200)]
gitlab-ci: disable RAM disk on macOS jobs

When we added the macOS jobs to GitLab CI in 56090a35ab (ci: add macOS
jobs to GitLab CI, 2024-01-18) we had to work around some very slow
disks. This workaround essentially creates a RAM disk that we mount,
where all test data is being written into RAM instead of the real disk.

In the next commit though we're about to enable "GIT_TEST_LONG", which
will make tests run that are marked with the "EXPENSIVE" prerequisite.
This change will make a couple of tests run that write up to 8GB of data
into the test output directory. As our RAM disk is only 4GB in size,
this change will cause ENOSPC errors.

We could accommodate for this by increasing the size of the RAM disk.
In c9d708b7fc (gitlab-ci: upgrade macOS runners, 2026-05-21) we have
upgraded our runners to use the "large" runners, which have 16GB of RAM
available. So we could easily expand the RAM disk to a capacity of for
example 12GB. But some test runs have shown that this is still quite
flaky overall, as we get quite close to our limits.

Instead, drop the workaround completely. This does indeed slow down
execution of the test jobs:

  - osx-clang goes from 18 minutes to 25 minutes

  - osx-meson goes from 21 minutes to 33 minutes

  - osx-reftable stays at 21 minutes

The last one seems like an outlier. The only explanation that I have is
that we end up writing significantly less files with the reftable
backend, which ultimately causes less I/O.

Overall though, it's preferable to have something that works with the
least amount of flakiness compared to having something else that is
faster but unstable. Despite that, the macOS jobs aren't even the
slowest jobs, so this doesn't extend the overall pipeline's length.

Signed-off-by: Patrick Steinhardt <redacted>
Signed-off-by: Junio C Hamano <redacted>
4 weeks agot: use `test_bool_env` to parse GIT_TEST_LONG
Patrick Steinhardt [Mon, 6 Jul 2026 06:24:02 +0000 (08:24 +0200)]
t: use `test_bool_env` to parse GIT_TEST_LONG

It's currently hard to explicitly disable GIT_TEST_LONG by setting it to
`false`. Fix this by using `test_bool_env` instead.

Signed-off-by: Patrick Steinhardt <redacted>
Signed-off-by: Junio C Hamano <redacted>
4 weeks agot7900: clean up large EXPENSIVE repository
Patrick Steinhardt [Mon, 6 Jul 2026 06:24:01 +0000 (08:24 +0200)]
t7900: clean up large EXPENSIVE repository

One of the tests in t7900 is marked with EXPENSIVE because we create a
repository with 2GB of data that we end up repacking. We never clean up
that repository though, so we occupy the full 2GB of data until the end
of the test suite.

Besides clogging our disk, having an EXPENSIVE test that alters the
repository's state used by subsequent tests is also a bad idea, as it
can easily have an impact on the heuristics used by other maintenance
tasks.

Adapt the test so that we create the data in a standalone repository
that we clean up at the end of the test. While at it, also disable
auto-maintenance so that it does not race with our manual maintenance.

Signed-off-by: Patrick Steinhardt <redacted>
Signed-off-by: Junio C Hamano <redacted>
4 weeks agot7508: skip EXPENSIVE test that is broken without SIZE_T_IS_64BIT
Patrick Steinhardt [Mon, 6 Jul 2026 06:24:00 +0000 (08:24 +0200)]
t7508: skip EXPENSIVE test that is broken without SIZE_T_IS_64BIT

One of the tests in t7508 is marked as EXPENSIVE because it ends up
creating and adding files that are multiple gigabytes in size. This
takes a while to complete, hence the EXPENSIVE prerequisite.

Besides being expensive though the test can only work on systems where
`size_t` is at least 64 bit. This is because one of the created files
is larger than 4GB, and because Git tracks object size via `size_t` it
will eventually blow up.

This test has also been blowing up in the "linux32" CI job in GitHub
Workflows since 7a094d68a2 (ci: run expensive tests on push builds to
integration branches, 2026-05-08). But that job doesn't only fail, it
also hangs, and that has been concealing the failure.

Fix the issue by marking the test as requiring 64 bit `size_t`.

Signed-off-by: Patrick Steinhardt <redacted>
Signed-off-by: Junio C Hamano <redacted>
4 weeks agot5608: reduce maximum disk usage
Patrick Steinhardt [Mon, 6 Jul 2026 06:23:59 +0000 (08:23 +0200)]
t5608: reduce maximum disk usage

The tests in t5608 perform a couple of clones of repositories that are
somewhat large. Ultimately, we end up creating:

  - A setup repository that contains 2GB of uncompressed pack data.

  - A bare clone that contains the same 2GB of data.

  - A clone with worktree writes a 2GB packfile and a 2GB worktree.

  - A second setup repository that contains a 4GB packfile.

  - Two 4GB clone of that repository.

Some of these clones ultimately hardlink files, which ensures that we at
least don't end up with more than 20GB of data. But at the end of the
test we still have around 16GB of data, which is only a tiny bit better.

Refactor the test to prune repositories after they have no use anymore.
This reduced the peak disk usage of this test to 8GB.

Signed-off-by: Patrick Steinhardt <redacted>
Signed-off-by: Junio C Hamano <redacted>
4 weeks agot4141: fix inefficient use of dd(1)
Patrick Steinhardt [Mon, 6 Jul 2026 06:23:58 +0000 (08:23 +0200)]
t4141: fix inefficient use of dd(1)

In t4141 we generate a patch that is roughly 1GB in size to verify that
git-apply(1) indeed rejects that patch. We generate that patch by
prepending a patch header and then executing `test-tool genzeros`
without a limit. This causes us to print infinitely many zeros, and we
limit the overall amount of generated bytes via `test_copy_bytes`.

This test setup is extremely expensive, as `test_copy_bytes` is
implemented via `dd ibs=1 count="$1"`, which copies data one byte at a
time. So as we write 1GB of data, we end up doing 1 billion reads and
writes. This naturally takes a while: it takes 6 minutes on my system,
and around 40 minutes in some CI jobs!

We can do much better though, as genzeros already knows to handle an
optional limit of how much data it is supposed to write, which allows us
to remove the call to `test_copy_bytes`. Furthermore, it has already
been optimized to generate the data fast.

And indeed, doing this conversion drops the test execution to less than
a second on my machine. That means that in theory it becomes feasible to
drop the EXPENSIVE prerequisite now. But git-apply(1) still soaks up 1GB
of data into memory, which may count as being expensive. Consequently,
we keep the prerequisite intact.

Signed-off-by: Patrick Steinhardt <redacted>
Signed-off-by: Junio C Hamano <redacted>
4 weeks agot0021: skip EXPENSIVE test that is broken without SIZE_T_IS_64BIT
Patrick Steinhardt [Mon, 6 Jul 2026 06:23:57 +0000 (08:23 +0200)]
t0021: skip EXPENSIVE test that is broken without SIZE_T_IS_64BIT

One of the tests in t0021 writes a 2GB file and then roundtrips it
through the clean/sumdge filters. This test is broken on 32 bit
platforms because they typically don't handle files larger then
`SSIZE_MAX` well at all.

While our CI has a "linux32" job that should in theory hit this issue,
we never noticed it because we didn't use to run EXPENSIVE tests until
7a094d68a2 (ci: run expensive tests on push builds to integration
branches, 2026-05-08). And after that commit, the test does not fail but
instead hangs completely.

Ideally, we'd of course properly detect this situation and then test for
it. In practice, this turns out to be hard as the test failure are not
reliable as they often (but not always) run into ENOMEM errors.

Instead, skip the test altogether.

Signed-off-by: Patrick Steinhardt <redacted>
Signed-off-by: Junio C Hamano <redacted>
4 weeks agoREADME: add GitLab CI badge to make it more discoverable
Patrick Steinhardt [Mon, 6 Jul 2026 06:23:56 +0000 (08:23 +0200)]
README: add GitLab CI badge to make it more discoverable

The Git project uses CI systems from both GitHub and GitLab. While both
of these systems are extensively used in day-to-day work, we only have a
link to the GitHub Workflows in our README, which makes the GitLab CI
hard to discover.

Improve the situation by adding a second badge for GitLab CI to our
README.

Signed-off-by: Patrick Steinhardt <redacted>
Signed-off-by: Junio C Hamano <redacted>
4 weeks agomingw: make `exit_process()` own the process handle on all paths
Johannes Schindelin [Sun, 5 Jul 2026 08:24:29 +0000 (08:24 +0000)]
mingw: make `exit_process()` own the process handle on all paths

After "mingw: kill child processes in a gentler way", the ownership of
the HANDLE passed to `exit_process()` and `terminate_process_tree()` is
inconsistent. `terminate_process_tree()` always closes the handle;
`exit_process()` closes it on success and on the terminate-tree
fallback, but leaks it on the early return where GetExitCodeProcess()
fails or reports the process is no longer STILL_ACTIVE.

`mingw_kill()` compensated by closing the handle on its own error path,
which is a double-close on every error path that does not hit that one
leaky branch -- the callee has already closed the handle by then.
Coverity flagged the resulting use-after-free as CID 1437238.

Pin down the invariant that `exit_process()` and
`terminate_process_tree()` own the handle from the call onward and close
it on every return path; with that, the bogus close in `mingw_kill()`
goes away.

Assisted-by: Opus 4.7
Signed-off-by: Johannes Schindelin <redacted>
Signed-off-by: Junio C Hamano <redacted>
4 weeks agofsmonitor: plug token-data leak on early daemon-startup failures
Johannes Schindelin [Sun, 5 Jul 2026 08:24:28 +0000 (08:24 +0000)]
fsmonitor: plug token-data leak on early daemon-startup failures

`fsmonitor_run_daemon()` allocates `state.current_token_data`
before any subordinate setup step that may fail (alias resolution,
listener/health constructors, asynchronous IPC server init). On
the successful path the listener thread takes ownership and clears
the field during its teardown, so the `done:` cleanup block sees a
NULL pointer. On every early-error path, however, control jumps
straight to `done:` with the freshly allocated token data still
referenced, and it is never freed, as Coverity flagged.

Free it at the top of `done:` and clear the pointer. The success
path is a no-op (the pointer is already NULL there); the error
paths now drop the otherwise-leaked allocation.
`fsmonitor_free_token_data()` is NULL-safe and asserts
`client_ref_count == 0`, which holds trivially here because the
IPC server has not yet begun accepting clients when these failures
occur.

Assisted-by: Opus 4.7
Signed-off-by: Johannes Schindelin <redacted>
Signed-off-by: Junio C Hamano <redacted>
4 weeks agoreftable/table: release filter on error path
Johannes Schindelin [Sun, 5 Jul 2026 08:24:27 +0000 (08:24 +0000)]
reftable/table: release filter on error path

`reftable_table_refs_for_unindexed()` allocates a filtering_ref_iterator
and then calls `reftable_buf_add()` to populate its oid buffer. On
success ownership is transferred to the output iterator, but if
`reftable_buf_add()` fails, the goto-out cleanup only frees the table
iterator and walks away from both the filter allocation and the oid
buffer that `reftable_buf_add()` may have grown.

Release filter->oid and free filter alongside the existing table
iterator cleanup.

Reported by Coverity as CID 1671512 ("Resource leak").

Assisted-by: Opus 4.7
Signed-off-by: Johannes Schindelin <redacted>
Signed-off-by: Junio C Hamano <redacted>
4 weeks agoimap-send: avoid leaking the IMAP upload buffer
Johannes Schindelin [Sun, 5 Jul 2026 08:24:26 +0000 (08:24 +0000)]
imap-send: avoid leaking the IMAP upload buffer

When uploading messages via libcurl, `curl_append_msgs_to_imap()`
accumulates each one in a strbuf that grows across loop iterations but
is never released before the function returns.

Release it alongside the existing libcurl cleanup.

Reported by Coverity as CID 1671507 ("Resource leak").

Assisted-by: Opus 4.7
Signed-off-by: Johannes Schindelin <redacted>
Signed-off-by: Junio C Hamano <redacted>
4 weeks agoworktree: fix resource leaks when branch creation fails
Johannes Schindelin [Sun, 5 Jul 2026 08:24:25 +0000 (08:24 +0000)]
worktree: fix resource leaks when branch creation fails

In the "add" subcommand, when `run_command()` fails while creating a new
branch (line 948), the function returns -1 immediately without freeing
the allocations made earlier: path (from prefix_filename at line 858),
opt_track, branch_to_free, and new_branch_to_free.

Redirect the error return through the existing cleanup block at the end
of the function so all four allocations are properly freed.

Pointed out by Coverity.

Assisted-by: Claude Opus 4.6
Signed-off-by: Johannes Schindelin <redacted>
Signed-off-by: Junio C Hamano <redacted>
4 weeks agosubmodule: fix cwd leak in `get_superproject_working_tree()`
Johannes Schindelin [Sun, 5 Jul 2026 08:24:24 +0000 (08:24 +0000)]
submodule: fix cwd leak in `get_superproject_working_tree()`

`get_superproject_working_tree()` allocates cwd via `xgetcwd()` at the
top of the function, but two early-return paths (when not inside a work
tree, and when strbuf_realpath for "../" fails) return 0 without freeing
it.

Redirect these early returns through a cleanup label that frees cwd
before returning.

Pointed out by Coverity.

Assisted-by: Claude Opus 4.6
Signed-off-by: Johannes Schindelin <redacted>
Signed-off-by: Junio C Hamano <redacted>
4 weeks agodir: free allocations on parse-error paths in `read_one_dir()`
Johannes Schindelin [Sun, 5 Jul 2026 08:24:23 +0000 (08:24 +0000)]
dir: free allocations on parse-error paths in `read_one_dir()`

Two of `read_one_dir()`'s parse-error early returns leak ud.untracked
and ud.dirs. Plug them.

The other early returns in the same function are fine: they occur after
the `xmalloc()`+`memcpy()` that copies ud into `*untracked_`, at which
point ownership is transferred to the caller.
`read_untracked_extension()` then releases everything via
`free_untracked_cache()` on failure.

Pointed out by Coverity.

Assisted-by: Claude Opus 4.6
Signed-off-by: Johannes Schindelin <redacted>
Signed-off-by: Junio C Hamano <redacted>
4 weeks agoline-log: avoid redundant copy that leaks in process_ranges
Johannes Schindelin [Sun, 5 Jul 2026 08:24:22 +0000 (08:24 +0000)]
line-log: avoid redundant copy that leaks in process_ranges

When `bloom_filter_check()` indicates that a commit does not touch any
of the tracked paths, `line_log_process_ranges_arbitrary_commit()`
propagates the current ranges to the parent by calling
`line_log_data_copy()` and passing the copy to add_line_range().
However, `add_line_range()` always makes its own copy internally (via
line_log_data_copy or line_log_data_merge), so the caller's copy is
never freed and leaks every time this path is taken.

Pass range directly to `add_line_range()` instead of making a redundant
intermediate copy. The callee's internal copy handles ownership
correctly.

Pointed out by Coverity.

Assisted-by: Claude Opus 4.6
Signed-off-by: Johannes Schindelin <redacted>
Signed-off-by: Junio C Hamano <redacted>
4 weeks agorun-command: avoid `close(-1)` in `start_command()` error paths
Johannes Schindelin [Sun, 5 Jul 2026 08:24:21 +0000 (08:24 +0000)]
run-command: avoid `close(-1)` in `start_command()` error paths

When `start_command()` fails to set up a pipe partway through, it rolls
back by closing the pipe ends it has already opened. For descriptors
supplied by the caller rather than allocated locally, that rollback
tested `if (cmd->in)` / `if (cmd->out)` before calling close(). The
CHILD_PROCESS_INIT default of -1 ("no descriptor") is non-zero and so
passes the test, meaning a caller that sets cmd->no_stdin or
cmd->no_stdout without supplying a real fd ends up triggering close(-1)
on the error path.

The stdin-pipe failure branch a few lines above already uses the right
idiom, `if (cmd->out > 0)`, which rejects both the -1 sentinel and 0
(the parent's own standard streams). Apply it to the three remaining
rollback sites.

Reported by Coverity as CID 1049722 ("Argument cannot be negative").

Assisted-by: Opus 4.7
Signed-off-by: Johannes Schindelin <redacted>
Signed-off-by: Junio C Hamano <redacted>
4 weeks agodownload_https_uri_to_file(): do not leak fd upon failure
Johannes Schindelin [Sun, 5 Jul 2026 08:24:20 +0000 (08:24 +0000)]
download_https_uri_to_file(): do not leak fd upon failure

When the `git-remote-https` command fails, we do not want to leak
`child_out`.

Pointed out by Coverity.

Signed-off-by: Johannes Schindelin <redacted>
Signed-off-by: Junio C Hamano <redacted>
4 weeks agoloose: avoid closing invalid fd on error path
Johannes Schindelin [Sun, 5 Jul 2026 08:24:19 +0000 (08:24 +0000)]
loose: avoid closing invalid fd on error path

`write_one_object()` opens a file at line 186 and jumps to the errout
label on failure. The errout cleanup unconditionally calls `close(fd)`,
but when `open()` itself failed, fd is -1. Calling `close(-1)` is
harmless on most platforms (returns EBADF) but is undefined behavior per
POSIX and can confuse fd tracking in sanitizer builds.

Guard the close with fd >= 0.

Pointed out by Coverity.

Assisted-by: Claude Opus 4.6
Signed-off-by: Johannes Schindelin <redacted>
Signed-off-by: Junio C Hamano <redacted>
4 weeks agoload_one_loose_object_map(): fix resource leak
Johannes Schindelin [Sun, 5 Jul 2026 08:24:18 +0000 (08:24 +0000)]
load_one_loose_object_map(): fix resource leak

Pointed out by Coverity.

While at it, reduce near-duplicate clean-up code at the end of the
function.

Signed-off-by: Johannes Schindelin <redacted>
Signed-off-by: Junio C Hamano <redacted>
4 weeks agoprecompose_utf8: use a flex array for d_name
Ihar Hrachyshka [Sat, 4 Jul 2026 23:37:24 +0000 (19:37 -0400)]
precompose_utf8: use a flex array for d_name

On macOS, git status may abort while reading a directory entry
whose UTF-8 name grows past NAME_MAX bytes:

  __chk_fail_overflow
  __strlcpy_chk
  precompose_utf8_readdir
  read_directory_recursive
  wt_status_collect
  cmd_status

The precompose wrapper already reallocates dirent_prec_psx for
long names, but d_name is declared as char[NAME_MAX + 1]. A
fortified libc can still see that declared object size and reject a
larger strlcpy bound, even though the allocation was grown.

Make d_name a FLEX_ARRAY and size allocations from offsetof(). That
matches the actual object layout with the dynamic allocation, so the
fortified copy sees a destination whose size can grow with max_name_len.

Add a regression test that creates an over-NAME_MAX non-ASCII basename
and runs status with core.precomposeunicode enabled.

Signed-off-by: Ihar Hrachyshka <redacted>
Signed-off-by: Junio C Hamano <redacted>
4 weeks agoci(dockerized): raise the PID limit for private repositories
Johannes Schindelin [Sat, 4 Jul 2026 08:52:04 +0000 (08:52 +0000)]
ci(dockerized): raise the PID limit for private repositories

Every once in a while I need to verify that Microsoft Git's test suite
passes for changes that are not yet meant for public consumption, and
since it was (made) too difficult to keep up a working Azure Pipeline
definition, I have to use GitHub Actions in a private GitHub repository
for that purpose.

In these tests, basically all Dockerized CI jobs fail consistently. The
symptom is something like:

  error: cannot create async thread: Resource temporarily unavailable

in the middle of a test, typically in the t5xxx-t6xxx range. The first
such error is immediately followed by plenty more of these errors, and
not a single test succeeds afterwards.

At first, I thought that maybe the massive parallelism I enjoy there is
the problem, and I thought that the cgroups limits might be shared
between the many containers that run on essentially the same physical
machine. But even reducing the matrix to just a single of those
Dockerized jobs runs into the very same problems.

The underlying reason seems to be a substantial difference in the hosted
runners that execute these Dockerized jobs: forcing the PID limit of the
container to a high number lets the jobs pass, even when running the
complete matrix of all 13 Dockerized jobs concurrently. But that's not
the only difference: The jobs seem to take a lot longer in these
containers than, say, in the containers made available to
https://github.com/git/git.

When forcing a PID limit of 64k in that private repository, the jobs
completed successfully, but they also took a lot longer, between 2x to
2.5x longer, i.e. painfully much longer. Reducing the PID limit to 16k,
the CI jobs still passed, but took an equally long amount of time.
Reducing the PID limit to 8k caused the errors to reappear.

Here are the numbers from three example runs, the first one forcing the
PID and nproc limit to 65536, the second one to 16384, the third run is
from the public git/git repository:

Job                           | 64k     | 16k     | reference
------------------------------|---------|---------|---------
almalinux-8                   | 19m 3s  | 16m 0s  | 9m 36s
debian-11                     | 20m 31s | 20m 3s  | 8m 5s
fedora-breaking-changes-meson | 16m 29s | 19m 19s | 9m 40s
linux-asan-ubsan              | 1h 10m  | 1h 11m  | 34m 36s
linux-breaking-changes        | 25m 39s | 25m 58s | 13m 15s
linux-leaks                   | 1h 9m   | 1h 10m  | 33m 30s
linux-meson                   | 28m 9s  | 27m 4s  | 13m 45s
linux-musl-meson              | 16m 32s | 13m 39s | 8m 6s
linux-reftable-leaks          | 1h 13m  | 1h 13m  | 34m 34s
linux-reftable                | 26m 2s  | 25m 48s | 13m 31s
linux-sha256                  | 26m 12s | 26m 3s  | 12m 36s
linux-TEST-vars               | 26m 5s  | 25m 21s | 13m 25s
linux32                       | 21m 16s | 19m 57s | 10m 44s

It does not look as if the PID limit is the reason for the longer
runtime, seeing as the 64k vs 16k timings deviate no more than as is
usual with GitHub workflows. So let's go for 16k.

Signed-off-by: Johannes Schindelin <redacted>
Signed-off-by: Junio C Hamano <redacted>
4 weeks agoreftable/table: fix OOB read on truncated table
Patrick Steinhardt [Fri, 3 Jul 2026 12:58:55 +0000 (14:58 +0200)]
reftable/table: fix OOB read on truncated table

When opening a table we compute the size of its data section by
subtracting the footer size from the file size. We do not verify that
the file is actually large enough to contain both the header and the
footer though. With a truncated table the subtraction can thus
underflow, causing us to read the footer out of bounds:

  SUMMARY: AddressSanitizer: heap-buffer-overflow (/home/pks/Development/git/build/t/unit-tests+0x2479a4) in __asan_memcpy
  Shadow bytes around the buggy address:
    0x7ccff6e0de80: fa fa fa fa fa fa fa fa fd fd fd fd fd fd fd fd
    0x7ccff6e0df00: fd fd fd fd fd fd fd fd fd fa fa fa fa fa fa fa
    0x7ccff6e0df80: fa fa fd fd fd fd fd fd fd fd fd fd fd fd fd fd
    0x7ccff6e0e000: fd fd fd fd fa fa fa fa fa fa fa fa fd fd fd fd
    0x7ccff6e0e080: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fa fa
  =>0x7ccff6e0e100: fa fa fa fa fa[fa]00 00 00 00 00 00 00 00 00 00
    0x7ccff6e0e180: 00 00 00 00 00 00 00 04 fa fa fa fa fa fa fa fa
    0x7ccff6e0e200: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
    0x7ccff6e0e280: 00 00 fa fa fa fa fa fa fa fa fa fa fa fa fa fa
    0x7ccff6e0e300: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
    0x7ccff6e0e380: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  Shadow byte legend (one shadow byte represents 8 application bytes):
    Addressable:           00
    Partially addressable: 01 02 03 04 05 06 07
    Heap left redzone:       fa
    Freed heap region:       fd
    Stack left redzone:      f1
    Stack mid redzone:       f2
    Stack right redzone:     f3
    Stack after return:      f5
    Stack use after scope:   f8
    Global redzone:          f9
    Global init order:       f6
    Poisoned by user:        f7
    Container overflow:      fc
    Array cookie:            ac
    Intra object redzone:    bb
    ASan internal:           fe
    Left alloca redzone:     ca
    Right alloca redzone:    cb
  ==1500371==ABORTING

Verify that the file is large enough to contain both the header and the
footer before computing the table size.

Signed-off-by: Patrick Steinhardt <redacted>
Signed-off-by: Junio C Hamano <redacted>
4 weeks agoreftable/table: fix NULL pointer access when seeking to bogus offsets
Patrick Steinhardt [Fri, 3 Jul 2026 12:58:54 +0000 (14:58 +0200)]
reftable/table: fix NULL pointer access when seeking to bogus offsets

When seeking an iterator to an arbitrary offset we may return a positive
value in case the offset points beyond the block. This makes sense when
iterating through multiple blocks of the same section, as the positive
value indicates to us that we're at the end of the table.

But when the offset originates from a section or index offset it is
supposed to point at a valid block, so an out-of-bounds value means that
the table is corrupt. Treating it as a normal end-of-iteration causes us
to silently report an empty section instead of surfacing the corruption,
and we are left with a partially-initialized block. This may later on
cause a NULL pointer exception:

  ==1486841==ERROR: AddressSanitizer: SEGV on unknown address 0x000000000000 (pc 0x55555598e02c bp 0x7fffffff4eb0 sp 0x7fffffff4e70 T0)
  ==1486841==The signal is caused by a READ memory access.
  ==1486841==Hint: address points to the zero page.
      #0 0x55555598e02c in reftable_block_type ./git/build/../reftable/block.c:392:9
      #1 0x55555598ee6e in block_iter_seek_key ./git/build/../reftable/block.c:536:35
      #2 0x5555559ae553 in table_iter_seek_linear ./git/build/../reftable/table.c:344:8
      #3 0x5555559adbff in table_iter_seek ./git/build/../reftable/table.c:450:9
      #4 0x5555559ada9c in table_iter_seek_void ./git/build/../reftable/table.c:460:9
      #5 0x555555992872 in reftable_iterator_seek_log_at ./git/build/../reftable/iter.c:281:9
      #6 0x555555992953 in reftable_iterator_seek_log ./git/build/../reftable/iter.c:287:9
      #7 0x55555583aa78 in test_reftable_table__seek_invalid_log_offset ./git/build/../t/unit-tests/u-reftable-table.c:257:20
      #8 0x5555557f684e in clar_run_test ./git/build/../t/unit-tests/clar/clar.c:335:3
      #9 0x5555557f2e69 in clar_run_suite ./git/build/../t/unit-tests/clar/clar.c:431:3
      #10 0x5555557f2882 in clar_test_run ./git/build/../t/unit-tests/clar/clar.c:636:4
      #11 0x5555557f375f in clar_test ./git/build/../t/unit-tests/clar/clar.c:687:11
      #12 0x5555557fa49d in cmd_main ./git/build/../t/unit-tests/unit-test.c:62:8
      #13 0x55555584cffa in main ./git/build/../common-main.c:9:11
      #14 0x7ffff7a2b284 in __libc_start_call_main (/nix/store/57iz36553175g3178pvxjij8z5rcsd4n-glibc-2.42-61/lib/libc.so.6+0x2b284) (BuildId: 8ae0b698f2d4e727f569f64bb166e08ae30bd077)
      #15 0x7ffff7a2b337 in __libc_start_main@GLIBC_2.2.5 (/nix/store/57iz36553175g3178pvxjij8z5rcsd4n-glibc-2.42-61/lib/libc.so.6+0x2b337) (BuildId: 8ae0b698f2d4e727f569f64bb166e08ae30bd077)
      #16 0x555555694c24 in _start (./git/build/t/unit-tests+0x140c24)

  ==1486841==Register values:
  rax = 0x0000000000000000  rbx = 0x00007fffffff4ec0  rcx = 0x0000000000000000  rdx = 0x00007cfff6e2bd58
  rdi = 0x00007cfff6e2bd58  rsi = 0x00007bfff5da1020  rbp = 0x00007fffffff4eb0  rsp = 0x00007fffffff4e70
   r8 = 0x0000000000000000   r9 = 0x0000000000000002  r10 = 0x0000000000000000  r11 = 0x0000000000000017
  r12 = 0x00007fffffff5908  r13 = 0x0000000000000001  r14 = 0x00007ffff7ffd000  r15 = 0x0000555556056e90
  AddressSanitizer can not provide additional info.
  SUMMARY: AddressSanitizer: SEGV ./git/build/../reftable/block.c:392:9 in reftable_block_type
  ==1486841==ABORTING

Fix this by returning a proper error in `table_iter_seek_to()` when the
offset ranges beyond the block.

Signed-off-by: Patrick Steinhardt <redacted>
Signed-off-by: Junio C Hamano <redacted>
4 weeks agoreftable/block: fix OOB read with bogus restart offset
Patrick Steinhardt [Fri, 3 Jul 2026 12:58:53 +0000 (14:58 +0200)]
reftable/block: fix OOB read with bogus restart offset

Restart points encode records in a given block that do not use prefix
compression and that can thus immediately be seeked to. These offsets
are encoded in the restart table, where each offset needs to point at
one of the records of the block. We do not verify this though, so a
bogus restart offset may cause an out-of-bounds read:

  ==1472280==ERROR: AddressSanitizer: SEGV on unknown address 0x7d8ff7de5f7f (pc 0x55555599502b bp 0x7fffffff4df0 sp 0x7fffffff4d40 T0)
  ==1472280==The signal is caused by a READ memory access.
      #0 0x55555599502b in get_var_int ./git/build/../reftable/record.c:30:6
      #1 0x555555995c2a in reftable_decode_keylen ./git/build/../reftable/record.c:177:6
      #2 0x55555598e85c in restart_needle_less ./git/build/../reftable/block.c:455:6
      #3 0x55555598895f in binsearch ./git/build/../reftable/basics.c:175:9
      #4 0x55555598e189 in block_iter_seek_key ./git/build/../reftable/block.c:543:6
      #5 0x555555814aee in test_reftable_block__corrupt_restart_offset ./git/build/../t/unit-tests/u-reftable-block.c:636:20
      #6 0x5555557f684e in clar_run_test ./git/build/../t/unit-tests/clar/clar.c:335:3
      #7 0x5555557f2e69 in clar_run_suite ./git/build/../t/unit-tests/clar/clar.c:431:3
      #8 0x5555557f2882 in clar_test_run ./git/build/../t/unit-tests/clar/clar.c:636:4
      #9 0x5555557f375f in clar_test ./git/build/../t/unit-tests/clar/clar.c:687:11
      #10 0x5555557fa49d in cmd_main ./git/build/../t/unit-tests/unit-test.c:62:8
      #11 0x55555584c25a in main ./git/build/../common-main.c:9:11
      #12 0x7ffff7a2b284 in __libc_start_call_main (/nix/store/57iz36553175g3178pvxjij8z5rcsd4n-glibc-2.42-61/lib/libc.so.6+0x2b284) (BuildId: 8ae0b698f2d4e727f569f64bb166e08ae30bd077)
      #13 0x7ffff7a2b337 in __libc_start_main@GLIBC_2.2.5 (/nix/store/57iz36553175g3178pvxjij8z5rcsd4n-glibc-2.42-61/lib/libc.so.6+0x2b337) (BuildId: 8ae0b698f2d4e727f569f64bb166e08ae30bd077)
      #14 0x555555694c24 in _start (./git/build/t/unit-tests+0x140c24)

  ==1472280==Register values:
  rax = 0x00007d8ff7de5f7f  rbx = 0x00007fffffff4e00  rcx = 0x00007d8ff7de5f80  rdx = 0x00007bfff5b6af60
  rdi = 0x00007bfff5b6af40  rsi = 0x00007bfff592dfa0  rbp = 0x00007fffffff4df0  rsp = 0x00007fffffff4d40
   r8 = 0x00000000ff00002b   r9 = 0x00007d8ff7de5f7f  r10 = 0x00000f7ffeb25bf0  r11 = 0xf3f30000f1f1f1f1
  r12 = 0x00007fffffff58f8  r13 = 0x0000000000000001  r14 = 0x00007ffff7ffd000  r15 = 0x0000555556055fd0
  AddressSanitizer can not provide additional info.
  SUMMARY: AddressSanitizer: SEGV ./git/build/../reftable/record.c:30:6 in get_var_int

Guard against such restart offsets and signal an error to the caller via
`args.error`.

Signed-off-by: Patrick Steinhardt <redacted>
Signed-off-by: Junio C Hamano <redacted>
4 weeks agoreftable/block: fix use of uninitialized memory when binsearch fails
Patrick Steinhardt [Fri, 3 Jul 2026 12:58:52 +0000 (14:58 +0200)]
reftable/block: fix use of uninitialized memory when binsearch fails

When doing the binary search through our restart offsets we may hit an
error in case `restart_needle_less()` fails to decode the record at the
given offset. While we correctly detect this case and error out, it will
cause us to call `reftable_record_release()` on the yet-uninitialized
record.

Fix this by initializing the record earlier.

Signed-off-by: Patrick Steinhardt <redacted>
Signed-off-by: Junio C Hamano <redacted>
4 weeks agoreftable/block: fix OOB read with bogus restart count
Patrick Steinhardt [Fri, 3 Jul 2026 12:58:51 +0000 (14:58 +0200)]
reftable/block: fix OOB read with bogus restart count

The restart count is stored in the last two bytes of a block. We use it
without verification to compute the offset of the restart table. With a
bogus restart count that is large enough this computation underflows,
and the subsequent reads via the restart table access out-of-bounds
memory:

  ==129439==ERROR: AddressSanitizer: SEGV on unknown address 0x7d90f6dcd0ad (pc 0x55555598ce89 bp 0x7fffffff4ed0 sp 0x7fffffff4e80 T0)
  ==129439==The signal is caused by a READ memory access.
      #0 0x55555598ce89 in reftable_get_be24 ./git/build/../reftable/basics.h:125:9
      #1 0x55555598eabf in block_restart_offset ./git/build/../reftable/block.c:407:9
      #2 0x55555598e5d5 in restart_needle_less ./git/build/../reftable/block.c:431:17
      #3 0x5555559887e2 in binsearch ./git/build/../reftable/basics.c:165:13
      #4 0x55555598dfec in block_iter_seek_key ./git/build/../reftable/block.c:529:6
      #5 0x555555814517 in test_reftable_block__corrupt_restart_count ./git/build/../t/unit-tests/u-reftable-block.c:593:15
      #6 0x5555557f684e in clar_run_test ./git/build/../t/unit-tests/clar/clar.c:335:3
      #7 0x5555557f2e69 in clar_run_suite ./git/build/../t/unit-tests/clar/clar.c:431:3
      #8 0x5555557f2882 in clar_test_run ./git/build/../t/unit-tests/clar/clar.c:636:4
      #9 0x5555557f375f in clar_test ./git/build/../t/unit-tests/clar/clar.c:687:11
      #10 0x5555557fa49d in cmd_main ./git/build/../t/unit-tests/unit-test.c:62:8
      #11 0x55555584c12a in main ./git/build/../common-main.c:9:11
      #12 0x7ffff7a2b284 in __libc_start_call_main (/nix/store/57iz36553175g3178pvxjij8z5rcsd4n-glibc-2.42-61/lib/libc.so.6+0x2b284) (BuildId: 8ae0b698f2d4e727f569f64bb166e08ae30bd077)
      #13 0x7ffff7a2b337 in __libc_start_main@GLIBC_2.2.5 (/nix/store/57iz36553175g3178pvxjij8z5rcsd4n-glibc-2.42-61/lib/libc.so.6+0x2b337) (BuildId: 8ae0b698f2d4e727f569f64bb166e08ae30bd077)
      #14 0x555555694c24 in _start (./git/build/t/unit-tests+0x140c24)

  ==129439==Register values:
  rax = 0x00007d90f6dcd0ad  rbx = 0x00007fffffff4f20  rcx = 0xf2f2f2f8f2f2f2f8  rdx = 0x0000000000000000
  rdi = 0x00007d90f6dcd0ad  rsi = 0x0000000000007fff  rbp = 0x00007fffffff4ed0  rsp = 0x00007fffffff4e80
   r8 = 0x0000000000000000   r9 = 0x0000000000000000  r10 = 0x0000000000000000  r11 = 0x0000000000000017
  r12 = 0x00007fffffff58e8  r13 = 0x0000000000000001  r14 = 0x00007ffff7ffd000  r15 = 0x00005555560550b0
  AddressSanitizer can not provide additional info.
  SUMMARY: AddressSanitizer: SEGV ./git/build/../reftable/basics.h:125:9 in reftable_get_be24

Verify that the restart table actually fits into the block.

Signed-off-by: Patrick Steinhardt <redacted>
Signed-off-by: Junio C Hamano <redacted>
4 weeks agoreftable/block: fix OOB read with bogus block size
Patrick Steinhardt [Fri, 3 Jul 2026 12:58:50 +0000 (14:58 +0200)]
reftable/block: fix OOB read with bogus block size

The block size is read from the block header, which is untrusted data.
We use it without verification to access the restart count at the end of
the block as well as to compute the restart table offset. With a bogus
block size that exceeds the data we have actually read this can lead to
an out-of-bounds read:

  ==2274138==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x7c3ff6de2e3f at pc 0x55555598c6ea bp 0x7fffffff4ee0 sp 0x7fffffff4ed8
  READ of size 1 at 0x7c3ff6de2e3f thread T0
      #0 0x55555598c6e9 in reftable_get_be16 /home/pks/Development/git/build/../reftable/basics.h:119:20
      #1 0x55555598c252 in reftable_block_init /home/pks/Development/git/build/../reftable/block.c:343:18
      #2 0x555555813c70 in test_reftable_block__corrupt_block_size /home/pks/Development/git/build/../t/unit-tests/u-reftable-block.c:531:20
      #3 0x5555557f684e in clar_run_test /home/pks/Development/git/build/../t/unit-tests/clar/clar.c:335:3
      #4 0x5555557f2e69 in clar_run_suite /home/pks/Development/git/build/../t/unit-tests/clar/clar.c:431:3
      #5 0x5555557f2882 in clar_test_run /home/pks/Development/git/build/../t/unit-tests/clar/clar.c:636:4
      #6 0x5555557f375f in clar_test /home/pks/Development/git/build/../t/unit-tests/clar/clar.c:687:11
      #7 0x5555557fa49d in cmd_main /home/pks/Development/git/build/../t/unit-tests/unit-test.c:62:8
      #8 0x55555584b8aa in main /home/pks/Development/git/build/../common-main.c:9:11
      #9 0x7ffff7a2b284 in __libc_start_call_main (/nix/store/8kvxvr3pmsypxiypq4g8zy13glnfr7nx-glibc-2.42-67/lib/libc.so.6+0x2b284) (BuildId: 5a702452a01df1d7d50ce0663acec7be3c71fd4d)
      #10 0x7ffff7a2b337 in __libc_start_main@GLIBC_2.2.5 (/nix/store/8kvxvr3pmsypxiypq4g8zy13glnfr7nx-glibc-2.42-67/lib/libc.so.6+0x2b337) (BuildId: 5a702452a01df1d7d50ce0663acec7be3c71fd4d)
      #11 0x555555694c24 in _start (/home/pks/Development/git/build/t/unit-tests+0x140c24)

  0x7c3ff6de2e3f is located 0 bytes after 47-byte region [0x7c3ff6de2e10,0x7c3ff6de2e3f)
  allocated by thread T0 here:
      #0 0x55555579e95b in malloc (/home/pks/Development/git/build/t/unit-tests+0x24a95b)
      #1 0x5555559871c2 in reftable_malloc /home/pks/Development/git/build/../reftable/basics.c:24:9
      #2 0x5555559872e8 in reftable_calloc /home/pks/Development/git/build/../reftable/basics.c:54:6
      #3 0x55555598f0d3 in reftable_buf_read_data /home/pks/Development/git/build/../reftable/blocksource.c:67:2
      #4 0x55555598ea7e in block_source_read_data /home/pks/Development/git/build/../reftable/blocksource.c:41:19
      #5 0x55555598c555 in read_block /home/pks/Development/git/build/../reftable/block.c:224:9
      #6 0x55555598b69e in reftable_block_init /home/pks/Development/git/build/../reftable/block.c:258:9
      #7 0x555555813c70 in test_reftable_block__corrupt_block_size /home/pks/Development/git/build/../t/unit-tests/u-reftable-block.c:531:20
      #8 0x5555557f684e in clar_run_test /home/pks/Development/git/build/../t/unit-tests/clar/clar.c:335:3
      #9 0x5555557f2e69 in clar_run_suite /home/pks/Development/git/build/../t/unit-tests/clar/clar.c:431:3
      #10 0x5555557f2882 in clar_test_run /home/pks/Development/git/build/../t/unit-tests/clar/clar.c:636:4
      #11 0x5555557f375f in clar_test /home/pks/Development/git/build/../t/unit-tests/clar/clar.c:687:11
      #12 0x5555557fa49d in cmd_main /home/pks/Development/git/build/../t/unit-tests/unit-test.c:62:8
      #13 0x55555584b8aa in main /home/pks/Development/git/build/../common-main.c:9:11
      #14 0x7ffff7a2b284 in __libc_start_call_main (/nix/store/8kvxvr3pmsypxiypq4g8zy13glnfr7nx-glibc-2.42-67/lib/libc.so.6+0x2b284) (BuildId: 5a702452a01df1d7d50ce0663acec7be3c71fd4d)
      #15 0x7ffff7a2b337 in __libc_start_main@GLIBC_2.2.5 (/nix/store/8kvxvr3pmsypxiypq4g8zy13glnfr7nx-glibc-2.42-67/lib/libc.so.6+0x2b337) (BuildId: 5a702452a01df1d7d50ce0663acec7be3c71fd4d)
      #16 0x555555694c24 in _start (/home/pks/Development/git/build/t/unit-tests+0x140c24)

  SUMMARY: AddressSanitizer: heap-buffer-overflow /home/pks/Development/git/build/../reftable/basics.h:119:20 in reftable_get_be16
  Shadow bytes around the buggy address:
    0x7c3ff6de2b80: fa fa fd fd fd fd fd fa fa fa fd fd fd fd fd fa
    0x7c3ff6de2c00: fa fa fd fd fd fd fd fa fa fa fd fd fd fd fd fa
    0x7c3ff6de2c80: fa fa fd fd fd fd fd fd fa fa fd fd fd fd fd fa
    0x7c3ff6de2d00: fa fa fd fd fd fd fd fd fa fa fd fd fd fd fd fa
    0x7c3ff6de2d80: fa fa 00 00 00 00 00 00 fa fa fd fd fd fd fd fd
  =>0x7c3ff6de2e00: fa fa 00 00 00 00 00[07]fa fa fa fa fa fa fa fa
    0x7c3ff6de2e80: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
    0x7c3ff6de2f00: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
    0x7c3ff6de2f80: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
    0x7c3ff6de3000: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
    0x7c3ff6de3080: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  Shadow byte legend (one shadow byte represents 8 application bytes):
    Addressable:           00
    Partially addressable: 01 02 03 04 05 06 07
    Heap left redzone:       fa
    Freed heap region:       fd
    Stack left redzone:      f1
    Stack mid redzone:       f2
    Stack right redzone:     f3
    Stack after return:      f5
    Stack use after scope:   f8
    Global redzone:          f9
    Global init order:       f6
    Poisoned by user:        f7
    Container overflow:      fc
    Array cookie:            ac
    Intra object redzone:    bb
    ASan internal:           fe
    Left alloca redzone:     ca
    Right alloca redzone:    cb

Verify that the claimed block size fits into the block data before using
it.

Signed-off-by: Patrick Steinhardt <redacted>
Signed-off-by: Junio C Hamano <redacted>
git clone https://git.99rst.org/PROJECT