From 0bb83c5f470579893ed0f0a6f9686c4383c928ce Mon Sep 17 00:00:00 2001 From: Shlok Kulshreshtha Date: Mon, 17 Aug 2026 13:51:27 +0530 Subject: [PATCH 1/4] object-name: avoid use-after-free in get_oid_with_context_1() When a ":" argument names a relative path, resolve_relative_path() returns a newly allocated string and "cp" is pointed at it: new_path = resolve_relative_path(repo, cp); if (!new_path) { namelen = namelen - (cp - name); } else { cp = new_path; namelen = strlen(cp); } From there on "cp" and "new_path" name the same allocation. Later the memory location that "new_path" points to is freed. free(new_path); if (reject_tree_in_index(repo, only_to_die, ce, stage, prefix, cp)) But here the reject_tree_in_index() passes "cp" to diagnose_invalid_index_path(), which calls strlen() on it, looks it up in the index, and formats it into its messages, allocating as it goes. All of this reads memory that has already been freed. Collapse the two exits into one to ensure a single free() that happens after the last use. Three things have to coincide to reach this: 1. The path has to be relative, or nothing is allocated and "cp" still points into the argument. 2. The entry found has to be a sparse directory, which needs a sparse index. 3. The argument has to get past the check in die_verify_filename() that skips a leading ':' followed by a non-alphanumeric, so ":0:./dir/" arrives here where ":./dir/" does not. Add a test to t1092 that covers the combination. It fails under SANITIZE=address without the change to object-name.c. This was reported in [1], and the shape used here was suggested in review [2], but that series was not rerolled and the fix never landed. [1] https://lore.kernel.org/git/cf6bcdb43e5b4abab464c30a914d64dc8e7a9925.1655336146.git.gitgitgadget@gmail.com/ [2] https://lore.kernel.org/git/xmqqy1xxw7rc.fsf@gitster.g/ Reported-by: Johannes Schindelin Original-patch-by: Johannes Schindelin Helped-by: Junio C Hamano Suggested-by: Patrick Steinhardt Signed-off-by: Shlok Kulshreshtha Signed-off-by: Junio C Hamano --- object-name.c | 14 ++++++++------ t/t1092-sparse-checkout-compatibility.sh | 11 +++++++++++ 2 files changed, 19 insertions(+), 6 deletions(-) diff --git a/object-name.c b/object-name.c index 46159466ac543a..9221d532ff08bd 100644 --- a/object-name.c +++ b/object-name.c @@ -1803,13 +1803,15 @@ static enum get_oid_result get_oid_with_context_1(struct repository *repo, memcmp(ce->name, cp, namelen)) break; if (ce_stage(ce) == stage) { + int ret = reject_tree_in_index(repo, only_to_die, ce, + stage, prefix, cp); + + if (!ret) { + oidcpy(oid, &ce->oid); + oc->mode = ce->ce_mode; + } free(new_path); - if (reject_tree_in_index(repo, only_to_die, ce, - stage, prefix, cp)) - return -1; - oidcpy(oid, &ce->oid); - oc->mode = ce->ce_mode; - return 0; + return ret; } pos++; } diff --git a/t/t1092-sparse-checkout-compatibility.sh b/t/t1092-sparse-checkout-compatibility.sh index 8186da5c887c56..be85ee0c4b7c10 100755 --- a/t/t1092-sparse-checkout-compatibility.sh +++ b/t/t1092-sparse-checkout-compatibility.sh @@ -1357,6 +1357,17 @@ do " done +test_expect_success 'relative path to a sparse directory' ' + init_repos && + + # A "::" argument whose path is relative is resolved + # into a heap-allocated buffer, and a sparse directory found at that + # path is reported through it. Cover that combination, so that the + # reporting does not read the buffer after it has been released. + test_sparse_match test_must_fail git show :0:./folder1/ && + test_sparse_match test_must_fail git rev-parse :0:./folder1/ +' + test_expect_success 'submodule handling' ' init_repos && From ddd7de134192fe287a2d1305227c99392b7cd8c7 Mon Sep 17 00:00:00 2001 From: Kristoffer Haugsbakk Date: Mon, 17 Aug 2026 20:51:48 +0200 Subject: [PATCH 2/4] doc: format-rev: quote subject placeholder before and after MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We first talk about just `%s`, but then show the result with quotes. That is inconsistent. Let’s use quotes both in the format as well as in the result. The implied input here, which is not spelled out for brevity, is: Did we not fix this in ? Which is then supposed to be formatted to `""`. Signed-off-by: Kristoffer Haugsbakk Signed-off-by: Junio C Hamano --- Documentation/git-format-rev.adoc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Documentation/git-format-rev.adoc b/Documentation/git-format-rev.adoc index 505a52feccd466..19241837345a91 100644 --- a/Documentation/git-format-rev.adoc +++ b/Documentation/git-format-rev.adoc @@ -93,8 +93,8 @@ acts as a _terminator_, not a _separator_. In other words, the final line or record is also terminated by the terminator character. The mode `--stdin-mode=text` replaces each object name with the -formatted commit, i.e. the format `%s` would transform some commit -object name to `` without any termination. Like this: +formatted commit, i.e. the format `"%s"` would transform some commit +object name to `""` without any termination. Like this: ---- Did we not fix this in ""? From 634257a89b4619ff14f9e7c75cc2645e52d8702b Mon Sep 17 00:00:00 2001 From: Kristoffer Haugsbakk Date: Mon, 17 Aug 2026 20:51:49 +0200 Subject: [PATCH 3/4] doc: format-rev: use [synopsis] on code block MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This code block uses the placeholder ``. Let’s highlight this placeholder properly by using the `synopsis` open block definition which was introduced in a34d1d53 (doc: convert git-show to synopsis style, 2026-02-06). This renders the block like a code block but with emphasis styling on placeholders, just like inline-verbatim (`) in running text. Yes, note that open blocks since commit a34d1d53 can, on synopsis-style docs like this one, be immediately preceded by `[synopsis]`, just like the command synopsis is: [synopsis] (EXPERIMENTAL!) git format-rev - [...] Cf. verse-style: [verse] 'git name-rev' [...] Signed-off-by: Kristoffer Haugsbakk Signed-off-by: Junio C Hamano --- Documentation/git-format-rev.adoc | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/Documentation/git-format-rev.adoc b/Documentation/git-format-rev.adoc index 19241837345a91..c2268c92b56bac 100644 --- a/Documentation/git-format-rev.adoc +++ b/Documentation/git-format-rev.adoc @@ -96,9 +96,10 @@ The mode `--stdin-mode=text` replaces each object name with the formatted commit, i.e. the format `"%s"` would transform some commit object name to `""` without any termination. Like this: ----- +[synopsis] +-- Did we not fix this in ""? ----- +-- It is safe to interactively read and write from this command since each record is immediately flushed. From c73e85354c275c9d409b26445089bc16940fc527 Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Fri, 28 Aug 2026 11:04:47 -0700 Subject: [PATCH 4/4] The 20th batch Signed-off-by: Junio C Hamano --- Documentation/RelNotes/2.56.0.adoc | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/Documentation/RelNotes/2.56.0.adoc b/Documentation/RelNotes/2.56.0.adoc index 65f0d965633959..3cf754a0bdfa49 100644 --- a/Documentation/RelNotes/2.56.0.adoc +++ b/Documentation/RelNotes/2.56.0.adoc @@ -126,6 +126,11 @@ UI, Workflows & Features clones, reclaiming space. Guards prevent running during other operations or if referenced by the index. + * The documentation for 'git format-rev' has been updated to use the + [synopsis] block definition on code blocks to properly highlight + placeholders, and a quoting inconsistency in the running text has + been fixed. + Performance, Internal Implementation, Development Support etc. -------------------------------------------------------------- @@ -343,14 +348,12 @@ Performance, Internal Implementation, Development Support etc. positive warning from the 'CHECK_ASSERTION_SIDE_EFFECTS' build with GCC 15 in the Bloom filter code has also been silenced to facilitate the image upgrade. - (merge 1a1579c42d jk/ci-static-analysis-image-bump later to maint). * The alias tests in 't/t0014-alias.sh' have been updated to dynamically query the list of deprecated commands using 'git --list-cmds=deprecated' to avoid test failures when running with 'WITH_BREAKING_CHANGES' in a build directory that contains stale executables of formerly deprecated commands. - (merge bc57ecb915 jk/t0014-dynamic-deprecated-cmds later to maint). * The code path that deals with relative paths in the diff-lib has been cleaned up. @@ -389,7 +392,6 @@ Performance, Internal Implementation, Development Support etc. * The 'ssh-agent' tests in 't7528' have been fixed to work when the user's login shell is csh-like, by explicitly passing '-s' to 'ssh-agent' to force Bourne shell syntax. - (merge d5dd17756d kl/t7528-ssh-agent-for-csh-users later to maint). * A compatibility wrapper for writev(3p) has been reintroduced, including fixes for CMake build and 'MAX_IO_SIZE' limits on NonStop. @@ -434,6 +436,10 @@ Performance, Internal Implementation, Development Support etc. related callback signatures across several subsystems, simplifying the API now that trace output no longer uses it. + * A heap-use-after-free bug in the object name parsing code when + reporting failures with a relative path to a sparse directory has + been corrected. + Fixes since v2.55 -----------------