]> git.ipfire.org Git - thirdparty/git.git/commitdiff
pack-bitmap: prevent pattern leak on pseudo-merge re-assignment
authorTaylor Blau <me@ttaylorr.com>
Tue, 21 Apr 2026 20:02:20 +0000 (16:02 -0400)
committerJunio C Hamano <gitster@pobox.com>
Wed, 22 Apr 2026 22:58:14 +0000 (15:58 -0700)
When "bitmapPseudoMerge.*.pattern" appears more than once for the same
group, `pseudo_merge_config()` frees the old `regex_t *` pointer
but does not call `regfree()` on it first. This leaks whatever internal
state `regcomp()` allocated.

The final cleanup path in `pseudo_merge_group_release()` does call
`regfree()` before `free()`, so only the intermediate replacement is
affected.

Fix this by guarding the replacement with a NULL check and calling
`regfree()` before `free()` when the pointer is non-NULL.

Signed-off-by: Taylor Blau <me@ttaylorr.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
pseudo-merge.c
t/t5333-pseudo-merge-bitmaps.sh

index 75bed04360274486b3d90c38a300011b7b700e46..22b8600d689de52fc8681ffb68e936b9b2e576d0 100644 (file)
@@ -150,7 +150,10 @@ static int pseudo_merge_config(const char *var, const char *value,
        if (!strcmp(key, "pattern")) {
                struct strbuf re = STRBUF_INIT;
 
-               free(group->pattern);
+               if (group->pattern) {
+                       regfree(group->pattern);
+                       free(group->pattern);
+               }
                if (*value != '^')
                        strbuf_addch(&re, '^');
                strbuf_addstr(&re, value);
index 3d0617a2e17b2ca685606d659cee4a799029c23b..382513ca5cc1ba38a82bbe642b47d10dd56d2ba5 100755 (executable)
@@ -663,4 +663,34 @@ test_expect_success 'sampleRate=0 does not cause division by zero' '
        )
 '
 
+test_expect_success 'duplicate pseudo-merge pattern does not leak' '
+       git init pseudo-merge-dup-pattern &&
+       test_when_finished "rm -fr pseudo-merge-dup-pattern" &&
+
+       (
+               cd pseudo-merge-dup-pattern &&
+
+               test_commit_bulk 64 &&
+               tag_everything &&
+               git repack -ad &&
+
+               pack=$(ls .git/objects/pack/pack-*.pack) &&
+
+               # Set the same group'\''s pattern twice. The second
+               # assignment should cleanly release the compiled regex
+               # from the first without leaking.
+               git config bitmapPseudoMerge.test.pattern "refs/tags/" &&
+               git config --add bitmapPseudoMerge.test.pattern "refs/tags/" &&
+               git config bitmapPseudoMerge.test.maxMerges 1 &&
+               git config bitmapPseudoMerge.test.threshold now &&
+               git config bitmapPseudoMerge.test.stableThreshold never &&
+
+               git rev-parse HEAD~63 |
+               test-tool bitmap write "$(basename $pack)" &&
+
+               test_pseudo_merges >merges &&
+               test_line_count = 1 merges
+       )
+'
+
 test_done