git.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 00/20] leak fixes: various simple leak fixes
@ 2022-12-28 18:00 Ævar Arnfjörð Bjarmason
  2022-12-28 18:00 ` [PATCH 01/20] t6021: mark as passing with SANITIZE=leak Ævar Arnfjörð Bjarmason
                   ` (20 more replies)
  0 siblings, 21 replies; 193+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2022-12-28 18:00 UTC (permalink / raw)
  To: git
  Cc: René Scharfe, Junio C Hamano,
	Ævar Arnfjörð Bjarmason

This is a follow-up to the ab/various-leak-fixes topic merged in
9ea1378d046 (Merge branch 'ab/various-leak-fixes', 2022-12-14). Like
that topic this is mixed collection of various leak fixes, all of
which should be simple to review & reason about.

With this series we'll all 32 more tests to the linux-leaks CI job, as
they're now leak-free, out of those 11 are made leak-free in this
topic, the others are already leak-free, but aren't being tested in
CI.

Ævar Arnfjörð Bjarmason (20):
  t6021: mark as passing with SANITIZE=leak
  tests: mark tests as passing with SANITIZE=leak
  bundle.c: don't leak the "args" in the "struct child_process"
  commit-graph: use free() instead of UNLEAK()
  clone: use free() instead of UNLEAK()
  archive.c: call clear_pathspec() in write_archive()
  stash: fix a "struct pathspec" leak
  reset: fix cmd_reset() leaks with a clear_pathspec() call
  name-rev: don't xstrdup() an already dup'd string
  repack: fix leaks on error with "goto cleanup"
  worktree: fix a trivial leak in prune_worktrees()
  http-backend.c: fix cmd_main() memory leak, refactor reg{exec,free}()
  commit-graph: fix a parse_options_concat() leak
  show-branch: free() allocated "head" before return
  builtin/merge.c: always free "struct strbuf msg"
  builtin/merge.c: free "&buf" on "Your local changes..." error
  connected.c: free(new_pack) in check_connected()
  object-file.c: free the "t.tag" in check_tag()
  grep.c: make it easier to extend free_grep_patterns()
  grep API: plug memory leaks by freeing "header_list"

 archive.c                                  |  1 +
 builtin/clone.c                            |  5 +++--
 builtin/commit-graph.c                     | 10 ++++++----
 builtin/merge.c                            |  5 ++++-
 builtin/name-rev.c                         |  3 ++-
 builtin/repack.c                           | 13 +++++++------
 builtin/reset.c                            | 11 ++++++++---
 builtin/show-branch.c                      |  1 +
 builtin/stash.c                            |  9 ++++++---
 builtin/worktree.c                         |  6 +++---
 bundle.c                                   |  6 ++++--
 connected.c                                | 13 +++++++------
 grep.c                                     | 15 ++++++++++-----
 http-backend.c                             |  7 +++++--
 object-file.c                              |  1 +
 t/t0023-crlf-am.sh                         |  1 +
 t/t1301-shared-repo.sh                     |  1 +
 t/t1302-repo-version.sh                    |  1 +
 t/t1304-default-acl.sh                     |  1 +
 t/t1408-packed-refs.sh                     |  1 +
 t/t1410-reflog.sh                          |  1 +
 t/t2401-worktree-prune.sh                  |  1 +
 t/t2406-worktree-repair.sh                 |  1 +
 t/t3210-pack-refs.sh                       |  1 +
 t/t3800-mktag.sh                           |  1 +
 t/t4152-am-subjects.sh                     |  2 ++
 t/t4254-am-corrupt.sh                      |  2 ++
 t/t4256-am-format-flowed.sh                |  1 +
 t/t4257-am-interactive.sh                  |  2 ++
 t/t5001-archive-attr.sh                    |  1 +
 t/t5004-archive-corner-cases.sh            |  2 ++
 t/t5302-pack-index.sh                      |  2 ++
 t/t5317-pack-objects-filter-objects.sh     |  1 +
 t/t5330-no-lazy-fetch-with-commit-graph.sh |  1 +
 t/t5403-post-checkout-hook.sh              |  1 +
 t/t5502-quickfetch.sh                      |  1 +
 t/t5604-clone-reference.sh                 |  1 +
 t/t5613-info-alternate.sh                  |  2 ++
 t/t6011-rev-list-with-bad-commit.sh        |  1 +
 t/t6014-rev-list-all.sh                    |  1 +
 t/t6021-rev-list-exclude-hidden.sh         |  1 +
 t/t6439-merge-co-error-msgs.sh             |  1 +
 t/t7105-reset-patch.sh                     |  2 ++
 t/t7106-reset-unborn-branch.sh             |  2 ++
 t/t7107-reset-pathspec-file.sh             |  1 +
 t/t7403-submodule-sync.sh                  |  1 +
 t/t7701-repack-unpack-unreachable.sh       |  1 +
 47 files changed, 108 insertions(+), 38 deletions(-)

-- 
2.39.0.1153.gb0033028ca9


^ permalink raw reply	[flat|nested] 193+ messages in thread

* [PATCH 01/20] t6021: mark as passing with SANITIZE=leak
  2022-12-28 18:00 [PATCH 00/20] leak fixes: various simple leak fixes Ævar Arnfjörð Bjarmason
@ 2022-12-28 18:00 ` Ævar Arnfjörð Bjarmason
  2022-12-28 18:00 ` [PATCH 02/20] tests: mark tests " Ævar Arnfjörð Bjarmason
                   ` (19 subsequent siblings)
  20 siblings, 0 replies; 193+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2022-12-28 18:00 UTC (permalink / raw)
  To: git
  Cc: René Scharfe, Junio C Hamano,
	Ævar Arnfjörð Bjarmason

This test was recently added in 8c1bc2a71a7 (revision: add new
parameter to exclude hidden refs, 2022-11-17), but wasn't marked as
passing with "SANITIZE=leak".

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 t/t6021-rev-list-exclude-hidden.sh | 1 +
 1 file changed, 1 insertion(+)

diff --git a/t/t6021-rev-list-exclude-hidden.sh b/t/t6021-rev-list-exclude-hidden.sh
index 32b2b094138..11c50b7c0dd 100755
--- a/t/t6021-rev-list-exclude-hidden.sh
+++ b/t/t6021-rev-list-exclude-hidden.sh
@@ -2,6 +2,7 @@
 
 test_description='git rev-list --exclude-hidden test'
 
+TEST_PASSES_SANITIZE_LEAK=true
 . ./test-lib.sh
 
 test_expect_success 'setup' '
-- 
2.39.0.1153.gb0033028ca9


^ permalink raw reply related	[flat|nested] 193+ messages in thread

* [PATCH 02/20] tests: mark tests as passing with SANITIZE=leak
  2022-12-28 18:00 [PATCH 00/20] leak fixes: various simple leak fixes Ævar Arnfjörð Bjarmason
  2022-12-28 18:00 ` [PATCH 01/20] t6021: mark as passing with SANITIZE=leak Ævar Arnfjörð Bjarmason
@ 2022-12-28 18:00 ` Ævar Arnfjörð Bjarmason
  2022-12-28 18:00 ` [PATCH 03/20] bundle.c: don't leak the "args" in the "struct child_process" Ævar Arnfjörð Bjarmason
                   ` (18 subsequent siblings)
  20 siblings, 0 replies; 193+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2022-12-28 18:00 UTC (permalink / raw)
  To: git
  Cc: René Scharfe, Junio C Hamano,
	Ævar Arnfjörð Bjarmason

When the "ab/various-leak-fixes" topic was merged in [1] only
t6021 (which was fixed in the preceding commit) would fail if the
tests were run in the "GIT_TEST_PASSING_SANITIZE_LEAK=check" mode,
i.e. to check whether we marked all leak-free tests with
"TEST_PASSES_SANITIZE_LEAK=true".

Since then we've had various tests starting to pass under
SANITIZE=leak. Let's mark those as passing, this is when they started
to pass, narrowed down with "git bisect":

- t5317-pack-objects-filter-objects.sh: In
  faebba436e6 (list-objects-filter: plug pattern_list leak, 2022-12-01).

- t3210-pack-refs.sh, t5613-info-alternate.sh,
  t7403-submodule-sync.sh: In 189e97bc4ba (diff: remove parseopts member
  from struct diff_options, 2022-12-01).

- t1408-packed-refs.sh: In ab91f6b7c42 (Merge branch
  'rs/diff-parseopts', 2022-12-19).

- t0023-crlf-am.sh, t4152-am-subjects.sh, t4254-am-corrupt.sh,
  t4256-am-format-flowed.sh, t4257-am-interactive.sh,
  t5403-post-checkout-hook.sh: In a658e881c13 (am: don't pass strvec to
  apply_parse_options(), 2022-12-13)

- t1301-shared-repo.sh, t1302-repo-version.sh: In b07a819c05f (reflog:
  clear leftovers in reflog_expiry_cleanup(), 2022-12-13).

- t1304-default-acl.sh, t1410-reflog.sh,
  t5330-no-lazy-fetch-with-commit-graph.sh, t5502-quickfetch.sh,
  t5604-clone-reference.sh, t6014-rev-list-all.sh,
  t7701-repack-unpack-unreachable.sh: In b0c61be3209 (Merge branch
  'rs/reflog-expiry-cleanup', 2022-12-26)

1. 9ea1378d046 (Merge branch 'ab/various-leak-fixes', 2022-12-14)

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 t/t0023-crlf-am.sh                         | 1 +
 t/t1301-shared-repo.sh                     | 1 +
 t/t1302-repo-version.sh                    | 1 +
 t/t1304-default-acl.sh                     | 1 +
 t/t1408-packed-refs.sh                     | 1 +
 t/t1410-reflog.sh                          | 1 +
 t/t3210-pack-refs.sh                       | 1 +
 t/t4152-am-subjects.sh                     | 2 ++
 t/t4254-am-corrupt.sh                      | 2 ++
 t/t4256-am-format-flowed.sh                | 1 +
 t/t4257-am-interactive.sh                  | 2 ++
 t/t5317-pack-objects-filter-objects.sh     | 1 +
 t/t5330-no-lazy-fetch-with-commit-graph.sh | 1 +
 t/t5403-post-checkout-hook.sh              | 1 +
 t/t5502-quickfetch.sh                      | 1 +
 t/t5604-clone-reference.sh                 | 1 +
 t/t5613-info-alternate.sh                  | 2 ++
 t/t6014-rev-list-all.sh                    | 1 +
 t/t7403-submodule-sync.sh                  | 1 +
 t/t7701-repack-unpack-unreachable.sh       | 1 +
 20 files changed, 24 insertions(+)

diff --git a/t/t0023-crlf-am.sh b/t/t0023-crlf-am.sh
index f9bbb91f64e..575805513a3 100755
--- a/t/t0023-crlf-am.sh
+++ b/t/t0023-crlf-am.sh
@@ -2,6 +2,7 @@
 
 test_description='Test am with auto.crlf'
 
+TEST_PASSES_SANITIZE_LEAK=true
 . ./test-lib.sh
 
 cat >patchfile <<\EOF
diff --git a/t/t1301-shared-repo.sh b/t/t1301-shared-repo.sh
index 93a2f91f8a5..a1251f65100 100755
--- a/t/t1301-shared-repo.sh
+++ b/t/t1301-shared-repo.sh
@@ -8,6 +8,7 @@ test_description='Test shared repository initialization'
 GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
 export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
 
+TEST_PASSES_SANITIZE_LEAK=true
 . ./test-lib.sh
 
 # Remove a default ACL from the test dir if possible.
diff --git a/t/t1302-repo-version.sh b/t/t1302-repo-version.sh
index 0acabb6d11b..83c327ac2c8 100755
--- a/t/t1302-repo-version.sh
+++ b/t/t1302-repo-version.sh
@@ -5,6 +5,7 @@
 
 test_description='Test repository version check'
 
+TEST_PASSES_SANITIZE_LEAK=true
 . ./test-lib.sh
 
 test_expect_success 'setup' '
diff --git a/t/t1304-default-acl.sh b/t/t1304-default-acl.sh
index c69ae41306c..31b89dd9693 100755
--- a/t/t1304-default-acl.sh
+++ b/t/t1304-default-acl.sh
@@ -9,6 +9,7 @@ test_description='Test repository with default ACL'
 # => this must come before . ./test-lib.sh
 umask 077
 
+TEST_PASSES_SANITIZE_LEAK=true
 . ./test-lib.sh
 
 # We need an arbitrary other user give permission to using ACLs. root
diff --git a/t/t1408-packed-refs.sh b/t/t1408-packed-refs.sh
index 41ba1f1d7fc..9469c79a585 100755
--- a/t/t1408-packed-refs.sh
+++ b/t/t1408-packed-refs.sh
@@ -5,6 +5,7 @@ test_description='packed-refs entries are covered by loose refs'
 GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
 export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
 
+TEST_PASSES_SANITIZE_LEAK=true
 . ./test-lib.sh
 
 test_expect_success setup '
diff --git a/t/t1410-reflog.sh b/t/t1410-reflog.sh
index aa59954f6c5..6c45965b1e4 100755
--- a/t/t1410-reflog.sh
+++ b/t/t1410-reflog.sh
@@ -7,6 +7,7 @@ test_description='Test prune and reflog expiration'
 GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
 export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
 
+TEST_PASSES_SANITIZE_LEAK=true
 . ./test-lib.sh
 
 check_have () {
diff --git a/t/t3210-pack-refs.sh b/t/t3210-pack-refs.sh
index 577f32dc71f..07a0ff93def 100755
--- a/t/t3210-pack-refs.sh
+++ b/t/t3210-pack-refs.sh
@@ -12,6 +12,7 @@ semantic is still the same.
 GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
 export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
 
+TEST_PASSES_SANITIZE_LEAK=true
 . ./test-lib.sh
 
 test_expect_success 'enable reflogs' '
diff --git a/t/t4152-am-subjects.sh b/t/t4152-am-subjects.sh
index 4c68245acad..9f2edba1f83 100755
--- a/t/t4152-am-subjects.sh
+++ b/t/t4152-am-subjects.sh
@@ -1,6 +1,8 @@
 #!/bin/sh
 
 test_description='test subject preservation with format-patch | am'
+
+TEST_PASSES_SANITIZE_LEAK=true
 . ./test-lib.sh
 
 make_patches() {
diff --git a/t/t4254-am-corrupt.sh b/t/t4254-am-corrupt.sh
index 54be7da1611..45f1d4f95e5 100755
--- a/t/t4254-am-corrupt.sh
+++ b/t/t4254-am-corrupt.sh
@@ -1,6 +1,8 @@
 #!/bin/sh
 
 test_description='git am with corrupt input'
+
+TEST_PASSES_SANITIZE_LEAK=true
 . ./test-lib.sh
 
 make_mbox_with_nul () {
diff --git a/t/t4256-am-format-flowed.sh b/t/t4256-am-format-flowed.sh
index 2369c4e17ad..1015273bc82 100755
--- a/t/t4256-am-format-flowed.sh
+++ b/t/t4256-am-format-flowed.sh
@@ -2,6 +2,7 @@
 
 test_description='test format=flowed support of git am'
 
+TEST_PASSES_SANITIZE_LEAK=true
 . ./test-lib.sh
 
 test_expect_success 'setup' '
diff --git a/t/t4257-am-interactive.sh b/t/t4257-am-interactive.sh
index aed8f4de3d6..f26d7fd2dbd 100755
--- a/t/t4257-am-interactive.sh
+++ b/t/t4257-am-interactive.sh
@@ -1,6 +1,8 @@
 #!/bin/sh
 
 test_description='am --interactive tests'
+
+TEST_PASSES_SANITIZE_LEAK=true
 . ./test-lib.sh
 
 test_expect_success 'set up patches to apply' '
diff --git a/t/t5317-pack-objects-filter-objects.sh b/t/t5317-pack-objects-filter-objects.sh
index 5b707d911b5..b26d476c646 100755
--- a/t/t5317-pack-objects-filter-objects.sh
+++ b/t/t5317-pack-objects-filter-objects.sh
@@ -5,6 +5,7 @@ test_description='git pack-objects using object filtering'
 GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
 export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
 
+TEST_PASSES_SANITIZE_LEAK=true
 . ./test-lib.sh
 
 # Test blob:none filter.
diff --git a/t/t5330-no-lazy-fetch-with-commit-graph.sh b/t/t5330-no-lazy-fetch-with-commit-graph.sh
index 2cc7fd7a476..5eb28f0512d 100755
--- a/t/t5330-no-lazy-fetch-with-commit-graph.sh
+++ b/t/t5330-no-lazy-fetch-with-commit-graph.sh
@@ -2,6 +2,7 @@
 
 test_description='test for no lazy fetch with the commit-graph'
 
+TEST_PASSES_SANITIZE_LEAK=true
 . ./test-lib.sh
 
 test_expect_success 'setup: prepare a repository with a commit' '
diff --git a/t/t5403-post-checkout-hook.sh b/t/t5403-post-checkout-hook.sh
index 978f240cdac..cfaae547398 100755
--- a/t/t5403-post-checkout-hook.sh
+++ b/t/t5403-post-checkout-hook.sh
@@ -7,6 +7,7 @@ test_description='Test the post-checkout hook.'
 GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
 export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
 
+TEST_PASSES_SANITIZE_LEAK=true
 . ./test-lib.sh
 
 test_expect_success setup '
diff --git a/t/t5502-quickfetch.sh b/t/t5502-quickfetch.sh
index b160f8b7fb7..7b3ff21b984 100755
--- a/t/t5502-quickfetch.sh
+++ b/t/t5502-quickfetch.sh
@@ -5,6 +5,7 @@ test_description='test quickfetch from local'
 GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
 export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
 
+TEST_PASSES_SANITIZE_LEAK=true
 . ./test-lib.sh
 
 test_expect_success setup '
diff --git a/t/t5604-clone-reference.sh b/t/t5604-clone-reference.sh
index 2734e37e880..dc86dea1333 100755
--- a/t/t5604-clone-reference.sh
+++ b/t/t5604-clone-reference.sh
@@ -7,6 +7,7 @@ test_description='test clone --reference'
 GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
 export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
 
+TEST_PASSES_SANITIZE_LEAK=true
 . ./test-lib.sh
 
 base_dir=$(pwd)
diff --git a/t/t5613-info-alternate.sh b/t/t5613-info-alternate.sh
index 895f46bb911..7708cbafa98 100755
--- a/t/t5613-info-alternate.sh
+++ b/t/t5613-info-alternate.sh
@@ -4,6 +4,8 @@
 #
 
 test_description='test transitive info/alternate entries'
+
+TEST_PASSES_SANITIZE_LEAK=true
 . ./test-lib.sh
 
 test_expect_success 'preparing first repository' '
diff --git a/t/t6014-rev-list-all.sh b/t/t6014-rev-list-all.sh
index c9bedd29cba..16b8bd1d090 100755
--- a/t/t6014-rev-list-all.sh
+++ b/t/t6014-rev-list-all.sh
@@ -2,6 +2,7 @@
 
 test_description='--all includes detached HEADs'
 
+TEST_PASSES_SANITIZE_LEAK=true
 . ./test-lib.sh
 
 
diff --git a/t/t7403-submodule-sync.sh b/t/t7403-submodule-sync.sh
index ea92ef52a5e..ff09443a0a4 100755
--- a/t/t7403-submodule-sync.sh
+++ b/t/t7403-submodule-sync.sh
@@ -11,6 +11,7 @@ These tests exercise the "git submodule sync" subcommand.
 GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
 export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
 
+TEST_PASSES_SANITIZE_LEAK=true
 . ./test-lib.sh
 
 test_expect_success setup '
diff --git a/t/t7701-repack-unpack-unreachable.sh b/t/t7701-repack-unpack-unreachable.sh
index b7ac4f598a8..ebb267855fe 100755
--- a/t/t7701-repack-unpack-unreachable.sh
+++ b/t/t7701-repack-unpack-unreachable.sh
@@ -5,6 +5,7 @@ test_description='git repack works correctly'
 GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
 export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
 
+TEST_PASSES_SANITIZE_LEAK=true
 . ./test-lib.sh
 
 fsha1=
-- 
2.39.0.1153.gb0033028ca9


^ permalink raw reply related	[flat|nested] 193+ messages in thread

* [PATCH 03/20] bundle.c: don't leak the "args" in the "struct child_process"
  2022-12-28 18:00 [PATCH 00/20] leak fixes: various simple leak fixes Ævar Arnfjörð Bjarmason
  2022-12-28 18:00 ` [PATCH 01/20] t6021: mark as passing with SANITIZE=leak Ævar Arnfjörð Bjarmason
  2022-12-28 18:00 ` [PATCH 02/20] tests: mark tests " Ævar Arnfjörð Bjarmason
@ 2022-12-28 18:00 ` Ævar Arnfjörð Bjarmason
  2022-12-28 18:00 ` [PATCH 04/20] commit-graph: use free() instead of UNLEAK() Ævar Arnfjörð Bjarmason
                   ` (17 subsequent siblings)
  20 siblings, 0 replies; 193+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2022-12-28 18:00 UTC (permalink / raw)
  To: git
  Cc: René Scharfe, Junio C Hamano,
	Ævar Arnfjörð Bjarmason

Fix a leak that's been here since 7366096de9d (bundle API: change
"flags" to be "extra_index_pack_args", 2021-09-05), if can't verify
the bundle we didn't call child_process_clear() to clear the "args".

But rather than doing that let's verify the bundle before we start
preparing the process we're going to spawn, if we get an error we
don't need to push anything to the "args".

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 bundle.c | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/bundle.c b/bundle.c
index 4ef7256aa11..9ebb10a8f72 100644
--- a/bundle.c
+++ b/bundle.c
@@ -627,6 +627,10 @@ int unbundle(struct repository *r, struct bundle_header *header,
 	     enum verify_bundle_flags flags)
 {
 	struct child_process ip = CHILD_PROCESS_INIT;
+
+	if (verify_bundle(r, header, flags))
+		return -1;
+
 	strvec_pushl(&ip.args, "index-pack", "--fix-thin", "--stdin", NULL);
 
 	/* If there is a filter, then we need to create the promisor pack. */
@@ -638,8 +642,6 @@ int unbundle(struct repository *r, struct bundle_header *header,
 		strvec_clear(extra_index_pack_args);
 	}
 
-	if (verify_bundle(r, header, flags))
-		return -1;
 	ip.in = bundle_fd;
 	ip.no_stdout = 1;
 	ip.git_cmd = 1;
-- 
2.39.0.1153.gb0033028ca9


^ permalink raw reply related	[flat|nested] 193+ messages in thread

* [PATCH 04/20] commit-graph: use free() instead of UNLEAK()
  2022-12-28 18:00 [PATCH 00/20] leak fixes: various simple leak fixes Ævar Arnfjörð Bjarmason
                   ` (2 preceding siblings ...)
  2022-12-28 18:00 ` [PATCH 03/20] bundle.c: don't leak the "args" in the "struct child_process" Ævar Arnfjörð Bjarmason
@ 2022-12-28 18:00 ` Ævar Arnfjörð Bjarmason
  2022-12-28 18:10   ` René Scharfe
  2022-12-28 18:00 ` [PATCH 05/20] clone: " Ævar Arnfjörð Bjarmason
                   ` (16 subsequent siblings)
  20 siblings, 1 reply; 193+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2022-12-28 18:00 UTC (permalink / raw)
  To: git
  Cc: René Scharfe, Junio C Hamano,
	Ævar Arnfjörð Bjarmason

In 0bfb48e6723 (builtin/commit-graph.c: UNLEAK variables, 2018-10-03)
this was made to UNLEAK(), but we can just as easily free() the memory
instead.

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 builtin/commit-graph.c | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/builtin/commit-graph.c b/builtin/commit-graph.c
index e8f77f535f3..b6e5726b082 100644
--- a/builtin/commit-graph.c
+++ b/builtin/commit-graph.c
@@ -67,6 +67,7 @@ static int graph_verify(int argc, const char **argv, const char *prefix)
 	int fd;
 	struct stat st;
 	int flags = 0;
+	int ret;
 
 	static struct option builtin_commit_graph_verify_options[] = {
 		OPT_BOOL(0, "shallow", &opts.shallow,
@@ -111,8 +112,9 @@ static int graph_verify(int argc, const char **argv, const char *prefix)
 	if (!graph)
 		return !!open_ok;
 
-	UNLEAK(graph);
-	return verify_commit_graph(the_repository, graph, flags);
+	ret = verify_commit_graph(the_repository, graph, flags);
+	free(graph);
+	return ret;
 }
 
 extern int read_replace_refs;
-- 
2.39.0.1153.gb0033028ca9


^ permalink raw reply related	[flat|nested] 193+ messages in thread

* [PATCH 05/20] clone: use free() instead of UNLEAK()
  2022-12-28 18:00 [PATCH 00/20] leak fixes: various simple leak fixes Ævar Arnfjörð Bjarmason
                   ` (3 preceding siblings ...)
  2022-12-28 18:00 ` [PATCH 04/20] commit-graph: use free() instead of UNLEAK() Ævar Arnfjörð Bjarmason
@ 2022-12-28 18:00 ` Ævar Arnfjörð Bjarmason
  2022-12-28 18:20   ` René Scharfe
  2022-12-29  9:02   ` Junio C Hamano
  2022-12-28 18:00 ` [PATCH 06/20] archive.c: call clear_pathspec() in write_archive() Ævar Arnfjörð Bjarmason
                   ` (15 subsequent siblings)
  20 siblings, 2 replies; 193+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2022-12-28 18:00 UTC (permalink / raw)
  To: git
  Cc: René Scharfe, Junio C Hamano,
	Ævar Arnfjörð Bjarmason

Change an UNLEAK() added in 0c4542738e6 (clone: free or UNLEAK further
pointers when finished, 2021-03-14) to use a "to_free" pattern
instead. In this case the "repo" can be either this absolute_pathdup()
value, or in the "else if" branch seen in the context the the
"argv[0]" argument to "main()".

We can only free() the value in the former case, hence the "to_free"
pattern.

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 builtin/clone.c | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/builtin/clone.c b/builtin/clone.c
index f518bb2dc1f..48156a4f2c2 100644
--- a/builtin/clone.c
+++ b/builtin/clone.c
@@ -892,6 +892,7 @@ int cmd_clone(int argc, const char **argv, const char *prefix)
 	int is_bundle = 0, is_local;
 	int reject_shallow = 0;
 	const char *repo_name, *repo, *work_tree, *git_dir;
+	char *repo_to_free = NULL;
 	char *path = NULL, *dir, *display_repo = NULL;
 	int dest_exists, real_dest_exists = 0;
 	const struct ref *refs, *remote_head;
@@ -949,7 +950,7 @@ int cmd_clone(int argc, const char **argv, const char *prefix)
 	path = get_repo_path(repo_name, &is_bundle);
 	if (path) {
 		FREE_AND_NULL(path);
-		repo = absolute_pathdup(repo_name);
+		repo = repo_to_free = absolute_pathdup(repo_name);
 	} else if (strchr(repo_name, ':')) {
 		repo = repo_name;
 		display_repo = transport_anonymize_url(repo);
@@ -1392,7 +1393,7 @@ int cmd_clone(int argc, const char **argv, const char *prefix)
 	free(unborn_head);
 	free(dir);
 	free(path);
-	UNLEAK(repo);
+	free(repo_to_free);
 	junk_mode = JUNK_LEAVE_ALL;
 
 	transport_ls_refs_options_release(&transport_ls_refs_options);
-- 
2.39.0.1153.gb0033028ca9


^ permalink raw reply related	[flat|nested] 193+ messages in thread

* [PATCH 06/20] archive.c: call clear_pathspec() in write_archive()
  2022-12-28 18:00 [PATCH 00/20] leak fixes: various simple leak fixes Ævar Arnfjörð Bjarmason
                   ` (4 preceding siblings ...)
  2022-12-28 18:00 ` [PATCH 05/20] clone: " Ævar Arnfjörð Bjarmason
@ 2022-12-28 18:00 ` Ævar Arnfjörð Bjarmason
  2022-12-28 18:00 ` [PATCH 07/20] stash: fix a "struct pathspec" leak Ævar Arnfjörð Bjarmason
                   ` (14 subsequent siblings)
  20 siblings, 0 replies; 193+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2022-12-28 18:00 UTC (permalink / raw)
  To: git
  Cc: René Scharfe, Junio C Hamano,
	Ævar Arnfjörð Bjarmason

Plug a leak in the "struct archiver_args", and clear_pathspec() the
"pathspec" member that the "parse_pathspec_arg()" call in this
function populates.

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 archive.c                       | 1 +
 t/t5001-archive-attr.sh         | 1 +
 t/t5004-archive-corner-cases.sh | 2 ++
 3 files changed, 4 insertions(+)

diff --git a/archive.c b/archive.c
index 941495f5d78..a2d813e50db 100644
--- a/archive.c
+++ b/archive.c
@@ -710,6 +710,7 @@ int write_archive(int argc, const char **argv, const char *prefix,
 
 	string_list_clear_func(&args.extra_files, extra_file_info_clear);
 	free(args.refname);
+	clear_pathspec(&args.pathspec);
 
 	return rc;
 }
diff --git a/t/t5001-archive-attr.sh b/t/t5001-archive-attr.sh
index 2f6eef5e372..04d300eeda7 100755
--- a/t/t5001-archive-attr.sh
+++ b/t/t5001-archive-attr.sh
@@ -3,6 +3,7 @@
 test_description='git archive attribute tests'
 
 TEST_CREATE_REPO_NO_TEMPLATE=1
+TEST_PASSES_SANITIZE_LEAK=true
 . ./test-lib.sh
 
 SUBSTFORMAT='%H (%h)%n'
diff --git a/t/t5004-archive-corner-cases.sh b/t/t5004-archive-corner-cases.sh
index ae508e21623..9f2c6da80e8 100755
--- a/t/t5004-archive-corner-cases.sh
+++ b/t/t5004-archive-corner-cases.sh
@@ -1,6 +1,8 @@
 #!/bin/sh
 
 test_description='test corner cases of git-archive'
+
+TEST_PASSES_SANITIZE_LEAK=true
 . ./test-lib.sh
 
 # the 10knuls.tar file is used to test for an empty git generated tar
-- 
2.39.0.1153.gb0033028ca9


^ permalink raw reply related	[flat|nested] 193+ messages in thread

* [PATCH 07/20] stash: fix a "struct pathspec" leak
  2022-12-28 18:00 [PATCH 00/20] leak fixes: various simple leak fixes Ævar Arnfjörð Bjarmason
                   ` (5 preceding siblings ...)
  2022-12-28 18:00 ` [PATCH 06/20] archive.c: call clear_pathspec() in write_archive() Ævar Arnfjörð Bjarmason
@ 2022-12-28 18:00 ` Ævar Arnfjörð Bjarmason
  2022-12-28 19:45   ` René Scharfe
  2022-12-28 18:00 ` [PATCH 08/20] reset: fix cmd_reset() leaks with a clear_pathspec() call Ævar Arnfjörð Bjarmason
                   ` (13 subsequent siblings)
  20 siblings, 1 reply; 193+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2022-12-28 18:00 UTC (permalink / raw)
  To: git
  Cc: René Scharfe, Junio C Hamano,
	Ævar Arnfjörð Bjarmason

Call clear_pathspec() on the pathspec initialized in
push_stash(). Initializing that structure in this way is already done
by a few other callers, and now we have:

	$ git grep -e 'struct pathspec.* = { 0 }' -e memset.pathspec
	add-interactive.c:              struct pathspec ps_selected = { 0 };
	builtin/sparse-checkout.c:              struct pathspec p = { 0 };
	builtin/stash.c:        struct pathspec ps = { 0 };
	pathspec.c:     memset(pathspec, 0, sizeof(*pathspec));
	wt-status.c:                    struct pathspec ps = { 0 };

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 builtin/stash.c | 9 ++++++---
 1 file changed, 6 insertions(+), 3 deletions(-)

diff --git a/builtin/stash.c b/builtin/stash.c
index bb0fd861434..e82fb69c2b3 100644
--- a/builtin/stash.c
+++ b/builtin/stash.c
@@ -1708,7 +1708,7 @@ static int push_stash(int argc, const char **argv, const char *prefix,
 	int pathspec_file_nul = 0;
 	const char *stash_msg = NULL;
 	const char *pathspec_from_file = NULL;
-	struct pathspec ps;
+	struct pathspec ps = { 0 };
 	struct option options[] = {
 		OPT_BOOL('k', "keep-index", &keep_index,
 			 N_("keep index")),
@@ -1727,6 +1727,7 @@ static int push_stash(int argc, const char **argv, const char *prefix,
 		OPT_PATHSPEC_FILE_NUL(&pathspec_file_nul),
 		OPT_END()
 	};
+	int ret;
 
 	if (argc) {
 		force_assume = !strcmp(argv[0], "-p");
@@ -1766,8 +1767,10 @@ static int push_stash(int argc, const char **argv, const char *prefix,
 		die(_("the option '%s' requires '%s'"), "--pathspec-file-nul", "--pathspec-from-file");
 	}
 
-	return do_push_stash(&ps, stash_msg, quiet, keep_index, patch_mode,
-			     include_untracked, only_staged);
+	ret = do_push_stash(&ps, stash_msg, quiet, keep_index, patch_mode,
+			    include_untracked, only_staged);
+	clear_pathspec(&ps);
+	return ret;
 }
 
 static int push_stash_unassumed(int argc, const char **argv, const char *prefix)
-- 
2.39.0.1153.gb0033028ca9


^ permalink raw reply related	[flat|nested] 193+ messages in thread

* [PATCH 08/20] reset: fix cmd_reset() leaks with a clear_pathspec() call
  2022-12-28 18:00 [PATCH 00/20] leak fixes: various simple leak fixes Ævar Arnfjörð Bjarmason
                   ` (6 preceding siblings ...)
  2022-12-28 18:00 ` [PATCH 07/20] stash: fix a "struct pathspec" leak Ævar Arnfjörð Bjarmason
@ 2022-12-28 18:00 ` Ævar Arnfjörð Bjarmason
  2022-12-29  9:12   ` Junio C Hamano
  2022-12-28 18:00 ` [PATCH 09/20] name-rev: don't xstrdup() an already dup'd string Ævar Arnfjörð Bjarmason
                   ` (12 subsequent siblings)
  20 siblings, 1 reply; 193+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2022-12-28 18:00 UTC (permalink / raw)
  To: git
  Cc: René Scharfe, Junio C Hamano,
	Ævar Arnfjörð Bjarmason

Add clear_pathspec() calls to cmd_reset(), including to the codepaths
where we'd return early.

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 builtin/reset.c                | 11 ++++++++---
 t/t7105-reset-patch.sh         |  2 ++
 t/t7106-reset-unborn-branch.sh |  2 ++
 t/t7107-reset-pathspec-file.sh |  1 +
 4 files changed, 13 insertions(+), 3 deletions(-)

diff --git a/builtin/reset.c b/builtin/reset.c
index fea20a9ba0b..e9c10618cd3 100644
--- a/builtin/reset.c
+++ b/builtin/reset.c
@@ -390,7 +390,8 @@ int cmd_reset(int argc, const char **argv, const char *prefix)
 		if (reset_type != NONE)
 			die(_("options '%s' and '%s' cannot be used together"), "--patch", "--{hard,mixed,soft}");
 		trace2_cmd_mode("patch-interactive");
-		return run_add_interactive(rev, "--patch=reset", &pathspec);
+		update_ref_status = run_add_interactive(rev, "--patch=reset", &pathspec);
+		goto cleanup;
 	}
 
 	/* git reset tree [--] paths... can be used to
@@ -439,8 +440,10 @@ int cmd_reset(int argc, const char **argv, const char *prefix)
 				       LOCK_DIE_ON_ERROR);
 		if (reset_type == MIXED) {
 			int flags = quiet ? REFRESH_QUIET : REFRESH_IN_PORCELAIN;
-			if (read_from_tree(&pathspec, &oid, intent_to_add))
-				return 1;
+			if (read_from_tree(&pathspec, &oid, intent_to_add)) {
+				update_ref_status = 1;
+				goto cleanup;
+			}
 			the_index.updated_skipworktree = 1;
 			if (!no_refresh && get_git_work_tree()) {
 				uint64_t t_begin, t_delta_in_ms;
@@ -488,5 +491,7 @@ int cmd_reset(int argc, const char **argv, const char *prefix)
 
 	discard_index(&the_index);
 
+cleanup:
+	clear_pathspec(&pathspec);
 	return update_ref_status;
 }
diff --git a/t/t7105-reset-patch.sh b/t/t7105-reset-patch.sh
index fc2a6cf5c7a..9b46da7aaa7 100755
--- a/t/t7105-reset-patch.sh
+++ b/t/t7105-reset-patch.sh
@@ -1,6 +1,8 @@
 #!/bin/sh
 
 test_description='git reset --patch'
+
+TEST_PASSES_SANITIZE_LEAK=true
 . ./lib-patch-mode.sh
 
 test_expect_success PERL 'setup' '
diff --git a/t/t7106-reset-unborn-branch.sh b/t/t7106-reset-unborn-branch.sh
index ecb85c3b823..a0b67a0b843 100755
--- a/t/t7106-reset-unborn-branch.sh
+++ b/t/t7106-reset-unborn-branch.sh
@@ -1,6 +1,8 @@
 #!/bin/sh
 
 test_description='git reset should work on unborn branch'
+
+TEST_PASSES_SANITIZE_LEAK=true
 . ./test-lib.sh
 
 test_expect_success 'setup' '
diff --git a/t/t7107-reset-pathspec-file.sh b/t/t7107-reset-pathspec-file.sh
index 523efbecde1..af5ea406db3 100755
--- a/t/t7107-reset-pathspec-file.sh
+++ b/t/t7107-reset-pathspec-file.sh
@@ -2,6 +2,7 @@
 
 test_description='reset --pathspec-from-file'
 
+TEST_PASSES_SANITIZE_LEAK=true
 . ./test-lib.sh
 
 test_tick
-- 
2.39.0.1153.gb0033028ca9


^ permalink raw reply related	[flat|nested] 193+ messages in thread

* [PATCH 09/20] name-rev: don't xstrdup() an already dup'd string
  2022-12-28 18:00 [PATCH 00/20] leak fixes: various simple leak fixes Ævar Arnfjörð Bjarmason
                   ` (7 preceding siblings ...)
  2022-12-28 18:00 ` [PATCH 08/20] reset: fix cmd_reset() leaks with a clear_pathspec() call Ævar Arnfjörð Bjarmason
@ 2022-12-28 18:00 ` Ævar Arnfjörð Bjarmason
  2022-12-28 20:31   ` René Scharfe
  2022-12-28 18:00 ` [PATCH 10/20] repack: fix leaks on error with "goto cleanup" Ævar Arnfjörð Bjarmason
                   ` (11 subsequent siblings)
  20 siblings, 1 reply; 193+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2022-12-28 18:00 UTC (permalink / raw)
  To: git
  Cc: René Scharfe, Junio C Hamano,
	Ævar Arnfjörð Bjarmason

When "add_to_tip_table()" is called with a non-zero
"shorten_unambiguous" we always return an xstrdup()'d string, which
we'd then xstrdup() again, leaking memory. See [1] and [2] for how
this leak came about.

1. 98c5c4ad015 (name-rev: allow to specify a subpath for --refs
   option, 2013-06-18)
2. b23e0b9353e (name-rev: allow converting the exact object name at
   the tip of a ref, 2013-07-07)

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 builtin/name-rev.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/builtin/name-rev.c b/builtin/name-rev.c
index 15535e914a6..24f4438eb01 100644
--- a/builtin/name-rev.c
+++ b/builtin/name-rev.c
@@ -313,7 +313,8 @@ static void add_to_tip_table(const struct object_id *oid, const char *refname,
 
 	ALLOC_GROW(tip_table.table, tip_table.nr + 1, tip_table.alloc);
 	oidcpy(&tip_table.table[tip_table.nr].oid, oid);
-	tip_table.table[tip_table.nr].refname = xstrdup(refname);
+	tip_table.table[tip_table.nr].refname = shorten_unambiguous ? refname :
+		xstrdup(refname);
 	tip_table.table[tip_table.nr].commit = commit;
 	tip_table.table[tip_table.nr].taggerdate = taggerdate;
 	tip_table.table[tip_table.nr].from_tag = from_tag;
-- 
2.39.0.1153.gb0033028ca9


^ permalink raw reply related	[flat|nested] 193+ messages in thread

* [PATCH 10/20] repack: fix leaks on error with "goto cleanup"
  2022-12-28 18:00 [PATCH 00/20] leak fixes: various simple leak fixes Ævar Arnfjörð Bjarmason
                   ` (8 preceding siblings ...)
  2022-12-28 18:00 ` [PATCH 09/20] name-rev: don't xstrdup() an already dup'd string Ævar Arnfjörð Bjarmason
@ 2022-12-28 18:00 ` Ævar Arnfjörð Bjarmason
  2022-12-28 18:00 ` [PATCH 11/20] worktree: fix a trivial leak in prune_worktrees() Ævar Arnfjörð Bjarmason
                   ` (10 subsequent siblings)
  20 siblings, 0 replies; 193+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2022-12-28 18:00 UTC (permalink / raw)
  To: git
  Cc: René Scharfe, Junio C Hamano,
	Ævar Arnfjörð Bjarmason

Change cmd_repack() to "goto cleanup" rather than "return ret" on
error, when we returned we'd potentially skip cleaning up the
string_lists and other data we'd allocated in this function.

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 builtin/repack.c                    | 13 +++++++------
 t/t6011-rev-list-with-bad-commit.sh |  1 +
 2 files changed, 8 insertions(+), 6 deletions(-)

diff --git a/builtin/repack.c b/builtin/repack.c
index c1402ad038f..f6493795318 100644
--- a/builtin/repack.c
+++ b/builtin/repack.c
@@ -948,7 +948,7 @@ int cmd_repack(int argc, const char **argv, const char *prefix)
 
 	ret = start_command(&cmd);
 	if (ret)
-		return ret;
+		goto cleanup;
 
 	if (geometry) {
 		FILE *in = xfdopen(cmd.in, "w");
@@ -977,7 +977,7 @@ int cmd_repack(int argc, const char **argv, const char *prefix)
 	fclose(out);
 	ret = finish_command(&cmd);
 	if (ret)
-		return ret;
+		goto cleanup;
 
 	if (!names.nr && !po_args.quiet)
 		printf_ln(_("Nothing new to pack."));
@@ -1007,7 +1007,7 @@ int cmd_repack(int argc, const char **argv, const char *prefix)
 				       &existing_nonkept_packs,
 				       &existing_kept_packs);
 		if (ret)
-			return ret;
+			goto cleanup;
 
 		if (delete_redundant && expire_to) {
 			/*
@@ -1039,7 +1039,7 @@ int cmd_repack(int argc, const char **argv, const char *prefix)
 					       &existing_nonkept_packs,
 					       &existing_kept_packs);
 			if (ret)
-				return ret;
+				goto cleanup;
 		}
 	}
 
@@ -1115,7 +1115,7 @@ int cmd_repack(int argc, const char **argv, const char *prefix)
 		string_list_clear(&include, 0);
 
 		if (ret)
-			return ret;
+			goto cleanup;
 	}
 
 	reprepare_packed_git(the_repository);
@@ -1172,10 +1172,11 @@ int cmd_repack(int argc, const char **argv, const char *prefix)
 		write_midx_file(get_object_directory(), NULL, NULL, flags);
 	}
 
+cleanup:
 	string_list_clear(&names, 1);
 	string_list_clear(&existing_nonkept_packs, 0);
 	string_list_clear(&existing_kept_packs, 0);
 	clear_pack_geometry(geometry);
 
-	return 0;
+	return ret;
 }
diff --git a/t/t6011-rev-list-with-bad-commit.sh b/t/t6011-rev-list-with-bad-commit.sh
index bad02cf5b83..b2e422cf0f7 100755
--- a/t/t6011-rev-list-with-bad-commit.sh
+++ b/t/t6011-rev-list-with-bad-commit.sh
@@ -2,6 +2,7 @@
 
 test_description='git rev-list should notice bad commits'
 
+TEST_PASSES_SANITIZE_LEAK=true
 . ./test-lib.sh
 
 # Note:
-- 
2.39.0.1153.gb0033028ca9


^ permalink raw reply related	[flat|nested] 193+ messages in thread

* [PATCH 11/20] worktree: fix a trivial leak in prune_worktrees()
  2022-12-28 18:00 [PATCH 00/20] leak fixes: various simple leak fixes Ævar Arnfjörð Bjarmason
                   ` (9 preceding siblings ...)
  2022-12-28 18:00 ` [PATCH 10/20] repack: fix leaks on error with "goto cleanup" Ævar Arnfjörð Bjarmason
@ 2022-12-28 18:00 ` Ævar Arnfjörð Bjarmason
  2022-12-28 20:53   ` René Scharfe
  2022-12-28 18:00 ` [PATCH 12/20] http-backend.c: fix cmd_main() memory leak, refactor reg{exec,free}() Ævar Arnfjörð Bjarmason
                   ` (9 subsequent siblings)
  20 siblings, 1 reply; 193+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2022-12-28 18:00 UTC (permalink / raw)
  To: git
  Cc: René Scharfe, Junio C Hamano,
	Ævar Arnfjörð Bjarmason

We were leaking both the "struct strbuf" in prune_worktrees(), as well
as the "path" we got from should_prune_worktree(). Since these were
the only two uses of the "struct string_list" let's change it to a
"DUP" and push these to it with "string_list_append_nodup()".

For the string_list_append_nodup() we could also string_list_append()
the main_path.buf, and then strbuf_release(&main_path) right away. But
doing it this way avoids an allocation, as we already have the "struct
strbuf" prepared for appending to "kept".

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 builtin/worktree.c         | 6 +++---
 t/t2401-worktree-prune.sh  | 1 +
 t/t2406-worktree-repair.sh | 1 +
 3 files changed, 5 insertions(+), 3 deletions(-)

diff --git a/builtin/worktree.c b/builtin/worktree.c
index 591d659faea..865ce9be22b 100644
--- a/builtin/worktree.c
+++ b/builtin/worktree.c
@@ -173,7 +173,7 @@ static void prune_worktrees(void)
 {
 	struct strbuf reason = STRBUF_INIT;
 	struct strbuf main_path = STRBUF_INIT;
-	struct string_list kept = STRING_LIST_INIT_NODUP;
+	struct string_list kept = STRING_LIST_INIT_DUP;
 	DIR *dir = opendir(git_path("worktrees"));
 	struct dirent *d;
 	if (!dir)
@@ -184,14 +184,14 @@ static void prune_worktrees(void)
 		if (should_prune_worktree(d->d_name, &reason, &path, expire))
 			prune_worktree(d->d_name, reason.buf);
 		else if (path)
-			string_list_append(&kept, path)->util = xstrdup(d->d_name);
+			string_list_append_nodup(&kept, path)->util = xstrdup(d->d_name);
 	}
 	closedir(dir);
 
 	strbuf_add_absolute_path(&main_path, get_git_common_dir());
 	/* massage main worktree absolute path to match 'gitdir' content */
 	strbuf_strip_suffix(&main_path, "/.");
-	string_list_append(&kept, strbuf_detach(&main_path, NULL));
+	string_list_append_nodup(&kept, strbuf_detach(&main_path, NULL));
 	prune_dups(&kept);
 	string_list_clear(&kept, 1);
 
diff --git a/t/t2401-worktree-prune.sh b/t/t2401-worktree-prune.sh
index 3d28c7f06b2..568a47ec426 100755
--- a/t/t2401-worktree-prune.sh
+++ b/t/t2401-worktree-prune.sh
@@ -5,6 +5,7 @@ test_description='prune $GIT_DIR/worktrees'
 GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
 export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
 
+TEST_PASSES_SANITIZE_LEAK=true
 . ./test-lib.sh
 
 test_expect_success initialize '
diff --git a/t/t2406-worktree-repair.sh b/t/t2406-worktree-repair.sh
index 5c44453e1c1..8970780efcc 100755
--- a/t/t2406-worktree-repair.sh
+++ b/t/t2406-worktree-repair.sh
@@ -2,6 +2,7 @@
 
 test_description='test git worktree repair'
 
+TEST_PASSES_SANITIZE_LEAK=true
 . ./test-lib.sh
 
 test_expect_success setup '
-- 
2.39.0.1153.gb0033028ca9


^ permalink raw reply related	[flat|nested] 193+ messages in thread

* [PATCH 12/20] http-backend.c: fix cmd_main() memory leak, refactor reg{exec,free}()
  2022-12-28 18:00 [PATCH 00/20] leak fixes: various simple leak fixes Ævar Arnfjörð Bjarmason
                   ` (10 preceding siblings ...)
  2022-12-28 18:00 ` [PATCH 11/20] worktree: fix a trivial leak in prune_worktrees() Ævar Arnfjörð Bjarmason
@ 2022-12-28 18:00 ` Ævar Arnfjörð Bjarmason
  2022-12-28 21:37   ` René Scharfe
  2022-12-28 18:00 ` [PATCH 13/20] commit-graph: fix a parse_options_concat() leak Ævar Arnfjörð Bjarmason
                   ` (8 subsequent siblings)
  20 siblings, 1 reply; 193+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2022-12-28 18:00 UTC (permalink / raw)
  To: git
  Cc: René Scharfe, Junio C Hamano,
	Ævar Arnfjörð Bjarmason

Fix a memory leak that's been with us ever since
2f4038ab337 (Git-aware CGI to provide dumb HTTP transport,
2009-10-30). In this case we're not calling regerror() after a failed
regexec(), and don't otherwise use "re" afterwards.

We can therefore simplify this code by calling regfree() right after
the regexec(). An alternative fix would be to add a regfree() to both
the "return" and "break" path in this for-loop.

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 http-backend.c | 7 +++++--
 1 file changed, 5 insertions(+), 2 deletions(-)

diff --git a/http-backend.c b/http-backend.c
index 6eb3b2fe51c..9bb63c458b1 100644
--- a/http-backend.c
+++ b/http-backend.c
@@ -759,10 +759,14 @@ int cmd_main(int argc, const char **argv)
 		struct service_cmd *c = &services[i];
 		regex_t re;
 		regmatch_t out[1];
+		int ret;
 
 		if (regcomp(&re, c->pattern, REG_EXTENDED))
 			die("Bogus regex in service table: %s", c->pattern);
-		if (!regexec(&re, dir, 1, out, 0)) {
+		ret = regexec(&re, dir, 1, out, 0);
+		regfree(&re);
+
+		if (!ret) {
 			size_t n;
 
 			if (strcmp(method, c->method))
@@ -774,7 +778,6 @@ int cmd_main(int argc, const char **argv)
 			dir[out[0].rm_so] = 0;
 			break;
 		}
-		regfree(&re);
 	}
 
 	if (!cmd)
-- 
2.39.0.1153.gb0033028ca9


^ permalink raw reply related	[flat|nested] 193+ messages in thread

* [PATCH 13/20] commit-graph: fix a parse_options_concat() leak
  2022-12-28 18:00 [PATCH 00/20] leak fixes: various simple leak fixes Ævar Arnfjörð Bjarmason
                   ` (11 preceding siblings ...)
  2022-12-28 18:00 ` [PATCH 12/20] http-backend.c: fix cmd_main() memory leak, refactor reg{exec,free}() Ævar Arnfjörð Bjarmason
@ 2022-12-28 18:00 ` Ævar Arnfjörð Bjarmason
  2022-12-28 18:00 ` [PATCH 14/20] show-branch: free() allocated "head" before return Ævar Arnfjörð Bjarmason
                   ` (7 subsequent siblings)
  20 siblings, 0 replies; 193+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2022-12-28 18:00 UTC (permalink / raw)
  To: git
  Cc: René Scharfe, Junio C Hamano,
	Ævar Arnfjörð Bjarmason

When the parse_options_concat() was added to this file in
84e4484f128 (commit-graph: use parse_options_concat(), 2021-08-23) we
wouldn't free() it if we returned early in these cases.

Since "result" is 0 by default we can "goto cleanup" in both cases,
and only need to set "result" if write_commit_graph_reachable() fails.

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 builtin/commit-graph.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/builtin/commit-graph.c b/builtin/commit-graph.c
index b6e5726b082..c76faffde4b 100644
--- a/builtin/commit-graph.c
+++ b/builtin/commit-graph.c
@@ -269,8 +269,8 @@ static int graph_write(int argc, const char **argv, const char *prefix)
 
 	if (opts.reachable) {
 		if (write_commit_graph_reachable(odb, flags, &write_opts))
-			return 1;
-		return 0;
+			result = 1;
+		goto cleanup;
 	}
 
 	if (opts.stdin_packs) {
-- 
2.39.0.1153.gb0033028ca9


^ permalink raw reply related	[flat|nested] 193+ messages in thread

* [PATCH 14/20] show-branch: free() allocated "head" before return
  2022-12-28 18:00 [PATCH 00/20] leak fixes: various simple leak fixes Ævar Arnfjörð Bjarmason
                   ` (12 preceding siblings ...)
  2022-12-28 18:00 ` [PATCH 13/20] commit-graph: fix a parse_options_concat() leak Ævar Arnfjörð Bjarmason
@ 2022-12-28 18:00 ` Ævar Arnfjörð Bjarmason
  2022-12-28 18:00 ` [PATCH 15/20] builtin/merge.c: always free "struct strbuf msg" Ævar Arnfjörð Bjarmason
                   ` (6 subsequent siblings)
  20 siblings, 0 replies; 193+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2022-12-28 18:00 UTC (permalink / raw)
  To: git
  Cc: René Scharfe, Junio C Hamano,
	Ævar Arnfjörð Bjarmason

Stop leaking the "head" variable, which we've been leaking since it
was originally added in [1], and in its current form since [2]

1. ed378ec7e85 (Make ref resolution saner, 2006-09-11)
2. d9e557a320b (show-branch: store resolved head in heap buffer,
   2017-02-14).

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 builtin/show-branch.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/builtin/show-branch.c b/builtin/show-branch.c
index c013abaf942..358ac3e519a 100644
--- a/builtin/show-branch.c
+++ b/builtin/show-branch.c
@@ -956,5 +956,6 @@ int cmd_show_branch(int ac, const char **av, const char *prefix)
 		if (shown_merge_point && --extra < 0)
 			break;
 	}
+	free(head);
 	return 0;
 }
-- 
2.39.0.1153.gb0033028ca9


^ permalink raw reply related	[flat|nested] 193+ messages in thread

* [PATCH 15/20] builtin/merge.c: always free "struct strbuf msg"
  2022-12-28 18:00 [PATCH 00/20] leak fixes: various simple leak fixes Ævar Arnfjörð Bjarmason
                   ` (13 preceding siblings ...)
  2022-12-28 18:00 ` [PATCH 14/20] show-branch: free() allocated "head" before return Ævar Arnfjörð Bjarmason
@ 2022-12-28 18:00 ` Ævar Arnfjörð Bjarmason
  2022-12-28 22:06   ` René Scharfe
  2022-12-28 18:00 ` [PATCH 16/20] builtin/merge.c: free "&buf" on "Your local changes..." error Ævar Arnfjörð Bjarmason
                   ` (5 subsequent siblings)
  20 siblings, 1 reply; 193+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2022-12-28 18:00 UTC (permalink / raw)
  To: git
  Cc: René Scharfe, Junio C Hamano,
	Ævar Arnfjörð Bjarmason

Follow-up 465028e0e25 (merge: add missing strbuf_release(),
2021-10-07) and free "&msg" also when we'd "goto done" from the scope
it's allocated in.

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 builtin/merge.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/builtin/merge.c b/builtin/merge.c
index 0f093f2a4f2..8f78f326dbe 100644
--- a/builtin/merge.c
+++ b/builtin/merge.c
@@ -1577,6 +1577,7 @@ int cmd_merge(int argc, const char **argv, const char *prefix)
 		commit = remoteheads->item;
 		if (!commit) {
 			ret = 1;
+			strbuf_release(&msg);
 			goto done;
 		}
 
@@ -1589,6 +1590,7 @@ int cmd_merge(int argc, const char **argv, const char *prefix)
 					  overwrite_ignore)) {
 			apply_autostash(git_path_merge_autostash(the_repository));
 			ret = 1;
+			strbuf_release(&msg);
 			goto done;
 		}
 
-- 
2.39.0.1153.gb0033028ca9


^ permalink raw reply related	[flat|nested] 193+ messages in thread

* [PATCH 16/20] builtin/merge.c: free "&buf" on "Your local changes..." error
  2022-12-28 18:00 [PATCH 00/20] leak fixes: various simple leak fixes Ævar Arnfjörð Bjarmason
                   ` (14 preceding siblings ...)
  2022-12-28 18:00 ` [PATCH 15/20] builtin/merge.c: always free "struct strbuf msg" Ævar Arnfjörð Bjarmason
@ 2022-12-28 18:00 ` Ævar Arnfjörð Bjarmason
  2022-12-28 22:13   ` René Scharfe
  2022-12-28 18:00 ` [PATCH 17/20] connected.c: free(new_pack) in check_connected() Ævar Arnfjörð Bjarmason
                   ` (4 subsequent siblings)
  20 siblings, 1 reply; 193+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2022-12-28 18:00 UTC (permalink / raw)
  To: git
  Cc: René Scharfe, Junio C Hamano,
	Ævar Arnfjörð Bjarmason

Plug a memory leak introduced in [1], since that change didn't follow
the "goto done" pattern introduced in [2] we'd leak the "&buf" memory.

1. e4cdfe84a0d (merge: abort if index does not match HEAD for trivial
   merges, 2022-07-23)
2. d5a35c114ab (Copy resolve_ref() return value for longer use,
   2011-11-13)

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 builtin/merge.c                | 3 ++-
 t/t6439-merge-co-error-msgs.sh | 1 +
 2 files changed, 3 insertions(+), 1 deletion(-)

diff --git a/builtin/merge.c b/builtin/merge.c
index 8f78f326dbe..e29b456f92c 100644
--- a/builtin/merge.c
+++ b/builtin/merge.c
@@ -1623,7 +1623,8 @@ int cmd_merge(int argc, const char **argv, const char *prefix)
 				error(_("Your local changes to the following files would be overwritten by merge:\n  %s"),
 				      sb.buf);
 				strbuf_release(&sb);
-				return 2;
+				ret = 2;
+				goto done;
 			}
 
 			/* See if it is really trivial. */
diff --git a/t/t6439-merge-co-error-msgs.sh b/t/t6439-merge-co-error-msgs.sh
index 52cf0c87690..0cbec57cdab 100755
--- a/t/t6439-merge-co-error-msgs.sh
+++ b/t/t6439-merge-co-error-msgs.sh
@@ -5,6 +5,7 @@ test_description='unpack-trees error messages'
 GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
 export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
 
+TEST_PASSES_SANITIZE_LEAK=true
 . ./test-lib.sh
 
 
-- 
2.39.0.1153.gb0033028ca9


^ permalink raw reply related	[flat|nested] 193+ messages in thread

* [PATCH 17/20] connected.c: free(new_pack) in check_connected()
  2022-12-28 18:00 [PATCH 00/20] leak fixes: various simple leak fixes Ævar Arnfjörð Bjarmason
                   ` (15 preceding siblings ...)
  2022-12-28 18:00 ` [PATCH 16/20] builtin/merge.c: free "&buf" on "Your local changes..." error Ævar Arnfjörð Bjarmason
@ 2022-12-28 18:00 ` Ævar Arnfjörð Bjarmason
  2022-12-28 18:00 ` [PATCH 18/20] object-file.c: free the "t.tag" in check_tag() Ævar Arnfjörð Bjarmason
                   ` (3 subsequent siblings)
  20 siblings, 0 replies; 193+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2022-12-28 18:00 UTC (permalink / raw)
  To: git
  Cc: René Scharfe, Junio C Hamano,
	Ævar Arnfjörð Bjarmason

Fix a memory leak that's been with us since this code was introduced
in c6807a40dcd (clone: open a shortcut for connectivity check,
2013-05-26). We'd never free() the "new_pack" that we'd potentially
allocate. Since it's initialized to "NULL" it's safe to call free()
here unconditionally.

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 connected.c | 13 +++++++------
 1 file changed, 7 insertions(+), 6 deletions(-)

diff --git a/connected.c b/connected.c
index b90fd61790c..e4d404e10b2 100644
--- a/connected.c
+++ b/connected.c
@@ -38,7 +38,7 @@ int check_connected(oid_iterate_fn fn, void *cb_data,
 	if (!oid) {
 		if (opt->err_fd)
 			close(opt->err_fd);
-		return err;
+		goto cleanup;
 	}
 
 	if (transport && transport->smart_options &&
@@ -85,8 +85,7 @@ int check_connected(oid_iterate_fn fn, void *cb_data,
 promisor_pack_found:
 			;
 		} while ((oid = fn(cb_data)) != NULL);
-		free(new_pack);
-		return 0;
+		goto cleanup;
 	}
 
 no_promisor_pack_found:
@@ -123,8 +122,8 @@ int check_connected(oid_iterate_fn fn, void *cb_data,
 		rev_list.no_stderr = opt->quiet;
 
 	if (start_command(&rev_list)) {
-		free(new_pack);
-		return error(_("Could not run 'git rev-list'"));
+		err = error(_("Could not run 'git rev-list'"));
+		goto cleanup;
 	}
 
 	sigchain_push(SIGPIPE, SIG_IGN);
@@ -157,6 +156,8 @@ int check_connected(oid_iterate_fn fn, void *cb_data,
 		err = error_errno(_("failed to close rev-list's stdin"));
 
 	sigchain_pop(SIGPIPE);
+	err = finish_command(&rev_list) || err;
+cleanup:
 	free(new_pack);
-	return finish_command(&rev_list) || err;
+	return err;
 }
-- 
2.39.0.1153.gb0033028ca9


^ permalink raw reply related	[flat|nested] 193+ messages in thread

* [PATCH 18/20] object-file.c: free the "t.tag" in check_tag()
  2022-12-28 18:00 [PATCH 00/20] leak fixes: various simple leak fixes Ævar Arnfjörð Bjarmason
                   ` (16 preceding siblings ...)
  2022-12-28 18:00 ` [PATCH 17/20] connected.c: free(new_pack) in check_connected() Ævar Arnfjörð Bjarmason
@ 2022-12-28 18:00 ` Ævar Arnfjörð Bjarmason
  2022-12-28 22:25   ` René Scharfe
  2022-12-28 18:00 ` [PATCH 19/20] grep.c: make it easier to extend free_grep_patterns() Ævar Arnfjörð Bjarmason
                   ` (2 subsequent siblings)
  20 siblings, 1 reply; 193+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2022-12-28 18:00 UTC (permalink / raw)
  To: git
  Cc: René Scharfe, Junio C Hamano,
	Ævar Arnfjörð Bjarmason

Fix a memory leak that's been with us ever since c879daa2372 (Make
hash-object more robust against malformed objects, 2011-02-05). With
"HASH_FORMAT_CHECK" (used by "hash-object" and "replace") we'll parse
tags into a throwaway variable on the stack, but weren't freeing the
"item->tag" we might malloc() when doing so.

Mark the tests that now pass in their entirety as passing under
"SANITIZE=leak", which means we'll test them as part of the
"linux-leaks" CI job.

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 object-file.c         | 1 +
 t/t3800-mktag.sh      | 1 +
 t/t5302-pack-index.sh | 2 ++
 3 files changed, 4 insertions(+)

diff --git a/object-file.c b/object-file.c
index c1b71c28347..36ed6c3122c 100644
--- a/object-file.c
+++ b/object-file.c
@@ -2331,6 +2331,7 @@ static void check_tag(const void *buf, size_t size)
 	memset(&t, 0, sizeof(t));
 	if (parse_tag_buffer(the_repository, &t, buf, size))
 		die(_("corrupt tag"));
+	free(t.tag);
 }
 
 static int index_mem(struct index_state *istate,
diff --git a/t/t3800-mktag.sh b/t/t3800-mktag.sh
index e3cf0ffbe59..d3e428ff46e 100755
--- a/t/t3800-mktag.sh
+++ b/t/t3800-mktag.sh
@@ -4,6 +4,7 @@
 
 test_description='git mktag: tag object verify test'
 
+TEST_PASSES_SANITIZE_LEAK=true
 . ./test-lib.sh
 
 ###########################################################
diff --git a/t/t5302-pack-index.sh b/t/t5302-pack-index.sh
index b0095ab41d3..54b11f81c63 100755
--- a/t/t5302-pack-index.sh
+++ b/t/t5302-pack-index.sh
@@ -4,6 +4,8 @@
 #
 
 test_description='pack index with 64-bit offsets and object CRC'
+
+TEST_PASSES_SANITIZE_LEAK=true
 . ./test-lib.sh
 
 test_expect_success 'setup' '
-- 
2.39.0.1153.gb0033028ca9


^ permalink raw reply related	[flat|nested] 193+ messages in thread

* [PATCH 19/20] grep.c: make it easier to extend free_grep_patterns()
  2022-12-28 18:00 [PATCH 00/20] leak fixes: various simple leak fixes Ævar Arnfjörð Bjarmason
                   ` (17 preceding siblings ...)
  2022-12-28 18:00 ` [PATCH 18/20] object-file.c: free the "t.tag" in check_tag() Ævar Arnfjörð Bjarmason
@ 2022-12-28 18:00 ` Ævar Arnfjörð Bjarmason
  2022-12-28 18:00 ` [PATCH 20/20] grep API: plug memory leaks by freeing "header_list" Ævar Arnfjörð Bjarmason
  2022-12-30  2:18 ` [PATCH v2 00/20] leak fixes: various simple leak fixes Ævar Arnfjörð Bjarmason
  20 siblings, 0 replies; 193+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2022-12-28 18:00 UTC (permalink / raw)
  To: git
  Cc: René Scharfe, Junio C Hamano,
	Ævar Arnfjörð Bjarmason

Before db84376f981 (grep.c: remove "extended" in favor of
"pattern_expression", fix segfault, 2022-10-11) the pattern here was:

	if (!x)
		return;
	free(y);

But after the cleanup in db84376f981 (which was a narrow segfault fix,
and thus avoided refactoring this) we ended up with:

	if (!x)
		return;
	free(x);

Let's instead do:

	if (x)
		free(x);

This doesn't matter for now, but makes the free_grep_patterns() easier
to reason about, as we don't have to wonder why we're doing an early
"return" if and when we add free()-ing of any members that come after
"pattern_expression" in the "struct grep_opt".

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 grep.c | 5 ++---
 1 file changed, 2 insertions(+), 3 deletions(-)

diff --git a/grep.c b/grep.c
index 06eed694936..ca75514f8f6 100644
--- a/grep.c
+++ b/grep.c
@@ -791,9 +791,8 @@ void free_grep_patterns(struct grep_opt *opt)
 		free(p);
 	}
 
-	if (!opt->pattern_expression)
-		return;
-	free_pattern_expr(opt->pattern_expression);
+	if (opt->pattern_expression)
+		free_pattern_expr(opt->pattern_expression);
 }
 
 static const char *end_of_line(const char *cp, unsigned long *left)
-- 
2.39.0.1153.gb0033028ca9


^ permalink raw reply related	[flat|nested] 193+ messages in thread

* [PATCH 20/20] grep API: plug memory leaks by freeing "header_list"
  2022-12-28 18:00 [PATCH 00/20] leak fixes: various simple leak fixes Ævar Arnfjörð Bjarmason
                   ` (18 preceding siblings ...)
  2022-12-28 18:00 ` [PATCH 19/20] grep.c: make it easier to extend free_grep_patterns() Ævar Arnfjörð Bjarmason
@ 2022-12-28 18:00 ` Ævar Arnfjörð Bjarmason
  2022-12-28 19:36   ` Eric Sunshine
  2022-12-28 22:50   ` René Scharfe
  2022-12-30  2:18 ` [PATCH v2 00/20] leak fixes: various simple leak fixes Ævar Arnfjörð Bjarmason
  20 siblings, 2 replies; 193+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2022-12-28 18:00 UTC (permalink / raw)
  To: git
  Cc: René Scharfe, Junio C Hamano,
	Ævar Arnfjörð Bjarmason

When the "header_list" struct member was added in [1] it wasn't made
to free the list using loop added for the adjacent "pattern_list"
member, see [2] for when we started freeing it.

Let's start doing o by splitting up the loop in free_grep_patterns()
into a utility function. This makes e.g. this command leak-free when
run on git.git:

	./git -P log -1 --color=always --author=A origin/master

1. 80235ba79ef ("log --author=me --grep=it" should find intersection,
   not union, 2010-01-17)
2. b48fb5b6a95 (grep: free expressions and patterns when done.,
   2006-09-27)

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 grep.c | 10 ++++++++--
 1 file changed, 8 insertions(+), 2 deletions(-)

diff --git a/grep.c b/grep.c
index ca75514f8f6..c908535e0d8 100644
--- a/grep.c
+++ b/grep.c
@@ -769,11 +769,11 @@ static void free_pattern_expr(struct grep_expr *x)
 	free(x);
 }
 
-void free_grep_patterns(struct grep_opt *opt)
+static void free_grep_pat(struct grep_pat *pattern)
 {
 	struct grep_pat *p, *n;
 
-	for (p = opt->pattern_list; p; p = n) {
+	for (p = pattern; p; p = n) {
 		n = p->next;
 		switch (p->token) {
 		case GREP_PATTERN: /* atom */
@@ -790,6 +790,12 @@ void free_grep_patterns(struct grep_opt *opt)
 		}
 		free(p);
 	}
+}
+
+void free_grep_patterns(struct grep_opt *opt)
+{
+	free_grep_pat(opt->pattern_list);
+	free_grep_pat(opt->header_list);
 
 	if (opt->pattern_expression)
 		free_pattern_expr(opt->pattern_expression);
-- 
2.39.0.1153.gb0033028ca9


^ permalink raw reply related	[flat|nested] 193+ messages in thread

* Re: [PATCH 04/20] commit-graph: use free() instead of UNLEAK()
  2022-12-28 18:00 ` [PATCH 04/20] commit-graph: use free() instead of UNLEAK() Ævar Arnfjörð Bjarmason
@ 2022-12-28 18:10   ` René Scharfe
  0 siblings, 0 replies; 193+ messages in thread
From: René Scharfe @ 2022-12-28 18:10 UTC (permalink / raw)
  To: Ævar Arnfjörð Bjarmason, git; +Cc: Junio C Hamano

Am 28.12.22 um 19:00 schrieb Ævar Arnfjörð Bjarmason:
> In 0bfb48e6723 (builtin/commit-graph.c: UNLEAK variables, 2018-10-03)
> this was made to UNLEAK(), but we can just as easily free() the memory
> instead.
>
> Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
> ---
>  builtin/commit-graph.c | 6 ++++--
>  1 file changed, 4 insertions(+), 2 deletions(-)
>
> diff --git a/builtin/commit-graph.c b/builtin/commit-graph.c
> index e8f77f535f3..b6e5726b082 100644
> --- a/builtin/commit-graph.c
> +++ b/builtin/commit-graph.c
> @@ -67,6 +67,7 @@ static int graph_verify(int argc, const char **argv, const char *prefix)
>  	int fd;
>  	struct stat st;
>  	int flags = 0;
> +	int ret;
>
>  	static struct option builtin_commit_graph_verify_options[] = {
>  		OPT_BOOL(0, "shallow", &opts.shallow,
> @@ -111,8 +112,9 @@ static int graph_verify(int argc, const char **argv, const char *prefix)
>  	if (!graph)
>  		return !!open_ok;
>
> -	UNLEAK(graph);
> -	return verify_commit_graph(the_repository, graph, flags);
> +	ret = verify_commit_graph(the_repository, graph, flags);
> +	free(graph);
Shouldn't this be "free_commit_graph(graph);" instead?

> +	return ret;
>  }
>
>  extern int read_replace_refs;

^ permalink raw reply	[flat|nested] 193+ messages in thread

* Re: [PATCH 05/20] clone: use free() instead of UNLEAK()
  2022-12-28 18:00 ` [PATCH 05/20] clone: " Ævar Arnfjörð Bjarmason
@ 2022-12-28 18:20   ` René Scharfe
  2022-12-29  9:02   ` Junio C Hamano
  1 sibling, 0 replies; 193+ messages in thread
From: René Scharfe @ 2022-12-28 18:20 UTC (permalink / raw)
  To: Ævar Arnfjörð Bjarmason, git; +Cc: Junio C Hamano

Am 28.12.22 um 19:00 schrieb Ævar Arnfjörð Bjarmason:
> Change an UNLEAK() added in 0c4542738e6 (clone: free or UNLEAK further
> pointers when finished, 2021-03-14) to use a "to_free" pattern
> instead. In this case the "repo" can be either this absolute_pathdup()
> value, or in the "else if" branch seen in the context the the
> "argv[0]" argument to "main()".
>
> We can only free() the value in the former case, hence the "to_free"
> pattern.
>
> Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
> ---
>  builtin/clone.c | 5 +++--
>  1 file changed, 3 insertions(+), 2 deletions(-)
>
> diff --git a/builtin/clone.c b/builtin/clone.c
> index f518bb2dc1f..48156a4f2c2 100644
> --- a/builtin/clone.c
> +++ b/builtin/clone.c
> @@ -892,6 +892,7 @@ int cmd_clone(int argc, const char **argv, const char *prefix)
>  	int is_bundle = 0, is_local;
>  	int reject_shallow = 0;
>  	const char *repo_name, *repo, *work_tree, *git_dir;
> +	char *repo_to_free = NULL;
>  	char *path = NULL, *dir, *display_repo = NULL;
>  	int dest_exists, real_dest_exists = 0;
>  	const struct ref *refs, *remote_head;
> @@ -949,7 +950,7 @@ int cmd_clone(int argc, const char **argv, const char *prefix)
>  	path = get_repo_path(repo_name, &is_bundle);
>  	if (path) {
>  		FREE_AND_NULL(path);
> -		repo = absolute_pathdup(repo_name);
> +		repo = repo_to_free = absolute_pathdup(repo_name);
>  	} else if (strchr(repo_name, ':')) {
>  		repo = repo_name;

Alternatively you could do "repo = xstrdup(repo_name);" here to simplify
memory ownership of this string, at the cost of a small allocation.  But
the approach taken by this patch is fine as well.

>  		display_repo = transport_anonymize_url(repo);
> @@ -1392,7 +1393,7 @@ int cmd_clone(int argc, const char **argv, const char *prefix)
>  	free(unborn_head);
>  	free(dir);
>  	free(path);
> -	UNLEAK(repo);
> +	free(repo_to_free);
>  	junk_mode = JUNK_LEAVE_ALL;
>
>  	transport_ls_refs_options_release(&transport_ls_refs_options);

^ permalink raw reply	[flat|nested] 193+ messages in thread

* Re: [PATCH 20/20] grep API: plug memory leaks by freeing "header_list"
  2022-12-28 18:00 ` [PATCH 20/20] grep API: plug memory leaks by freeing "header_list" Ævar Arnfjörð Bjarmason
@ 2022-12-28 19:36   ` Eric Sunshine
  2022-12-28 22:50   ` René Scharfe
  1 sibling, 0 replies; 193+ messages in thread
From: Eric Sunshine @ 2022-12-28 19:36 UTC (permalink / raw)
  To: Ævar Arnfjörð Bjarmason
  Cc: git, René Scharfe, Junio C Hamano

On Wed, Dec 28, 2022 at 1:03 PM Ævar Arnfjörð Bjarmason
<avarab@gmail.com> wrote:
> When the "header_list" struct member was added in [1] it wasn't made
> to free the list using loop added for the adjacent "pattern_list"
> member, see [2] for when we started freeing it.
>
> Let's start doing o by splitting up the loop in free_grep_patterns()
> into a utility function. This makes e.g. this command leak-free when
> run on git.git:

s/o by/so by/

>         ./git -P log -1 --color=always --author=A origin/master
>
> 1. 80235ba79ef ("log --author=me --grep=it" should find intersection,
>    not union, 2010-01-17)
> 2. b48fb5b6a95 (grep: free expressions and patterns when done.,
>    2006-09-27)
>
> Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>

^ permalink raw reply	[flat|nested] 193+ messages in thread

* Re: [PATCH 07/20] stash: fix a "struct pathspec" leak
  2022-12-28 18:00 ` [PATCH 07/20] stash: fix a "struct pathspec" leak Ævar Arnfjörð Bjarmason
@ 2022-12-28 19:45   ` René Scharfe
  2022-12-29  7:02     ` Junio C Hamano
  0 siblings, 1 reply; 193+ messages in thread
From: René Scharfe @ 2022-12-28 19:45 UTC (permalink / raw)
  To: Ævar Arnfjörð Bjarmason, git; +Cc: Junio C Hamano

Am 28.12.22 um 19:00 schrieb Ævar Arnfjörð Bjarmason:
> Call clear_pathspec() on the pathspec initialized in
> push_stash().

This puzzled me for a while.  This patch adds an {0} initializer to the
declaration of the pathspec.  I assumed that this is necessary to avoid
giving clear_pathspec() an uninitialized struct.  It isn't, though,
because the pathspec is handed to parse_pathspec() first, which
initializes it.  So you can safely drop the first hunk.

> Initializing that structure in this way is already done
> by a few other callers, and now we have:
>
> 	$ git grep -e 'struct pathspec.* = { 0 }' -e memset.pathspec
> 	add-interactive.c:              struct pathspec ps_selected = { 0 };
> 	builtin/sparse-checkout.c:              struct pathspec p = { 0 };
> 	builtin/stash.c:        struct pathspec ps = { 0 };
> 	pathspec.c:     memset(pathspec, 0, sizeof(*pathspec));
> 	wt-status.c:                    struct pathspec ps = { 0 };

Not sure if this part of the commit message is useful.  It seems to
suggest that the only place to initialize a pathspec with memset is
pathspec.c itself, but there are a few more.  Here's a really sloppy
way to find (some of?) them:

   $ git grep -e 'struct pathspec [^*]' -e memset --all-match -p -n | awk '
      /struct pathspec [^*]/ {
         decl=$0
         declfunc=prevfunc
         var=decl; sub(/^.* /, "", var); sub(/;/, "", var)
         next
      }
      /memset/ && declfunc==prevfunc && match($0, var) {
         print decl
         print
         next
      }
      {prevfunc=$0}'
   builtin/log.c:726:	struct pathspec match_all;
   builtin/log.c:737:	memset(&match_all, 0, sizeof(match_all));
   builtin/ls-files.c:572:	struct pathspec pathspec;
   builtin/ls-files.c:600:		memset(&pathspec, 0, sizeof(pathspec));
   builtin/stash.c:1469:	struct pathspec ps;
   builtin/stash.c:1474:	memset(&ps, 0, sizeof(ps));
   builtin/stash.c:1787:	struct pathspec ps;
   builtin/stash.c:1813:	memset(&ps, 0, sizeof(ps));
   merge-recursive.c:479:	struct pathspec match_all;
   merge-recursive.c:480:	memset(&match_all, 0, sizeof(match_all));
   sparse-index.c:364:		struct pathspec ps;
   sparse-index.c:388:		memset(&ps, 0, sizeof(ps));

>
> Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
> ---
>  builtin/stash.c | 9 ++++++---
>  1 file changed, 6 insertions(+), 3 deletions(-)
>
> diff --git a/builtin/stash.c b/builtin/stash.c
> index bb0fd861434..e82fb69c2b3 100644
> --- a/builtin/stash.c
> +++ b/builtin/stash.c
> @@ -1708,7 +1708,7 @@ static int push_stash(int argc, const char **argv, const char *prefix,
>  	int pathspec_file_nul = 0;
>  	const char *stash_msg = NULL;
>  	const char *pathspec_from_file = NULL;
> -	struct pathspec ps;
> +	struct pathspec ps = { 0 };
>  	struct option options[] = {
>  		OPT_BOOL('k', "keep-index", &keep_index,
>  			 N_("keep index")),
> @@ -1727,6 +1727,7 @@ static int push_stash(int argc, const char **argv, const char *prefix,
>  		OPT_PATHSPEC_FILE_NUL(&pathspec_file_nul),
>  		OPT_END()
>  	};
> +	int ret;
>
>  	if (argc) {
>  		force_assume = !strcmp(argv[0], "-p");
> @@ -1766,8 +1767,10 @@ static int push_stash(int argc, const char **argv, const char *prefix,
>  		die(_("the option '%s' requires '%s'"), "--pathspec-file-nul", "--pathspec-from-file");
>  	}
>
> -	return do_push_stash(&ps, stash_msg, quiet, keep_index, patch_mode,
> -			     include_untracked, only_staged);
> +	ret = do_push_stash(&ps, stash_msg, quiet, keep_index, patch_mode,
> +			    include_untracked, only_staged);
> +	clear_pathspec(&ps);
> +	return ret;
>  }
>
>  static int push_stash_unassumed(int argc, const char **argv, const char *prefix)

^ permalink raw reply	[flat|nested] 193+ messages in thread

* Re: [PATCH 09/20] name-rev: don't xstrdup() an already dup'd string
  2022-12-28 18:00 ` [PATCH 09/20] name-rev: don't xstrdup() an already dup'd string Ævar Arnfjörð Bjarmason
@ 2022-12-28 20:31   ` René Scharfe
  2022-12-29  7:12     ` Junio C Hamano
  0 siblings, 1 reply; 193+ messages in thread
From: René Scharfe @ 2022-12-28 20:31 UTC (permalink / raw)
  To: Ævar Arnfjörð Bjarmason, git; +Cc: Junio C Hamano

Am 28.12.22 um 19:00 schrieb Ævar Arnfjörð Bjarmason:
> When "add_to_tip_table()" is called with a non-zero
> "shorten_unambiguous" we always return an xstrdup()'d string, which
> we'd then xstrdup() again, leaking memory. See [1] and [2] for how
> this leak came about.
>
> 1. 98c5c4ad015 (name-rev: allow to specify a subpath for --refs
>    option, 2013-06-18)
> 2. b23e0b9353e (name-rev: allow converting the exact object name at
>    the tip of a ref, 2013-07-07)
>
> Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
> ---
>  builtin/name-rev.c | 3 ++-
>  1 file changed, 2 insertions(+), 1 deletion(-)
>
> diff --git a/builtin/name-rev.c b/builtin/name-rev.c
> index 15535e914a6..24f4438eb01 100644
> --- a/builtin/name-rev.c
> +++ b/builtin/name-rev.c
> @@ -313,7 +313,8 @@ static void add_to_tip_table(const struct object_id *oid, const char *refname,
>
>  	ALLOC_GROW(tip_table.table, tip_table.nr + 1, tip_table.alloc);
>  	oidcpy(&tip_table.table[tip_table.nr].oid, oid);
> -	tip_table.table[tip_table.nr].refname = xstrdup(refname);
> +	tip_table.table[tip_table.nr].refname = shorten_unambiguous ? refname :
> +		xstrdup(refname);

Hmm, this works based on knowledge about the inner workings of
name_ref_abbrev(), which provides the refname.  Could be cleaned up by
inlining that short function, or by moving the xstrdup() call there.

>  	tip_table.table[tip_table.nr].commit = commit;
>  	tip_table.table[tip_table.nr].taggerdate = taggerdate;
>  	tip_table.table[tip_table.nr].from_tag = from_tag;

^ permalink raw reply	[flat|nested] 193+ messages in thread

* Re: [PATCH 11/20] worktree: fix a trivial leak in prune_worktrees()
  2022-12-28 18:00 ` [PATCH 11/20] worktree: fix a trivial leak in prune_worktrees() Ævar Arnfjörð Bjarmason
@ 2022-12-28 20:53   ` René Scharfe
  0 siblings, 0 replies; 193+ messages in thread
From: René Scharfe @ 2022-12-28 20:53 UTC (permalink / raw)
  To: Ævar Arnfjörð Bjarmason, git; +Cc: Junio C Hamano

Am 28.12.22 um 19:00 schrieb Ævar Arnfjörð Bjarmason:
> We were leaking both the "struct strbuf" in prune_worktrees(), as well
> as the "path" we got from should_prune_worktree(). Since these were
> the only two uses of the "struct string_list" let's change it to a
> "DUP" and push these to it with "string_list_append_nodup()".

Seems odd at first to only use _nodup() on a _DUP list, but is valid.

> For the string_list_append_nodup() we could also string_list_append()
> the main_path.buf, and then strbuf_release(&main_path) right away. But
> doing it this way avoids an allocation, as we already have the "struct
> strbuf" prepared for appending to "kept".

Similarly we could release the path that should_prune_worktree() gives us
after adding it.

The patch looks good to me.

>
> Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
> ---
>  builtin/worktree.c         | 6 +++---
>  t/t2401-worktree-prune.sh  | 1 +
>  t/t2406-worktree-repair.sh | 1 +
>  3 files changed, 5 insertions(+), 3 deletions(-)
>
> diff --git a/builtin/worktree.c b/builtin/worktree.c
> index 591d659faea..865ce9be22b 100644
> --- a/builtin/worktree.c
> +++ b/builtin/worktree.c
> @@ -173,7 +173,7 @@ static void prune_worktrees(void)
>  {
>  	struct strbuf reason = STRBUF_INIT;
>  	struct strbuf main_path = STRBUF_INIT;
> -	struct string_list kept = STRING_LIST_INIT_NODUP;
> +	struct string_list kept = STRING_LIST_INIT_DUP;
>  	DIR *dir = opendir(git_path("worktrees"));
>  	struct dirent *d;
>  	if (!dir)
> @@ -184,14 +184,14 @@ static void prune_worktrees(void)
>  		if (should_prune_worktree(d->d_name, &reason, &path, expire))
>  			prune_worktree(d->d_name, reason.buf);
>  		else if (path)
> -			string_list_append(&kept, path)->util = xstrdup(d->d_name);
> +			string_list_append_nodup(&kept, path)->util = xstrdup(d->d_name);
>  	}
>  	closedir(dir);
>
>  	strbuf_add_absolute_path(&main_path, get_git_common_dir());
>  	/* massage main worktree absolute path to match 'gitdir' content */
>  	strbuf_strip_suffix(&main_path, "/.");
> -	string_list_append(&kept, strbuf_detach(&main_path, NULL));
> +	string_list_append_nodup(&kept, strbuf_detach(&main_path, NULL));
>  	prune_dups(&kept);
>  	string_list_clear(&kept, 1);
>
> diff --git a/t/t2401-worktree-prune.sh b/t/t2401-worktree-prune.sh
> index 3d28c7f06b2..568a47ec426 100755
> --- a/t/t2401-worktree-prune.sh
> +++ b/t/t2401-worktree-prune.sh
> @@ -5,6 +5,7 @@ test_description='prune $GIT_DIR/worktrees'
>  GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
>  export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
>
> +TEST_PASSES_SANITIZE_LEAK=true
>  . ./test-lib.sh
>
>  test_expect_success initialize '
> diff --git a/t/t2406-worktree-repair.sh b/t/t2406-worktree-repair.sh
> index 5c44453e1c1..8970780efcc 100755
> --- a/t/t2406-worktree-repair.sh
> +++ b/t/t2406-worktree-repair.sh
> @@ -2,6 +2,7 @@
>
>  test_description='test git worktree repair'
>
> +TEST_PASSES_SANITIZE_LEAK=true
>  . ./test-lib.sh
>
>  test_expect_success setup '

^ permalink raw reply	[flat|nested] 193+ messages in thread

* Re: [PATCH 12/20] http-backend.c: fix cmd_main() memory leak, refactor reg{exec,free}()
  2022-12-28 18:00 ` [PATCH 12/20] http-backend.c: fix cmd_main() memory leak, refactor reg{exec,free}() Ævar Arnfjörð Bjarmason
@ 2022-12-28 21:37   ` René Scharfe
  2022-12-29  7:32     ` Junio C Hamano
  0 siblings, 1 reply; 193+ messages in thread
From: René Scharfe @ 2022-12-28 21:37 UTC (permalink / raw)
  To: Ævar Arnfjörð Bjarmason, git; +Cc: Junio C Hamano

Am 28.12.22 um 19:00 schrieb Ævar Arnfjörð Bjarmason:
> Fix a memory leak that's been with us ever since
> 2f4038ab337 (Git-aware CGI to provide dumb HTTP transport,
> 2009-10-30). In this case we're not calling regerror() after a failed
> regexec(), and don't otherwise use "re" afterwards.
>
> We can therefore simplify this code by calling regfree() right after
> the regexec(). An alternative fix would be to add a regfree() to both
> the "return" and "break" path in this for-loop.

Yes, or to add one regfree() call early in the conditional...

>
> Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
> ---
>  http-backend.c | 7 +++++--
>  1 file changed, 5 insertions(+), 2 deletions(-)
>
> diff --git a/http-backend.c b/http-backend.c
> index 6eb3b2fe51c..9bb63c458b1 100644
> --- a/http-backend.c
> +++ b/http-backend.c
> @@ -759,10 +759,14 @@ int cmd_main(int argc, const char **argv)
>  		struct service_cmd *c = &services[i];
>  		regex_t re;
>  		regmatch_t out[1];
> +		int ret;
>
>  		if (regcomp(&re, c->pattern, REG_EXTENDED))
>  			die("Bogus regex in service table: %s", c->pattern);
> -		if (!regexec(&re, dir, 1, out, 0)) {
> +		ret = regexec(&re, dir, 1, out, 0);
> +		regfree(&re);
> +
> +		if (!ret) {
>  			size_t n;
>

... i.e. right here.  But only after copying the offsets out of "out"!

Anyway, the ret approach taken here is fine.

"dir" is still leaking, by the way.  Probably worth a separate patch.

>  			if (strcmp(method, c->method))
> @@ -774,7 +778,6 @@ int cmd_main(int argc, const char **argv)
>  			dir[out[0].rm_so] = 0;
>  			break;
>  		}
> -		regfree(&re);
>  	}
>
>  	if (!cmd)

^ permalink raw reply	[flat|nested] 193+ messages in thread

* Re: [PATCH 15/20] builtin/merge.c: always free "struct strbuf msg"
  2022-12-28 18:00 ` [PATCH 15/20] builtin/merge.c: always free "struct strbuf msg" Ævar Arnfjörð Bjarmason
@ 2022-12-28 22:06   ` René Scharfe
  0 siblings, 0 replies; 193+ messages in thread
From: René Scharfe @ 2022-12-28 22:06 UTC (permalink / raw)
  To: Ævar Arnfjörð Bjarmason, git; +Cc: Junio C Hamano

Am 28.12.22 um 19:00 schrieb Ævar Arnfjörð Bjarmason:
> Follow-up 465028e0e25 (merge: add missing strbuf_release(),
> 2021-10-07) and free "&msg" also when we'd "goto done" from the scope
> it's allocated in.

OK, but quite some trouble to go through to get one of two static
strings out without leaking.

>
> Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
> ---
>  builtin/merge.c | 2 ++
>  1 file changed, 2 insertions(+)
>
> diff --git a/builtin/merge.c b/builtin/merge.c
> index 0f093f2a4f2..8f78f326dbe 100644
> --- a/builtin/merge.c
> +++ b/builtin/merge.c
> @@ -1577,6 +1577,7 @@ int cmd_merge(int argc, const char **argv, const char *prefix)
>  		commit = remoteheads->item;
>  		if (!commit) {
>  			ret = 1;
> +			strbuf_release(&msg);
>  			goto done;
>  		}
>
> @@ -1589,6 +1590,7 @@ int cmd_merge(int argc, const char **argv, const char *prefix)
>  					  overwrite_ignore)) {
>  			apply_autostash(git_path_merge_autostash(the_repository));
>  			ret = 1;
> +			strbuf_release(&msg);
>  			goto done;
>  		}
>

How about not using strbuf instead?

 builtin/merge.c | 11 ++++-------
 1 file changed, 4 insertions(+), 7 deletions(-)

diff --git a/builtin/merge.c b/builtin/merge.c
index 0f093f2a4f..91dd5435c5 100644
--- a/builtin/merge.c
+++ b/builtin/merge.c
@@ -1560,7 +1560,9 @@ int cmd_merge(int argc, const char **argv, const char *prefix)
 			!common->next &&
 			oideq(&common->item->object.oid, &head_commit->object.oid)) {
 		/* Again the most common case of merging one remote. */
-		struct strbuf msg = STRBUF_INIT;
+		const char *msg = have_message ?
+			"Fast-forward (no commit created; -m option ignored)" :
+			"Fast-forward";
 		struct commit *commit;

 		if (verbosity >= 0) {
@@ -1570,10 +1572,6 @@ int cmd_merge(int argc, const char **argv, const char *prefix)
 			       find_unique_abbrev(&remoteheads->item->object.oid,
 						  DEFAULT_ABBREV));
 		}
-		strbuf_addstr(&msg, "Fast-forward");
-		if (have_message)
-			strbuf_addstr(&msg,
-				" (no commit created; -m option ignored)");
 		commit = remoteheads->item;
 		if (!commit) {
 			ret = 1;
@@ -1592,9 +1590,8 @@ int cmd_merge(int argc, const char **argv, const char *prefix)
 			goto done;
 		}

-		finish(head_commit, remoteheads, &commit->object.oid, msg.buf);
+		finish(head_commit, remoteheads, &commit->object.oid, msg);
 		remove_merge_branch_state(the_repository);
-		strbuf_release(&msg);
 		goto done;
 	} else if (!remoteheads->next && common->next)
 		;

^ permalink raw reply related	[flat|nested] 193+ messages in thread

* Re: [PATCH 16/20] builtin/merge.c: free "&buf" on "Your local changes..." error
  2022-12-28 18:00 ` [PATCH 16/20] builtin/merge.c: free "&buf" on "Your local changes..." error Ævar Arnfjörð Bjarmason
@ 2022-12-28 22:13   ` René Scharfe
  0 siblings, 0 replies; 193+ messages in thread
From: René Scharfe @ 2022-12-28 22:13 UTC (permalink / raw)
  To: Ævar Arnfjörð Bjarmason, git; +Cc: Junio C Hamano

Am 28.12.22 um 19:00 schrieb Ævar Arnfjörð Bjarmason:
> Plug a memory leak introduced in [1], since that change didn't follow
> the "goto done" pattern introduced in [2] we'd leak the "&buf" memory.
>
> 1. e4cdfe84a0d (merge: abort if index does not match HEAD for trivial
>    merges, 2022-07-23)
> 2. d5a35c114ab (Copy resolve_ref() return value for longer use,
>    2011-11-13)
>
> Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
> ---
>  builtin/merge.c                | 3 ++-
>  t/t6439-merge-co-error-msgs.sh | 1 +
>  2 files changed, 3 insertions(+), 1 deletion(-)
>
> diff --git a/builtin/merge.c b/builtin/merge.c
> index 8f78f326dbe..e29b456f92c 100644
> --- a/builtin/merge.c
> +++ b/builtin/merge.c
> @@ -1623,7 +1623,8 @@ int cmd_merge(int argc, const char **argv, const char *prefix)
>  				error(_("Your local changes to the following files would be overwritten by merge:\n  %s"),
>  				      sb.buf);
>  				strbuf_release(&sb);
> -				return 2;
> +				ret = 2;
> +				goto done;

Good change -- only a single return remains, which is easier to handle.

If it was only about "buf" then moving its strbuf_release() call way up to
free it immediately after its last use would work as well.

>  			}
>
>  			/* See if it is really trivial. */
> diff --git a/t/t6439-merge-co-error-msgs.sh b/t/t6439-merge-co-error-msgs.sh
> index 52cf0c87690..0cbec57cdab 100755
> --- a/t/t6439-merge-co-error-msgs.sh
> +++ b/t/t6439-merge-co-error-msgs.sh
> @@ -5,6 +5,7 @@ test_description='unpack-trees error messages'
>  GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
>  export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
>
> +TEST_PASSES_SANITIZE_LEAK=true
>  . ./test-lib.sh
>
>

^ permalink raw reply	[flat|nested] 193+ messages in thread

* Re: [PATCH 18/20] object-file.c: free the "t.tag" in check_tag()
  2022-12-28 18:00 ` [PATCH 18/20] object-file.c: free the "t.tag" in check_tag() Ævar Arnfjörð Bjarmason
@ 2022-12-28 22:25   ` René Scharfe
  0 siblings, 0 replies; 193+ messages in thread
From: René Scharfe @ 2022-12-28 22:25 UTC (permalink / raw)
  To: Ævar Arnfjörð Bjarmason, git; +Cc: Junio C Hamano

Am 28.12.22 um 19:00 schrieb Ævar Arnfjörð Bjarmason:
> Fix a memory leak that's been with us ever since c879daa2372 (Make
> hash-object more robust against malformed objects, 2011-02-05). With
> "HASH_FORMAT_CHECK" (used by "hash-object" and "replace") we'll parse
> tags into a throwaway variable on the stack, but weren't freeing the
> "item->tag" we might malloc() when doing so.
>
> Mark the tests that now pass in their entirety as passing under
> "SANITIZE=leak", which means we'll test them as part of the
> "linux-leaks" CI job.
>
> Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
> ---
>  object-file.c         | 1 +
>  t/t3800-mktag.sh      | 1 +
>  t/t5302-pack-index.sh | 2 ++
>  3 files changed, 4 insertions(+)
>
> diff --git a/object-file.c b/object-file.c
> index c1b71c28347..36ed6c3122c 100644
> --- a/object-file.c
> +++ b/object-file.c
> @@ -2331,6 +2331,7 @@ static void check_tag(const void *buf, size_t size)
>  	memset(&t, 0, sizeof(t));
>  	if (parse_tag_buffer(the_repository, &t, buf, size))
>  		die(_("corrupt tag"));
> +	free(t.tag);

Better use release_tag_memory() instead to avoid leaking knowledge of tag
internals, no?

>  }
>
>  static int index_mem(struct index_state *istate,
> diff --git a/t/t3800-mktag.sh b/t/t3800-mktag.sh
> index e3cf0ffbe59..d3e428ff46e 100755
> --- a/t/t3800-mktag.sh
> +++ b/t/t3800-mktag.sh
> @@ -4,6 +4,7 @@
>
>  test_description='git mktag: tag object verify test'
>
> +TEST_PASSES_SANITIZE_LEAK=true
>  . ./test-lib.sh
>
>  ###########################################################
> diff --git a/t/t5302-pack-index.sh b/t/t5302-pack-index.sh
> index b0095ab41d3..54b11f81c63 100755
> --- a/t/t5302-pack-index.sh
> +++ b/t/t5302-pack-index.sh
> @@ -4,6 +4,8 @@
>  #
>
>  test_description='pack index with 64-bit offsets and object CRC'
> +
> +TEST_PASSES_SANITIZE_LEAK=true
>  . ./test-lib.sh
>
>  test_expect_success 'setup' '

^ permalink raw reply	[flat|nested] 193+ messages in thread

* Re: [PATCH 20/20] grep API: plug memory leaks by freeing "header_list"
  2022-12-28 18:00 ` [PATCH 20/20] grep API: plug memory leaks by freeing "header_list" Ævar Arnfjörð Bjarmason
  2022-12-28 19:36   ` Eric Sunshine
@ 2022-12-28 22:50   ` René Scharfe
  1 sibling, 0 replies; 193+ messages in thread
From: René Scharfe @ 2022-12-28 22:50 UTC (permalink / raw)
  To: Ævar Arnfjörð Bjarmason, git; +Cc: Junio C Hamano

Am 28.12.22 um 19:00 schrieb Ævar Arnfjörð Bjarmason:
> When the "header_list" struct member was added in [1] it wasn't made
> to free the list using loop added for the adjacent "pattern_list"
> member, see [2] for when we started freeing it.
>
> Let's start doing o by splitting up the loop in free_grep_patterns()
> into a utility function. This makes e.g. this command leak-free when
> run on git.git:
>
> 	./git -P log -1 --color=always --author=A origin/master
>
> 1. 80235ba79ef ("log --author=me --grep=it" should find intersection,
>    not union, 2010-01-17)
> 2. b48fb5b6a95 (grep: free expressions and patterns when done.,
>    2006-09-27)
>
> Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
> ---
>  grep.c | 10 ++++++++--
>  1 file changed, 8 insertions(+), 2 deletions(-)
>
> diff --git a/grep.c b/grep.c
> index ca75514f8f6..c908535e0d8 100644
> --- a/grep.c
> +++ b/grep.c
> @@ -769,11 +769,11 @@ static void free_pattern_expr(struct grep_expr *x)
>  	free(x);
>  }
>
> -void free_grep_patterns(struct grep_opt *opt)
> +static void free_grep_pat(struct grep_pat *pattern)
>  {
>  	struct grep_pat *p, *n;
>
> -	for (p = opt->pattern_list; p; p = n) {
> +	for (p = pattern; p; p = n) {
>  		n = p->next;
>  		switch (p->token) {
>  		case GREP_PATTERN: /* atom */
> @@ -790,6 +790,12 @@ void free_grep_patterns(struct grep_opt *opt)
>  		}
>  		free(p);
>  	}
> +}
> +
> +void free_grep_patterns(struct grep_opt *opt)
> +{
> +	free_grep_pat(opt->pattern_list);
> +	free_grep_pat(opt->header_list);

OK.  Patch 19 didn't help me understand this one, though, contrary to
the foreshadowing in its commit message.  It seems quite unrelated, in
fact.  It's a stylistic improvement, to be sure, but I expected more
structural relevance.

Factoring out free_grep_pat() first and then using it for header_list
in a separate patch would have made a difference by making the actual
leak fix being a one-liner.

Not necessarily worth a re-roll, though -- the patch is understandable
as-is, but it probably took me a moment longer with refactoring and
fix blended together like this.

>
>  	if (opt->pattern_expression)
>  		free_pattern_expr(opt->pattern_expression);

^ permalink raw reply	[flat|nested] 193+ messages in thread

* Re: [PATCH 07/20] stash: fix a "struct pathspec" leak
  2022-12-28 19:45   ` René Scharfe
@ 2022-12-29  7:02     ` Junio C Hamano
  0 siblings, 0 replies; 193+ messages in thread
From: Junio C Hamano @ 2022-12-29  7:02 UTC (permalink / raw)
  To: René Scharfe; +Cc: Ævar Arnfjörð Bjarmason, git

René Scharfe <l.s.r@web.de> writes:

> Am 28.12.22 um 19:00 schrieb Ævar Arnfjörð Bjarmason:
>> Call clear_pathspec() on the pathspec initialized in
>> push_stash().
>
> This puzzled me for a while.  This patch adds an {0} initializer to the
> declaration of the pathspec.  I assumed that this is necessary to avoid
> giving clear_pathspec() an uninitialized struct.  It isn't, though,
> because the pathspec is handed to parse_pathspec() first, which
> initializes it.  So you can safely drop the first hunk.

It did mislead me too.  I expected that addition of "= { 0 }" was to
remove memset('\0') somewhere else, but that is not the case.

^ permalink raw reply	[flat|nested] 193+ messages in thread

* Re: [PATCH 09/20] name-rev: don't xstrdup() an already dup'd string
  2022-12-28 20:31   ` René Scharfe
@ 2022-12-29  7:12     ` Junio C Hamano
  0 siblings, 0 replies; 193+ messages in thread
From: Junio C Hamano @ 2022-12-29  7:12 UTC (permalink / raw)
  To: René Scharfe; +Cc: Ævar Arnfjörð Bjarmason, git

René Scharfe <l.s.r@web.de> writes:

>> -	tip_table.table[tip_table.nr].refname = xstrdup(refname);
>> +	tip_table.table[tip_table.nr].refname = shorten_unambiguous ? refname :
>> +		xstrdup(refname);
>
> Hmm, this works based on knowledge about the inner workings of
> name_ref_abbrev(), which provides the refname.  Could be cleaned up by
> inlining that short function, or by moving the xstrdup() call there.

Yeah, name_ref_abbrev() returns sometimes an allocated and some
other times a borrowed piece of memory, which is a poor design that
ignores memory ownership issues.  Luckily the function being touched
is the sole caller of it, and I agree with you that inlining may give
us a better fix.


^ permalink raw reply	[flat|nested] 193+ messages in thread

* Re: [PATCH 12/20] http-backend.c: fix cmd_main() memory leak, refactor reg{exec,free}()
  2022-12-28 21:37   ` René Scharfe
@ 2022-12-29  7:32     ` Junio C Hamano
  2022-12-29 15:49       ` René Scharfe
  0 siblings, 1 reply; 193+ messages in thread
From: Junio C Hamano @ 2022-12-29  7:32 UTC (permalink / raw)
  To: René Scharfe; +Cc: Ævar Arnfjörð Bjarmason, git

René Scharfe <l.s.r@web.de> writes:

>> diff --git a/http-backend.c b/http-backend.c
>> index 6eb3b2fe51c..9bb63c458b1 100644
>> --- a/http-backend.c
>> +++ b/http-backend.c
>> @@ -759,10 +759,14 @@ int cmd_main(int argc, const char **argv)
>>  		struct service_cmd *c = &services[i];
>>  		regex_t re;
>>  		regmatch_t out[1];
>> +		int ret;
>>
>>  		if (regcomp(&re, c->pattern, REG_EXTENDED))
>>  			die("Bogus regex in service table: %s", c->pattern);
>> -		if (!regexec(&re, dir, 1, out, 0)) {
>> +		ret = regexec(&re, dir, 1, out, 0);
>> +		regfree(&re);
>> +
>> +		if (!ret) {
>>  			size_t n;
>>
>
> ... i.e. right here.  But only after copying the offsets out of "out"!

"only after..."?  Do out[i].rm_eo and out[i].rm_so become invalid
after calling regfree() on the regex out[] was taken against?  I do
not think so, and am confused by the comment.  After all, if we can
free only after copying the offsets out of "out", the posted patch
in question is already wrong ;-)

> Anyway, the ret approach taken here is fine.

Yup.

> "dir" is still leaking, by the way.  Probably worth a separate patch.

Good eyes.  But I'd actually say UNLEAK() is fine for that one.

Thanks.


^ permalink raw reply	[flat|nested] 193+ messages in thread

* Re: [PATCH 05/20] clone: use free() instead of UNLEAK()
  2022-12-28 18:00 ` [PATCH 05/20] clone: " Ævar Arnfjörð Bjarmason
  2022-12-28 18:20   ` René Scharfe
@ 2022-12-29  9:02   ` Junio C Hamano
  2022-12-29 10:20     ` Ævar Arnfjörð Bjarmason
  1 sibling, 1 reply; 193+ messages in thread
From: Junio C Hamano @ 2022-12-29  9:02 UTC (permalink / raw)
  To: Ævar Arnfjörð Bjarmason; +Cc: git, René Scharfe

Ævar Arnfjörð Bjarmason  <avarab@gmail.com> writes:

> Change an UNLEAK() added in 0c4542738e6 (clone: free or UNLEAK further
> pointers when finished, 2021-03-14) to use a "to_free" pattern
> instead. In this case the "repo" can be either this absolute_pathdup()
> value, or in the "else if" branch seen in the context the the
> "argv[0]" argument to "main()".
>
> We can only free() the value in the former case, hence the "to_free"
> pattern.

Many other patches in the series, especially the ones that touch the
library-ish parts that can be called unbounded number of times, do
make sense, but this patch helps nobody.  Not even the leak checker,
who should already be happy with the existing UNLEAK() marking.  The
only thing it does is to free() a piece of memory obtained from a
one-time allocation that will be discarded upon program exit anyway.

If this were a freestanding patch done outside any series, I would
probably have not bothered to queue it.  I'll be queuing as part of
the larger whole, but I am not all that impressed by this step and
the thinking that led to its inclusion in the series.

Thanks.




>
> Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
> ---
>  builtin/clone.c | 5 +++--
>  1 file changed, 3 insertions(+), 2 deletions(-)
>
> diff --git a/builtin/clone.c b/builtin/clone.c
> index f518bb2dc1f..48156a4f2c2 100644
> --- a/builtin/clone.c
> +++ b/builtin/clone.c
> @@ -892,6 +892,7 @@ int cmd_clone(int argc, const char **argv, const char *prefix)
>  	int is_bundle = 0, is_local;
>  	int reject_shallow = 0;
>  	const char *repo_name, *repo, *work_tree, *git_dir;
> +	char *repo_to_free = NULL;
>  	char *path = NULL, *dir, *display_repo = NULL;
>  	int dest_exists, real_dest_exists = 0;
>  	const struct ref *refs, *remote_head;
> @@ -949,7 +950,7 @@ int cmd_clone(int argc, const char **argv, const char *prefix)
>  	path = get_repo_path(repo_name, &is_bundle);
>  	if (path) {
>  		FREE_AND_NULL(path);
> -		repo = absolute_pathdup(repo_name);
> +		repo = repo_to_free = absolute_pathdup(repo_name);
>  	} else if (strchr(repo_name, ':')) {
>  		repo = repo_name;
>  		display_repo = transport_anonymize_url(repo);
> @@ -1392,7 +1393,7 @@ int cmd_clone(int argc, const char **argv, const char *prefix)
>  	free(unborn_head);
>  	free(dir);
>  	free(path);
> -	UNLEAK(repo);
> +	free(repo_to_free);
>  	junk_mode = JUNK_LEAVE_ALL;
>  
>  	transport_ls_refs_options_release(&transport_ls_refs_options);

^ permalink raw reply	[flat|nested] 193+ messages in thread

* Re: [PATCH 08/20] reset: fix cmd_reset() leaks with a clear_pathspec() call
  2022-12-28 18:00 ` [PATCH 08/20] reset: fix cmd_reset() leaks with a clear_pathspec() call Ævar Arnfjörð Bjarmason
@ 2022-12-29  9:12   ` Junio C Hamano
  0 siblings, 0 replies; 193+ messages in thread
From: Junio C Hamano @ 2022-12-29  9:12 UTC (permalink / raw)
  To: Ævar Arnfjörð Bjarmason; +Cc: git, René Scharfe

Ævar Arnfjörð Bjarmason  <avarab@gmail.com> writes:

> Add clear_pathspec() calls to cmd_reset(), including to the codepaths
> where we'd return early.

Unlike the [05/20] step, this did not have UNLEAK(), so it is a true
improvement ;-)



^ permalink raw reply	[flat|nested] 193+ messages in thread

* Re: [PATCH 05/20] clone: use free() instead of UNLEAK()
  2022-12-29  9:02   ` Junio C Hamano
@ 2022-12-29 10:20     ` Ævar Arnfjörð Bjarmason
  0 siblings, 0 replies; 193+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2022-12-29 10:20 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: git, René Scharfe


On Thu, Dec 29 2022, Junio C Hamano wrote:

> Ævar Arnfjörð Bjarmason  <avarab@gmail.com> writes:
>
>> Change an UNLEAK() added in 0c4542738e6 (clone: free or UNLEAK further
>> pointers when finished, 2021-03-14) to use a "to_free" pattern
>> instead. In this case the "repo" can be either this absolute_pathdup()
>> value, or in the "else if" branch seen in the context the the
>> "argv[0]" argument to "main()".
>>
>> We can only free() the value in the former case, hence the "to_free"
>> pattern.
>
> Many other patches in the series, especially the ones that touch the
> library-ish parts that can be called unbounded number of times, do
> make sense, but this patch helps nobody.  Not even the leak checker,
> who should already be happy with the existing UNLEAK() marking.  The
> only thing it does is to free() a piece of memory obtained from a
> one-time allocation that will be discarded upon program exit anyway.

The changes in this series that deal with UNLEAK() take it as a given
that it's a good thing to replace these trivial cases with a free().

But the rationale is in ac95f5d36ad (built-ins: use free() not UNLEAK()
if trivial, rm dead code, 2022-11-08) in the earlier topic, this is the
follow-up.

We only have 15 UNLEAK() invocations in-tree left, with this series
(which made no special effort to get the rest, but just the remaining
very low hanging fruit) it's 13.

If our built-ins were using this pattern consistently I think it would
be worth keeping & using UNLEAK() like this, but they aren't.

Even the "display_repo" variable seen in the context of this patch is
free()'d, see 46da295a770 (clone/fetch: anonymize URLs in the reflog,
2020-06-04), along with the rest in this function and others (with the
exception of the remaining UNLEAK(...)), e.g. "remote_name" etc.

So I think keeping it just makes the code more confusing, one wonders
why this particular variable is being UNLEAK()'d, instead of just
free()'d like the rest.

As the comment on the SUPPRESS_ANNOTATED_LEAKS macro notes we only get
the benefit from it if you compile with SUPPRESS_ANNOTATED_LEAKS, so
e.g. if you use SANITIZE=leak it'll kick in, but not on a normal build
and e.g.:

	valgrind --leak-check=full ./git commit-graph verify

Which will with UNLEAK() report the leak fixed in 04/20 here (I'm just
using it in this example since easier to reproduce), but with free() we
won't report it.

I agree it has a marginal benefit, e.g. it won't contribute to the
linux-leaks job, as it uses SUPPRESS_ANNOTATED_LEAKS, but the above is
why I think it's worth changing the remaining low-hanging UNLEAK() fruit
to free().

We do have cases where it's much tricker to replace those UNLEAK() with
free(). I think it's much better if we narrow its use to those cases at
this point.

^ permalink raw reply	[flat|nested] 193+ messages in thread

* Re: [PATCH 12/20] http-backend.c: fix cmd_main() memory leak, refactor reg{exec,free}()
  2022-12-29  7:32     ` Junio C Hamano
@ 2022-12-29 15:49       ` René Scharfe
  0 siblings, 0 replies; 193+ messages in thread
From: René Scharfe @ 2022-12-29 15:49 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: Ævar Arnfjörð Bjarmason, git

Am 29.12.22 um 08:32 schrieb Junio C Hamano:
> René Scharfe <l.s.r@web.de> writes:
>
>>> diff --git a/http-backend.c b/http-backend.c
>>> index 6eb3b2fe51c..9bb63c458b1 100644
>>> --- a/http-backend.c
>>> +++ b/http-backend.c
>>> @@ -759,10 +759,14 @@ int cmd_main(int argc, const char **argv)
>>>  		struct service_cmd *c = &services[i];
>>>  		regex_t re;
>>>  		regmatch_t out[1];
>>> +		int ret;
>>>
>>>  		if (regcomp(&re, c->pattern, REG_EXTENDED))
>>>  			die("Bogus regex in service table: %s", c->pattern);
>>> -		if (!regexec(&re, dir, 1, out, 0)) {
>>> +		ret = regexec(&re, dir, 1, out, 0);
>>> +		regfree(&re);
>>> +
>>> +		if (!ret) {
>>>  			size_t n;
>>>
>>
>> ... i.e. right here.  But only after copying the offsets out of "out"!
>
> "only after..."?  Do out[i].rm_eo and out[i].rm_so become invalid
> after calling regfree() on the regex out[] was taken against?  I do
> not think so, and am confused by the comment.
Nah, sorry, I was confused. o_O  "out" is not affected by regfree(), of
course; it's supplied by the regexec() caller -- cmd_main() owns it.

René

^ permalink raw reply	[flat|nested] 193+ messages in thread

* [PATCH v2 00/20] leak fixes: various simple leak fixes
  2022-12-28 18:00 [PATCH 00/20] leak fixes: various simple leak fixes Ævar Arnfjörð Bjarmason
                   ` (19 preceding siblings ...)
  2022-12-28 18:00 ` [PATCH 20/20] grep API: plug memory leaks by freeing "header_list" Ævar Arnfjörð Bjarmason
@ 2022-12-30  2:18 ` Ævar Arnfjörð Bjarmason
  2022-12-30  2:18   ` [PATCH v2 01/20] tests: mark tests as passing with SANITIZE=leak Ævar Arnfjörð Bjarmason
                     ` (20 more replies)
  20 siblings, 21 replies; 193+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2022-12-30  2:18 UTC (permalink / raw)
  To: git
  Cc: René Scharfe, Junio C Hamano, Eric Sunshine,
	Ævar Arnfjörð Bjarmason

This is a follow-up to the ab/various-leak-fixes topic merged in
9ea1378d046 (Merge branch 'ab/various-leak-fixes', 2022-12-14). Like
that topic this is mixed collection of various leak fixes, all of
which should be simple to review & reason about.

Changes since v1:

 * v1 added 32 more tests to the linux-leaks job, this adds 51. In the
   v1 11 test files were made to pass by this series itself (the 1/20
   adds already existing tests with TEST_PASSES_SANITIZE_LEAK=true),
   we now have 30 newly passing tests.

   This is because I added a couple of more leak fixes to this v2, see below.

* Squash the previous [1-2]/20 into one.
* Squash all of the "pathspec" leak fixes into one patch
* Add a "name-rev" leak fix. Instad of UNLEAK() we can (mostly) skip
  allocation altogether (just need a string_list container)
* Fix the "dir" leak in http-backend.c as suggested, and also a
  "cmd_arg" leak in the same function.
* Rewrote the "builtin/merge.c" fix for "msg" as René suggested
* Use release_tag_memory() in the check_tag() fix. I also missed that
  I'd submitted that leak fix in another series. I re-rolled it
  (https://lore.kernel.org/git/cover-v2-0.3-00000000000-20221230T011725Z-avarab@gmail.com/)
  to avoid fixing the leak, and went for René's suggestion of using
  release_tag_memory() in this v2.
* Squashed/rewrote the grep.c refactoring & leak fix, hopfully this
  state is easier to grok/follow.
* Add two new leak fixes to the end of this series, each one is
  trivial, but they make 6 and 12 new tests pass in their entirety.
* Hopefully addressed all other comments, e.g. a typo fix, commit
  message clarifications etc.

Branch & CI for this at
https://github.com/avar/git/tree/avar/leak-fixes-more-misc-trivial-2
(the "win build" failure is unrelated, some generic CI issue that also
happens if I re-push Junio's "master").

Ævar Arnfjörð Bjarmason (20):
  tests: mark tests as passing with SANITIZE=leak
  bundle.c: don't leak the "args" in the "struct child_process"
  commit-graph: use free() instead of UNLEAK()
  clone: use free() instead of UNLEAK()
  various: add missing clear_pathspec(), fix leaks
  name-rev: don't xstrdup() an already dup'd string
  repack: fix leaks on error with "goto cleanup"
  worktree: fix a trivial leak in prune_worktrees()
  http-backend.c: fix "dir" and "cmd_arg" leaks in cmd_main()
  http-backend.c: fix cmd_main() memory leak, refactor reg{exec,free}()
  commit-graph: fix a parse_options_concat() leak
  show-branch: free() allocated "head" before return
  builtin/merge.c: always free "struct strbuf msg"
  builtin/merge.c: free "&buf" on "Your local changes..." error
  connected.c: free(new_pack) in check_connected()
  object-file.c: release the "tag" in check_tag()
  grep.c: refactor free_grep_patterns()
  grep API: plug memory leaks by freeing "header_list"
  receive-pack: free() the "ref_name" in "struct command"
  push: free_refs() the "local_refs" in set_refspecs()

 archive.c                                  |  1 +
 builtin/clean.c                            |  1 +
 builtin/clone.c                            |  5 +++--
 builtin/commit-graph.c                     | 10 ++++++----
 builtin/merge.c                            | 14 ++++++-------
 builtin/name-rev.c                         | 23 ++++++++++------------
 builtin/push.c                             |  1 +
 builtin/receive-pack.c                     | 10 ++++++++++
 builtin/repack.c                           | 13 ++++++------
 builtin/reset.c                            | 11 ++++++++---
 builtin/show-branch.c                      |  1 +
 builtin/stash.c                            |  7 +++++--
 builtin/worktree.c                         |  6 +++---
 bundle.c                                   |  6 ++++--
 connected.c                                | 13 ++++++------
 grep.c                                     | 15 +++++++++-----
 http-backend.c                             |  9 +++++++--
 object-file.c                              |  1 +
 t/t0023-crlf-am.sh                         |  1 +
 t/t1301-shared-repo.sh                     |  1 +
 t/t1302-repo-version.sh                    |  1 +
 t/t1304-default-acl.sh                     |  1 +
 t/t1408-packed-refs.sh                     |  1 +
 t/t1410-reflog.sh                          |  1 +
 t/t1416-ref-transaction-hooks.sh           |  1 +
 t/t2401-worktree-prune.sh                  |  1 +
 t/t2406-worktree-repair.sh                 |  1 +
 t/t3210-pack-refs.sh                       |  1 +
 t/t3800-mktag.sh                           |  1 +
 t/t4152-am-subjects.sh                     |  2 ++
 t/t4254-am-corrupt.sh                      |  2 ++
 t/t4256-am-format-flowed.sh                |  1 +
 t/t4257-am-interactive.sh                  |  2 ++
 t/t5001-archive-attr.sh                    |  1 +
 t/t5004-archive-corner-cases.sh            |  2 ++
 t/t5302-pack-index.sh                      |  2 ++
 t/t5317-pack-objects-filter-objects.sh     |  1 +
 t/t5330-no-lazy-fetch-with-commit-graph.sh |  1 +
 t/t5403-post-checkout-hook.sh              |  1 +
 t/t5405-send-pack-rewind.sh                |  1 +
 t/t5406-remote-rejects.sh                  |  1 +
 t/t5502-quickfetch.sh                      |  1 +
 t/t5504-fetch-receive-strict.sh            |  1 +
 t/t5507-remote-environment.sh              |  2 ++
 t/t5522-pull-symlink.sh                    |  1 +
 t/t5523-push-upstream.sh                   |  1 +
 t/t5527-fetch-odd-refs.sh                  |  1 +
 t/t5529-push-errors.sh                     |  2 ++
 t/t5546-receive-limits.sh                  |  2 ++
 t/t5547-push-quarantine.sh                 |  2 ++
 t/t5604-clone-reference.sh                 |  1 +
 t/t5606-clone-options.sh                   |  1 +
 t/t5613-info-alternate.sh                  |  2 ++
 t/t5705-session-id-in-capabilities.sh      |  1 +
 t/t5810-proto-disable-local.sh             |  2 ++
 t/t5813-proto-disable-ssh.sh               |  2 ++
 t/t6011-rev-list-with-bad-commit.sh        |  1 +
 t/t6014-rev-list-all.sh                    |  1 +
 t/t6021-rev-list-exclude-hidden.sh         |  1 +
 t/t6439-merge-co-error-msgs.sh             |  1 +
 t/t7105-reset-patch.sh                     |  2 ++
 t/t7106-reset-unborn-branch.sh             |  2 ++
 t/t7107-reset-pathspec-file.sh             |  1 +
 t/t7301-clean-interactive.sh               |  1 +
 t/t7403-submodule-sync.sh                  |  1 +
 t/t7409-submodule-detached-work-tree.sh    |  1 +
 t/t7416-submodule-dash-url.sh              |  2 ++
 t/t7450-bad-git-dotfiles.sh                |  2 ++
 t/t7701-repack-unpack-unreachable.sh       |  1 +
 69 files changed, 158 insertions(+), 56 deletions(-)

Range-diff against v1:
 1:  84393ca3139 <  -:  ----------- t6021: mark as passing with SANITIZE=leak
 2:  2ad81be0d7a !  1:  3de29c6d75f tests: mark tests as passing with SANITIZE=leak
    @@ Metadata
      ## Commit message ##
         tests: mark tests as passing with SANITIZE=leak
     
    -    When the "ab/various-leak-fixes" topic was merged in [1] only
    -    t6021 (which was fixed in the preceding commit) would fail if the
    -    tests were run in the "GIT_TEST_PASSING_SANITIZE_LEAK=check" mode,
    -    i.e. to check whether we marked all leak-free tests with
    -    "TEST_PASSES_SANITIZE_LEAK=true".
    +    When the "ab/various-leak-fixes" topic was merged in [1] only t6021
    +    would fail if the tests were run in the
    +    "GIT_TEST_PASSING_SANITIZE_LEAK=check" mode, i.e. to check whether we
    +    marked all leak-free tests with "TEST_PASSES_SANITIZE_LEAK=true".
     
         Since then we've had various tests starting to pass under
         SANITIZE=leak. Let's mark those as passing, this is when they started
    @@ t/t6014-rev-list-all.sh
      
      
     
    + ## t/t6021-rev-list-exclude-hidden.sh ##
    +@@
    + 
    + test_description='git rev-list --exclude-hidden test'
    + 
    ++TEST_PASSES_SANITIZE_LEAK=true
    + . ./test-lib.sh
    + 
    + test_expect_success 'setup' '
    +
      ## t/t7403-submodule-sync.sh ##
     @@ t/t7403-submodule-sync.sh: These tests exercise the "git submodule sync" subcommand.
      GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
 3:  a8b373ddef9 =  2:  5036712391d bundle.c: don't leak the "args" in the "struct child_process"
 4:  5be87f9720c !  3:  a840a1cb330 commit-graph: use free() instead of UNLEAK()
    @@ Commit message
         commit-graph: use free() instead of UNLEAK()
     
         In 0bfb48e6723 (builtin/commit-graph.c: UNLEAK variables, 2018-10-03)
    -    this was made to UNLEAK(), but we can just as easily free() the memory
    -    instead.
    +    this was made to UNLEAK(), but we can just as easily invoke the
    +    free_commit_graph() function added in c3756d5b7fc (commit-graph: add
    +    free_commit_graph, 2018-07-11) instead.
     
         Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
     
    @@ builtin/commit-graph.c: static int graph_verify(int argc, const char **argv, con
     -	UNLEAK(graph);
     -	return verify_commit_graph(the_repository, graph, flags);
     +	ret = verify_commit_graph(the_repository, graph, flags);
    -+	free(graph);
    ++	free_commit_graph(graph);
     +	return ret;
      }
      
 5:  49e6714939d =  4:  c05620cef49 clone: use free() instead of UNLEAK()
 8:  21670099c84 !  5:  62af6557760 reset: fix cmd_reset() leaks with a clear_pathspec() call
    @@ Metadata
     Author: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
     
      ## Commit message ##
    -    reset: fix cmd_reset() leaks with a clear_pathspec() call
    +    various: add missing clear_pathspec(), fix leaks
     
    -    Add clear_pathspec() calls to cmd_reset(), including to the codepaths
    -    where we'd return early.
    +    Fix memory leaks resulting from a missing clear_pathspec().
    +
    +    - archive.c: Plug a leak in the "struct archiver_args", and
    +      clear_pathspec() the "pathspec" member that the "parse_pathspec_arg()"
    +      call in this function populates.
    +
    +    - builtin/clean.c: Fix a memory leak that's been with us since
    +      893d839970c (clean: convert to use parse_pathspec, 2013-07-14).
    +
    +    - builtin/reset.c: Add clear_pathspec() calls to cmd_reset(),
    +      including to the codepaths where we'd return early.
    +
    +    - builtin/stash.c: Call clear_pathspec() on the pathspec initialized
    +      in push_stash().
     
         Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
     
    + ## archive.c ##
    +@@ archive.c: int write_archive(int argc, const char **argv, const char *prefix,
    + 
    + 	string_list_clear_func(&args.extra_files, extra_file_info_clear);
    + 	free(args.refname);
    ++	clear_pathspec(&args.pathspec);
    + 
    + 	return rc;
    + }
    +
    + ## builtin/clean.c ##
    +@@ builtin/clean.c: int cmd_clean(int argc, const char **argv, const char *prefix)
    + 	strbuf_release(&buf);
    + 	string_list_clear(&del_list, 0);
    + 	string_list_clear(&exclude_list, 0);
    ++	clear_pathspec(&pathspec);
    + 	return (errors != 0);
    + }
    +
      ## builtin/reset.c ##
     @@ builtin/reset.c: int cmd_reset(int argc, const char **argv, const char *prefix)
      		if (reset_type != NONE)
    @@ builtin/reset.c: int cmd_reset(int argc, const char **argv, const char *prefix)
      	return update_ref_status;
      }
     
    + ## builtin/stash.c ##
    +@@ builtin/stash.c: static int push_stash(int argc, const char **argv, const char *prefix,
    + 		OPT_PATHSPEC_FILE_NUL(&pathspec_file_nul),
    + 		OPT_END()
    + 	};
    ++	int ret;
    + 
    + 	if (argc) {
    + 		force_assume = !strcmp(argv[0], "-p");
    +@@ builtin/stash.c: static int push_stash(int argc, const char **argv, const char *prefix,
    + 		die(_("the option '%s' requires '%s'"), "--pathspec-file-nul", "--pathspec-from-file");
    + 	}
    + 
    +-	return do_push_stash(&ps, stash_msg, quiet, keep_index, patch_mode,
    +-			     include_untracked, only_staged);
    ++	ret = do_push_stash(&ps, stash_msg, quiet, keep_index, patch_mode,
    ++			    include_untracked, only_staged);
    ++	clear_pathspec(&ps);
    ++	return ret;
    + }
    + 
    + static int push_stash_unassumed(int argc, const char **argv, const char *prefix)
    +
    + ## t/t5001-archive-attr.sh ##
    +@@
    + test_description='git archive attribute tests'
    + 
    + TEST_CREATE_REPO_NO_TEMPLATE=1
    ++TEST_PASSES_SANITIZE_LEAK=true
    + . ./test-lib.sh
    + 
    + SUBSTFORMAT='%H (%h)%n'
    +
    + ## t/t5004-archive-corner-cases.sh ##
    +@@
    + #!/bin/sh
    + 
    + test_description='test corner cases of git-archive'
    ++
    ++TEST_PASSES_SANITIZE_LEAK=true
    + . ./test-lib.sh
    + 
    + # the 10knuls.tar file is used to test for an empty git generated tar
    +
      ## t/t7105-reset-patch.sh ##
     @@
      #!/bin/sh
    @@ t/t7107-reset-pathspec-file.sh
      . ./test-lib.sh
      
      test_tick
    +
    + ## t/t7301-clean-interactive.sh ##
    +@@
    + 
    + test_description='git clean -i basic tests'
    + 
    ++TEST_PASSES_SANITIZE_LEAK=true
    + . ./test-lib.sh
    + . "$TEST_DIRECTORY"/lib-terminal.sh
    + 
 9:  77fcdeb9284 !  6:  7cea3da9fae name-rev: don't xstrdup() an already dup'd string
    @@ Commit message
         we'd then xstrdup() again, leaking memory. See [1] and [2] for how
         this leak came about.
     
    +    We could xstrdup() only if "shorten_unambiguous" wasn't true, but
    +    let's instead inline this code, so that information on whether we need
    +    to xstrdup() is contained within add_to_tip_table().
    +
         1. 98c5c4ad015 (name-rev: allow to specify a subpath for --refs
            option, 2013-06-18)
         2. b23e0b9353e (name-rev: allow converting the exact object name at
    @@ Commit message
         Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
     
      ## builtin/name-rev.c ##
    +@@ builtin/name-rev.c: static int subpath_matches(const char *path, const char *filter)
    + 	return -1;
    + }
    + 
    +-static const char *name_ref_abbrev(const char *refname, int shorten_unambiguous)
    +-{
    +-	if (shorten_unambiguous)
    +-		refname = shorten_unambiguous_ref(refname, 0);
    +-	else if (skip_prefix(refname, "refs/heads/", &refname))
    +-		; /* refname already advanced */
    +-	else
    +-		skip_prefix(refname, "refs/", &refname);
    +-	return refname;
    +-}
    +-
    + struct name_ref_data {
    + 	int tags_only;
    + 	int name_only;
     @@ builtin/name-rev.c: static void add_to_tip_table(const struct object_id *oid, const char *refname,
    + 			     int shorten_unambiguous, struct commit *commit,
    + 			     timestamp_t taggerdate, int from_tag, int deref)
    + {
    +-	refname = name_ref_abbrev(refname, shorten_unambiguous);
    ++	char *short_refname = NULL;
    ++
    ++	if (shorten_unambiguous)
    ++		short_refname = shorten_unambiguous_ref(refname, 0);
    ++	else if (skip_prefix(refname, "refs/heads/", &refname))
    ++		; /* refname already advanced */
    ++	else
    ++		skip_prefix(refname, "refs/", &refname);
      
      	ALLOC_GROW(tip_table.table, tip_table.nr + 1, tip_table.alloc);
      	oidcpy(&tip_table.table[tip_table.nr].oid, oid);
     -	tip_table.table[tip_table.nr].refname = xstrdup(refname);
    -+	tip_table.table[tip_table.nr].refname = shorten_unambiguous ? refname :
    -+		xstrdup(refname);
    ++	tip_table.table[tip_table.nr].refname = short_refname ?
    ++		short_refname : xstrdup(refname);
      	tip_table.table[tip_table.nr].commit = commit;
      	tip_table.table[tip_table.nr].taggerdate = taggerdate;
      	tip_table.table[tip_table.nr].from_tag = from_tag;
10:  81555cce790 =  7:  b5978d75c6a repack: fix leaks on error with "goto cleanup"
11:  ee05254eb6a =  8:  468615570f4 worktree: fix a trivial leak in prune_worktrees()
 7:  e5a0134d1bb !  9:  8c5c964d872 stash: fix a "struct pathspec" leak
    @@ Metadata
     Author: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
     
      ## Commit message ##
    -    stash: fix a "struct pathspec" leak
    +    http-backend.c: fix "dir" and "cmd_arg" leaks in cmd_main()
     
    -    Call clear_pathspec() on the pathspec initialized in
    -    push_stash(). Initializing that structure in this way is already done
    -    by a few other callers, and now we have:
    +    Free the "dir" variable after we're done with it. Before
    +    917adc03608 (http-backend: add GIT_PROJECT_ROOT environment var,
    +    2009-10-30) there was no leak here, as we'd get it via getenv(), but
    +    since 917adc03608 we've xstrdup()'d it (or the equivalent), so we need
    +    to free() it.
     
    -            $ git grep -e 'struct pathspec.* = { 0 }' -e memset.pathspec
    -            add-interactive.c:              struct pathspec ps_selected = { 0 };
    -            builtin/sparse-checkout.c:              struct pathspec p = { 0 };
    -            builtin/stash.c:        struct pathspec ps = { 0 };
    -            pathspec.c:     memset(pathspec, 0, sizeof(*pathspec));
    -            wt-status.c:                    struct pathspec ps = { 0 };
    +    We also need to free the "cmd_arg" variable, which has been leaked
    +    ever since it was added in 2f4038ab337 (Git-aware CGI to provide dumb
    +    HTTP transport, 2009-10-30).
     
         Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
     
    - ## builtin/stash.c ##
    -@@ builtin/stash.c: static int push_stash(int argc, const char **argv, const char *prefix,
    - 	int pathspec_file_nul = 0;
    - 	const char *stash_msg = NULL;
    - 	const char *pathspec_from_file = NULL;
    --	struct pathspec ps;
    -+	struct pathspec ps = { 0 };
    - 	struct option options[] = {
    - 		OPT_BOOL('k', "keep-index", &keep_index,
    - 			 N_("keep index")),
    -@@ builtin/stash.c: static int push_stash(int argc, const char **argv, const char *prefix,
    - 		OPT_PATHSPEC_FILE_NUL(&pathspec_file_nul),
    - 		OPT_END()
    - 	};
    -+	int ret;
    + ## http-backend.c ##
    +@@ http-backend.c: int cmd_main(int argc, const char **argv)
    + 	if (!getenv("GIT_HTTP_EXPORT_ALL") &&
    + 	    access("git-daemon-export-ok", F_OK) )
    + 		not_found(&hdr, "Repository not exported: '%s'", dir);
    ++	free(dir);
      
    - 	if (argc) {
    - 		force_assume = !strcmp(argv[0], "-p");
    -@@ builtin/stash.c: static int push_stash(int argc, const char **argv, const char *prefix,
    - 		die(_("the option '%s' requires '%s'"), "--pathspec-file-nul", "--pathspec-from-file");
    - 	}
    + 	http_config();
    + 	max_request_buffer = git_env_ulong("GIT_HTTP_MAX_REQUEST_BUFFER",
    +@@ http-backend.c: int cmd_main(int argc, const char **argv)
    + 		setenv(GIT_PROTOCOL_ENVIRONMENT, proto_header, 0);
      
    --	return do_push_stash(&ps, stash_msg, quiet, keep_index, patch_mode,
    --			     include_untracked, only_staged);
    -+	ret = do_push_stash(&ps, stash_msg, quiet, keep_index, patch_mode,
    -+			    include_untracked, only_staged);
    -+	clear_pathspec(&ps);
    -+	return ret;
    + 	cmd->imp(&hdr, cmd_arg);
    ++	free(cmd_arg);
    + 	return 0;
      }
    - 
    - static int push_stash_unassumed(int argc, const char **argv, const char *prefix)
12:  9be5b0c7836 = 10:  fd34c4817f4 http-backend.c: fix cmd_main() memory leak, refactor reg{exec,free}()
13:  78f12259ac5 = 11:  f7005f32cc0 commit-graph: fix a parse_options_concat() leak
14:  9df41b090b4 = 12:  bf0e9bc5fa6 show-branch: free() allocated "head" before return
15:  8deeee4278d ! 13:  b157092e8d0 builtin/merge.c: always free "struct strbuf msg"
    @@ Commit message
         builtin/merge.c: always free "struct strbuf msg"
     
         Follow-up 465028e0e25 (merge: add missing strbuf_release(),
    -    2021-10-07) and free "&msg" also when we'd "goto done" from the scope
    -    it's allocated in.
    +    2021-10-07) and address the "msg" memory leak in this block. We could
    +    free "&msg" before the "goto done" here, but even better is to avoid
    +    allocating it in the first place.
     
    +    By repeating the "Fast-forward" string here we can avoid using a
    +    "struct strbuf" altogether.
    +
    +    Suggested-by: René Scharfe <l.s.r@web.de>
         Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
     
      ## builtin/merge.c ##
     @@ builtin/merge.c: int cmd_merge(int argc, const char **argv, const char *prefix)
    + 			!common->next &&
    + 			oideq(&common->item->object.oid, &head_commit->object.oid)) {
    + 		/* Again the most common case of merging one remote. */
    +-		struct strbuf msg = STRBUF_INIT;
    ++		const char *msg = have_message ?
    ++			"Fast-forward (no commit created; -m option ignored)" :
    ++			"Fast-forward";
    + 		struct commit *commit;
    + 
    + 		if (verbosity >= 0) {
    +@@ builtin/merge.c: int cmd_merge(int argc, const char **argv, const char *prefix)
    + 			       find_unique_abbrev(&remoteheads->item->object.oid,
    + 						  DEFAULT_ABBREV));
    + 		}
    +-		strbuf_addstr(&msg, "Fast-forward");
    +-		if (have_message)
    +-			strbuf_addstr(&msg,
    +-				" (no commit created; -m option ignored)");
      		commit = remoteheads->item;
      		if (!commit) {
      			ret = 1;
    -+			strbuf_release(&msg);
    - 			goto done;
    - 		}
    - 
     @@ builtin/merge.c: int cmd_merge(int argc, const char **argv, const char *prefix)
    - 					  overwrite_ignore)) {
    - 			apply_autostash(git_path_merge_autostash(the_repository));
    - 			ret = 1;
    -+			strbuf_release(&msg);
      			goto done;
      		}
      
    +-		finish(head_commit, remoteheads, &commit->object.oid, msg.buf);
    ++		finish(head_commit, remoteheads, &commit->object.oid, msg);
    + 		remove_merge_branch_state(the_repository);
    +-		strbuf_release(&msg);
    + 		goto done;
    + 	} else if (!remoteheads->next && common->next)
    + 		;
    +
    + ## t/t6439-merge-co-error-msgs.sh ##
    +@@ t/t6439-merge-co-error-msgs.sh: test_description='unpack-trees error messages'
    + GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
    + export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
    + 
    ++TEST_PASSES_SANITIZE_LEAK=true
    + . ./test-lib.sh
    + 
    + 
16:  95d59b914d0 ! 14:  bdd2bc9a956 builtin/merge.c: free "&buf" on "Your local changes..." error
    @@ builtin/merge.c: int cmd_merge(int argc, const char **argv, const char *prefix)
      			}
      
      			/* See if it is really trivial. */
    -
    - ## t/t6439-merge-co-error-msgs.sh ##
    -@@ t/t6439-merge-co-error-msgs.sh: test_description='unpack-trees error messages'
    - GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
    - export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
    - 
    -+TEST_PASSES_SANITIZE_LEAK=true
    - . ./test-lib.sh
    - 
    - 
17:  ae2f4931315 = 15:  d5210017cab connected.c: free(new_pack) in check_connected()
18:  aa4df0e1b5c ! 16:  2016b4ddd0b object-file.c: free the "t.tag" in check_tag()
    @@ Metadata
     Author: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
     
      ## Commit message ##
    -    object-file.c: free the "t.tag" in check_tag()
    +    object-file.c: release the "tag" in check_tag()
     
         Fix a memory leak that's been with us ever since c879daa2372 (Make
         hash-object more robust against malformed objects, 2011-02-05). With
    @@ Commit message
         tags into a throwaway variable on the stack, but weren't freeing the
         "item->tag" we might malloc() when doing so.
     
    +    The clearing that release_tag_memory() does for us is redundant here,
    +    but let's use it as-is anyway. It only has one other existing caller,
    +    which does need the tag to be cleared.
    +
         Mark the tests that now pass in their entirety as passing under
         "SANITIZE=leak", which means we'll test them as part of the
         "linux-leaks" CI job.
    @@ object-file.c: static void check_tag(const void *buf, size_t size)
      	memset(&t, 0, sizeof(t));
      	if (parse_tag_buffer(the_repository, &t, buf, size))
      		die(_("corrupt tag"));
    -+	free(t.tag);
    ++	release_tag_memory(&t);
      }
      
      static int index_mem(struct index_state *istate,
20:  8ecc68c3e93 ! 17:  fa2e8a7d297 grep API: plug memory leaks by freeing "header_list"
    @@ Metadata
     Author: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
     
      ## Commit message ##
    -    grep API: plug memory leaks by freeing "header_list"
    +    grep.c: refactor free_grep_patterns()
     
    -    When the "header_list" struct member was added in [1] it wasn't made
    -    to free the list using loop added for the adjacent "pattern_list"
    -    member, see [2] for when we started freeing it.
    +    Refactor the free_grep_patterns() function to split out the freeing of
    +    the "struct grep_pat" it contains, right now we're only freeing the
    +    "pattern_list", but we should be freeing another member of the same
    +    type, which we'll do in the subsequent commit.
     
    -    Let's start doing o by splitting up the loop in free_grep_patterns()
    -    into a utility function. This makes e.g. this command leak-free when
    -    run on git.git:
    +    Let's also replace the "return" if we don't have an
    +    "opt->pattern_expression" with a conditional call of
    +    free_pattern_expr().
     
    -            ./git -P log -1 --color=always --author=A origin/master
    +    Before db84376f981 (grep.c: remove "extended" in favor of
    +    "pattern_expression", fix segfault, 2022-10-11) the pattern here was:
     
    -    1. 80235ba79ef ("log --author=me --grep=it" should find intersection,
    -       not union, 2010-01-17)
    -    2. b48fb5b6a95 (grep: free expressions and patterns when done.,
    -       2006-09-27)
    +            if (!x)
    +                    return;
    +            free(y);
    +
    +    But after the cleanup in db84376f981 (which was a narrow segfault fix,
    +    and thus avoided refactoring this) we ended up with:
    +
    +            if (!x)
    +                    return;
    +            free(x);
    +
    +    Let's instead do:
    +
    +            if (x)
    +                    free(x);
    +
    +    This doesn't matter for the subsequent change, but as we're
    +    refactoring this function let's make it easier to reason about, and to
    +    extend in the future, i.e. if we start to free free() members that
    +    come after "pattern_expression" in the "struct grep_opt".
     
         Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
     
    @@ grep.c: void free_grep_patterns(struct grep_opt *opt)
      		free(p);
      	}
     +}
    -+
    + 
    +-	if (!opt->pattern_expression)
    +-		return;
    +-	free_pattern_expr(opt->pattern_expression);
     +void free_grep_patterns(struct grep_opt *opt)
     +{
     +	free_grep_pat(opt->pattern_list);
    -+	free_grep_pat(opt->header_list);
    ++
    ++	if (opt->pattern_expression)
    ++		free_pattern_expr(opt->pattern_expression);
    + }
      
    - 	if (opt->pattern_expression)
    - 		free_pattern_expr(opt->pattern_expression);
    + static const char *end_of_line(const char *cp, unsigned long *left)
19:  7928470addb ! 18:  3fcf7054708 grep.c: make it easier to extend free_grep_patterns()
    @@ Metadata
     Author: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
     
      ## Commit message ##
    -    grep.c: make it easier to extend free_grep_patterns()
    +    grep API: plug memory leaks by freeing "header_list"
     
    -    Before db84376f981 (grep.c: remove "extended" in favor of
    -    "pattern_expression", fix segfault, 2022-10-11) the pattern here was:
    +    When the "header_list" struct member was added in [1] it wasn't made
    +    to free the list using loop added for the adjacent "pattern_list"
    +    member, see [2] for when we started freeing it.
     
    -            if (!x)
    -                    return;
    -            free(y);
    +    This makes e.g. this command leak-free when run on git.git:
     
    -    But after the cleanup in db84376f981 (which was a narrow segfault fix,
    -    and thus avoided refactoring this) we ended up with:
    +            ./git -P log -1 --color=always --author=A origin/master
     
    -            if (!x)
    -                    return;
    -            free(x);
    -
    -    Let's instead do:
    -
    -            if (x)
    -                    free(x);
    -
    -    This doesn't matter for now, but makes the free_grep_patterns() easier
    -    to reason about, as we don't have to wonder why we're doing an early
    -    "return" if and when we add free()-ing of any members that come after
    -    "pattern_expression" in the "struct grep_opt".
    +    1. 80235ba79ef ("log --author=me --grep=it" should find intersection,
    +       not union, 2010-01-17)
    +    2. b48fb5b6a95 (grep: free expressions and patterns when done.,
    +       2006-09-27)
     
         Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
     
      ## grep.c ##
    -@@ grep.c: void free_grep_patterns(struct grep_opt *opt)
    - 		free(p);
    - 	}
    - 
    --	if (!opt->pattern_expression)
    --		return;
    --	free_pattern_expr(opt->pattern_expression);
    -+	if (opt->pattern_expression)
    -+		free_pattern_expr(opt->pattern_expression);
    - }
    +@@ grep.c: static void free_grep_pat(struct grep_pat *pattern)
    + void free_grep_patterns(struct grep_opt *opt)
    + {
    + 	free_grep_pat(opt->pattern_list);
    ++	free_grep_pat(opt->header_list);
      
    - static const char *end_of_line(const char *cp, unsigned long *left)
    + 	if (opt->pattern_expression)
    + 		free_pattern_expr(opt->pattern_expression);
 6:  bc45aee530c ! 19:  fa5d657312f archive.c: call clear_pathspec() in write_archive()
    @@ Metadata
     Author: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
     
      ## Commit message ##
    -    archive.c: call clear_pathspec() in write_archive()
    +    receive-pack: free() the "ref_name" in "struct command"
     
    -    Plug a leak in the "struct archiver_args", and clear_pathspec() the
    -    "pathspec" member that the "parse_pathspec_arg()" call in this
    -    function populates.
    +    Fix a memory leak that's been with us since this code was introduced
    +    in 575f497456e (Add first cut at "git-receive-pack", 2005-06-29), see
    +    eb1af2df0b1 (git-receive-pack: start parsing ref update commands,
    +    2005-06-29) for the later change that refactored the code to add the
    +    "ref_name" member.
     
         Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
     
    - ## archive.c ##
    -@@ archive.c: int write_archive(int argc, const char **argv, const char *prefix,
    + ## builtin/receive-pack.c ##
    +@@ builtin/receive-pack.c: static struct command **queue_command(struct command **tail,
    + 	return &cmd->next;
    + }
      
    - 	string_list_clear_func(&args.extra_files, extra_file_info_clear);
    - 	free(args.refname);
    -+	clear_pathspec(&args.pathspec);
    ++static void free_commands(struct command *commands)
    ++{
    ++	while (commands) {
    ++		struct command *next = commands->next;
    ++		free(commands);
    ++		commands = next;
    ++	}
    ++}
    ++
    + static void queue_commands_from_cert(struct command **tail,
    + 				     struct strbuf *push_cert)
    + {
    +@@ builtin/receive-pack.c: int cmd_receive_pack(int argc, const char **argv, const char *prefix)
    + 		run_receive_hook(commands, "post-receive", 1,
    + 				 &push_options);
    + 		run_update_post_hook(commands);
    ++		free_commands(commands);
    + 		string_list_clear(&push_options, 0);
    + 		if (auto_gc) {
    + 			struct child_process proc = CHILD_PROCESS_INIT;
    +
    + ## t/t5405-send-pack-rewind.sh ##
    +@@ t/t5405-send-pack-rewind.sh: test_description='forced push to replace commit we do not have'
    + GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
    + export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
      
    - 	return rc;
    - }
    ++TEST_PASSES_SANITIZE_LEAK=true
    + . ./test-lib.sh
    + 
    + test_expect_success setup '
     
    - ## t/t5001-archive-attr.sh ##
    + ## t/t5406-remote-rejects.sh ##
     @@
    - test_description='git archive attribute tests'
      
    - TEST_CREATE_REPO_NO_TEMPLATE=1
    + test_description='remote push rejects are reported by client'
    + 
     +TEST_PASSES_SANITIZE_LEAK=true
      . ./test-lib.sh
      
    - SUBSTFORMAT='%H (%h)%n'
    + test_expect_success 'setup' '
     
    - ## t/t5004-archive-corner-cases.sh ##
    + ## t/t5507-remote-environment.sh ##
     @@
      #!/bin/sh
      
    - test_description='test corner cases of git-archive'
    + test_description='check environment showed to remote side of transports'
     +
     +TEST_PASSES_SANITIZE_LEAK=true
      . ./test-lib.sh
      
    - # the 10knuls.tar file is used to test for an empty git generated tar
    + test_expect_success 'set up "remote" push situation' '
    +
    + ## t/t5522-pull-symlink.sh ##
    +@@
    + 
    + test_description='pulling from symlinked subdir'
    + 
    ++TEST_PASSES_SANITIZE_LEAK=true
    + . ./test-lib.sh
    + 
    + # The scenario we are building:
    +
    + ## t/t5527-fetch-odd-refs.sh ##
    +@@ t/t5527-fetch-odd-refs.sh: test_description='test fetching of oddly-named refs'
    + GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
    + export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
    + 
    ++TEST_PASSES_SANITIZE_LEAK=true
    + . ./test-lib.sh
    + 
    + # afterwards we will have:
    +
    + ## t/t5705-session-id-in-capabilities.sh ##
    +@@
    + 
    + test_description='session ID in capabilities'
    + 
    ++TEST_PASSES_SANITIZE_LEAK=true
    + . ./test-lib.sh
    + 
    + REPO="$(pwd)/repo"
 -:  ----------- > 20:  e5af27134df push: free_refs() the "local_refs" in set_refspecs()
-- 
2.39.0.1153.g589e4efe9dc


^ permalink raw reply	[flat|nested] 193+ messages in thread

* [PATCH v2 01/20] tests: mark tests as passing with SANITIZE=leak
  2022-12-30  2:18 ` [PATCH v2 00/20] leak fixes: various simple leak fixes Ævar Arnfjörð Bjarmason
@ 2022-12-30  2:18   ` Ævar Arnfjörð Bjarmason
  2022-12-30  2:18   ` [PATCH v2 02/20] bundle.c: don't leak the "args" in the "struct child_process" Ævar Arnfjörð Bjarmason
                     ` (19 subsequent siblings)
  20 siblings, 0 replies; 193+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2022-12-30  2:18 UTC (permalink / raw)
  To: git
  Cc: René Scharfe, Junio C Hamano, Eric Sunshine,
	Ævar Arnfjörð Bjarmason

When the "ab/various-leak-fixes" topic was merged in [1] only t6021
would fail if the tests were run in the
"GIT_TEST_PASSING_SANITIZE_LEAK=check" mode, i.e. to check whether we
marked all leak-free tests with "TEST_PASSES_SANITIZE_LEAK=true".

Since then we've had various tests starting to pass under
SANITIZE=leak. Let's mark those as passing, this is when they started
to pass, narrowed down with "git bisect":

- t5317-pack-objects-filter-objects.sh: In
  faebba436e6 (list-objects-filter: plug pattern_list leak, 2022-12-01).

- t3210-pack-refs.sh, t5613-info-alternate.sh,
  t7403-submodule-sync.sh: In 189e97bc4ba (diff: remove parseopts member
  from struct diff_options, 2022-12-01).

- t1408-packed-refs.sh: In ab91f6b7c42 (Merge branch
  'rs/diff-parseopts', 2022-12-19).

- t0023-crlf-am.sh, t4152-am-subjects.sh, t4254-am-corrupt.sh,
  t4256-am-format-flowed.sh, t4257-am-interactive.sh,
  t5403-post-checkout-hook.sh: In a658e881c13 (am: don't pass strvec to
  apply_parse_options(), 2022-12-13)

- t1301-shared-repo.sh, t1302-repo-version.sh: In b07a819c05f (reflog:
  clear leftovers in reflog_expiry_cleanup(), 2022-12-13).

- t1304-default-acl.sh, t1410-reflog.sh,
  t5330-no-lazy-fetch-with-commit-graph.sh, t5502-quickfetch.sh,
  t5604-clone-reference.sh, t6014-rev-list-all.sh,
  t7701-repack-unpack-unreachable.sh: In b0c61be3209 (Merge branch
  'rs/reflog-expiry-cleanup', 2022-12-26)

1. 9ea1378d046 (Merge branch 'ab/various-leak-fixes', 2022-12-14)

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 t/t0023-crlf-am.sh                         | 1 +
 t/t1301-shared-repo.sh                     | 1 +
 t/t1302-repo-version.sh                    | 1 +
 t/t1304-default-acl.sh                     | 1 +
 t/t1408-packed-refs.sh                     | 1 +
 t/t1410-reflog.sh                          | 1 +
 t/t3210-pack-refs.sh                       | 1 +
 t/t4152-am-subjects.sh                     | 2 ++
 t/t4254-am-corrupt.sh                      | 2 ++
 t/t4256-am-format-flowed.sh                | 1 +
 t/t4257-am-interactive.sh                  | 2 ++
 t/t5317-pack-objects-filter-objects.sh     | 1 +
 t/t5330-no-lazy-fetch-with-commit-graph.sh | 1 +
 t/t5403-post-checkout-hook.sh              | 1 +
 t/t5502-quickfetch.sh                      | 1 +
 t/t5604-clone-reference.sh                 | 1 +
 t/t5613-info-alternate.sh                  | 2 ++
 t/t6014-rev-list-all.sh                    | 1 +
 t/t6021-rev-list-exclude-hidden.sh         | 1 +
 t/t7403-submodule-sync.sh                  | 1 +
 t/t7701-repack-unpack-unreachable.sh       | 1 +
 21 files changed, 25 insertions(+)

diff --git a/t/t0023-crlf-am.sh b/t/t0023-crlf-am.sh
index f9bbb91f64e..575805513a3 100755
--- a/t/t0023-crlf-am.sh
+++ b/t/t0023-crlf-am.sh
@@ -2,6 +2,7 @@
 
 test_description='Test am with auto.crlf'
 
+TEST_PASSES_SANITIZE_LEAK=true
 . ./test-lib.sh
 
 cat >patchfile <<\EOF
diff --git a/t/t1301-shared-repo.sh b/t/t1301-shared-repo.sh
index 93a2f91f8a5..a1251f65100 100755
--- a/t/t1301-shared-repo.sh
+++ b/t/t1301-shared-repo.sh
@@ -8,6 +8,7 @@ test_description='Test shared repository initialization'
 GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
 export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
 
+TEST_PASSES_SANITIZE_LEAK=true
 . ./test-lib.sh
 
 # Remove a default ACL from the test dir if possible.
diff --git a/t/t1302-repo-version.sh b/t/t1302-repo-version.sh
index 0acabb6d11b..83c327ac2c8 100755
--- a/t/t1302-repo-version.sh
+++ b/t/t1302-repo-version.sh
@@ -5,6 +5,7 @@
 
 test_description='Test repository version check'
 
+TEST_PASSES_SANITIZE_LEAK=true
 . ./test-lib.sh
 
 test_expect_success 'setup' '
diff --git a/t/t1304-default-acl.sh b/t/t1304-default-acl.sh
index c69ae41306c..31b89dd9693 100755
--- a/t/t1304-default-acl.sh
+++ b/t/t1304-default-acl.sh
@@ -9,6 +9,7 @@ test_description='Test repository with default ACL'
 # => this must come before . ./test-lib.sh
 umask 077
 
+TEST_PASSES_SANITIZE_LEAK=true
 . ./test-lib.sh
 
 # We need an arbitrary other user give permission to using ACLs. root
diff --git a/t/t1408-packed-refs.sh b/t/t1408-packed-refs.sh
index 41ba1f1d7fc..9469c79a585 100755
--- a/t/t1408-packed-refs.sh
+++ b/t/t1408-packed-refs.sh
@@ -5,6 +5,7 @@ test_description='packed-refs entries are covered by loose refs'
 GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
 export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
 
+TEST_PASSES_SANITIZE_LEAK=true
 . ./test-lib.sh
 
 test_expect_success setup '
diff --git a/t/t1410-reflog.sh b/t/t1410-reflog.sh
index aa59954f6c5..6c45965b1e4 100755
--- a/t/t1410-reflog.sh
+++ b/t/t1410-reflog.sh
@@ -7,6 +7,7 @@ test_description='Test prune and reflog expiration'
 GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
 export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
 
+TEST_PASSES_SANITIZE_LEAK=true
 . ./test-lib.sh
 
 check_have () {
diff --git a/t/t3210-pack-refs.sh b/t/t3210-pack-refs.sh
index 577f32dc71f..07a0ff93def 100755
--- a/t/t3210-pack-refs.sh
+++ b/t/t3210-pack-refs.sh
@@ -12,6 +12,7 @@ semantic is still the same.
 GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
 export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
 
+TEST_PASSES_SANITIZE_LEAK=true
 . ./test-lib.sh
 
 test_expect_success 'enable reflogs' '
diff --git a/t/t4152-am-subjects.sh b/t/t4152-am-subjects.sh
index 4c68245acad..9f2edba1f83 100755
--- a/t/t4152-am-subjects.sh
+++ b/t/t4152-am-subjects.sh
@@ -1,6 +1,8 @@
 #!/bin/sh
 
 test_description='test subject preservation with format-patch | am'
+
+TEST_PASSES_SANITIZE_LEAK=true
 . ./test-lib.sh
 
 make_patches() {
diff --git a/t/t4254-am-corrupt.sh b/t/t4254-am-corrupt.sh
index 54be7da1611..45f1d4f95e5 100755
--- a/t/t4254-am-corrupt.sh
+++ b/t/t4254-am-corrupt.sh
@@ -1,6 +1,8 @@
 #!/bin/sh
 
 test_description='git am with corrupt input'
+
+TEST_PASSES_SANITIZE_LEAK=true
 . ./test-lib.sh
 
 make_mbox_with_nul () {
diff --git a/t/t4256-am-format-flowed.sh b/t/t4256-am-format-flowed.sh
index 2369c4e17ad..1015273bc82 100755
--- a/t/t4256-am-format-flowed.sh
+++ b/t/t4256-am-format-flowed.sh
@@ -2,6 +2,7 @@
 
 test_description='test format=flowed support of git am'
 
+TEST_PASSES_SANITIZE_LEAK=true
 . ./test-lib.sh
 
 test_expect_success 'setup' '
diff --git a/t/t4257-am-interactive.sh b/t/t4257-am-interactive.sh
index aed8f4de3d6..f26d7fd2dbd 100755
--- a/t/t4257-am-interactive.sh
+++ b/t/t4257-am-interactive.sh
@@ -1,6 +1,8 @@
 #!/bin/sh
 
 test_description='am --interactive tests'
+
+TEST_PASSES_SANITIZE_LEAK=true
 . ./test-lib.sh
 
 test_expect_success 'set up patches to apply' '
diff --git a/t/t5317-pack-objects-filter-objects.sh b/t/t5317-pack-objects-filter-objects.sh
index 5b707d911b5..b26d476c646 100755
--- a/t/t5317-pack-objects-filter-objects.sh
+++ b/t/t5317-pack-objects-filter-objects.sh
@@ -5,6 +5,7 @@ test_description='git pack-objects using object filtering'
 GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
 export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
 
+TEST_PASSES_SANITIZE_LEAK=true
 . ./test-lib.sh
 
 # Test blob:none filter.
diff --git a/t/t5330-no-lazy-fetch-with-commit-graph.sh b/t/t5330-no-lazy-fetch-with-commit-graph.sh
index 2cc7fd7a476..5eb28f0512d 100755
--- a/t/t5330-no-lazy-fetch-with-commit-graph.sh
+++ b/t/t5330-no-lazy-fetch-with-commit-graph.sh
@@ -2,6 +2,7 @@
 
 test_description='test for no lazy fetch with the commit-graph'
 
+TEST_PASSES_SANITIZE_LEAK=true
 . ./test-lib.sh
 
 test_expect_success 'setup: prepare a repository with a commit' '
diff --git a/t/t5403-post-checkout-hook.sh b/t/t5403-post-checkout-hook.sh
index 978f240cdac..cfaae547398 100755
--- a/t/t5403-post-checkout-hook.sh
+++ b/t/t5403-post-checkout-hook.sh
@@ -7,6 +7,7 @@ test_description='Test the post-checkout hook.'
 GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
 export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
 
+TEST_PASSES_SANITIZE_LEAK=true
 . ./test-lib.sh
 
 test_expect_success setup '
diff --git a/t/t5502-quickfetch.sh b/t/t5502-quickfetch.sh
index b160f8b7fb7..7b3ff21b984 100755
--- a/t/t5502-quickfetch.sh
+++ b/t/t5502-quickfetch.sh
@@ -5,6 +5,7 @@ test_description='test quickfetch from local'
 GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
 export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
 
+TEST_PASSES_SANITIZE_LEAK=true
 . ./test-lib.sh
 
 test_expect_success setup '
diff --git a/t/t5604-clone-reference.sh b/t/t5604-clone-reference.sh
index 2734e37e880..dc86dea1333 100755
--- a/t/t5604-clone-reference.sh
+++ b/t/t5604-clone-reference.sh
@@ -7,6 +7,7 @@ test_description='test clone --reference'
 GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
 export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
 
+TEST_PASSES_SANITIZE_LEAK=true
 . ./test-lib.sh
 
 base_dir=$(pwd)
diff --git a/t/t5613-info-alternate.sh b/t/t5613-info-alternate.sh
index 895f46bb911..7708cbafa98 100755
--- a/t/t5613-info-alternate.sh
+++ b/t/t5613-info-alternate.sh
@@ -4,6 +4,8 @@
 #
 
 test_description='test transitive info/alternate entries'
+
+TEST_PASSES_SANITIZE_LEAK=true
 . ./test-lib.sh
 
 test_expect_success 'preparing first repository' '
diff --git a/t/t6014-rev-list-all.sh b/t/t6014-rev-list-all.sh
index c9bedd29cba..16b8bd1d090 100755
--- a/t/t6014-rev-list-all.sh
+++ b/t/t6014-rev-list-all.sh
@@ -2,6 +2,7 @@
 
 test_description='--all includes detached HEADs'
 
+TEST_PASSES_SANITIZE_LEAK=true
 . ./test-lib.sh
 
 
diff --git a/t/t6021-rev-list-exclude-hidden.sh b/t/t6021-rev-list-exclude-hidden.sh
index 32b2b094138..11c50b7c0dd 100755
--- a/t/t6021-rev-list-exclude-hidden.sh
+++ b/t/t6021-rev-list-exclude-hidden.sh
@@ -2,6 +2,7 @@
 
 test_description='git rev-list --exclude-hidden test'
 
+TEST_PASSES_SANITIZE_LEAK=true
 . ./test-lib.sh
 
 test_expect_success 'setup' '
diff --git a/t/t7403-submodule-sync.sh b/t/t7403-submodule-sync.sh
index ea92ef52a5e..ff09443a0a4 100755
--- a/t/t7403-submodule-sync.sh
+++ b/t/t7403-submodule-sync.sh
@@ -11,6 +11,7 @@ These tests exercise the "git submodule sync" subcommand.
 GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
 export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
 
+TEST_PASSES_SANITIZE_LEAK=true
 . ./test-lib.sh
 
 test_expect_success setup '
diff --git a/t/t7701-repack-unpack-unreachable.sh b/t/t7701-repack-unpack-unreachable.sh
index b7ac4f598a8..ebb267855fe 100755
--- a/t/t7701-repack-unpack-unreachable.sh
+++ b/t/t7701-repack-unpack-unreachable.sh
@@ -5,6 +5,7 @@ test_description='git repack works correctly'
 GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
 export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
 
+TEST_PASSES_SANITIZE_LEAK=true
 . ./test-lib.sh
 
 fsha1=
-- 
2.39.0.1153.g589e4efe9dc


^ permalink raw reply related	[flat|nested] 193+ messages in thread

* [PATCH v2 02/20] bundle.c: don't leak the "args" in the "struct child_process"
  2022-12-30  2:18 ` [PATCH v2 00/20] leak fixes: various simple leak fixes Ævar Arnfjörð Bjarmason
  2022-12-30  2:18   ` [PATCH v2 01/20] tests: mark tests as passing with SANITIZE=leak Ævar Arnfjörð Bjarmason
@ 2022-12-30  2:18   ` Ævar Arnfjörð Bjarmason
  2022-12-30  2:18   ` [PATCH v2 03/20] commit-graph: use free() instead of UNLEAK() Ævar Arnfjörð Bjarmason
                     ` (18 subsequent siblings)
  20 siblings, 0 replies; 193+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2022-12-30  2:18 UTC (permalink / raw)
  To: git
  Cc: René Scharfe, Junio C Hamano, Eric Sunshine,
	Ævar Arnfjörð Bjarmason

Fix a leak that's been here since 7366096de9d (bundle API: change
"flags" to be "extra_index_pack_args", 2021-09-05), if can't verify
the bundle we didn't call child_process_clear() to clear the "args".

But rather than doing that let's verify the bundle before we start
preparing the process we're going to spawn, if we get an error we
don't need to push anything to the "args".

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 bundle.c | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/bundle.c b/bundle.c
index 4ef7256aa11..9ebb10a8f72 100644
--- a/bundle.c
+++ b/bundle.c
@@ -627,6 +627,10 @@ int unbundle(struct repository *r, struct bundle_header *header,
 	     enum verify_bundle_flags flags)
 {
 	struct child_process ip = CHILD_PROCESS_INIT;
+
+	if (verify_bundle(r, header, flags))
+		return -1;
+
 	strvec_pushl(&ip.args, "index-pack", "--fix-thin", "--stdin", NULL);
 
 	/* If there is a filter, then we need to create the promisor pack. */
@@ -638,8 +642,6 @@ int unbundle(struct repository *r, struct bundle_header *header,
 		strvec_clear(extra_index_pack_args);
 	}
 
-	if (verify_bundle(r, header, flags))
-		return -1;
 	ip.in = bundle_fd;
 	ip.no_stdout = 1;
 	ip.git_cmd = 1;
-- 
2.39.0.1153.g589e4efe9dc


^ permalink raw reply related	[flat|nested] 193+ messages in thread

* [PATCH v2 03/20] commit-graph: use free() instead of UNLEAK()
  2022-12-30  2:18 ` [PATCH v2 00/20] leak fixes: various simple leak fixes Ævar Arnfjörð Bjarmason
  2022-12-30  2:18   ` [PATCH v2 01/20] tests: mark tests as passing with SANITIZE=leak Ævar Arnfjörð Bjarmason
  2022-12-30  2:18   ` [PATCH v2 02/20] bundle.c: don't leak the "args" in the "struct child_process" Ævar Arnfjörð Bjarmason
@ 2022-12-30  2:18   ` Ævar Arnfjörð Bjarmason
  2022-12-30 16:26     ` René Scharfe
  2022-12-30  2:18   ` [PATCH v2 04/20] clone: " Ævar Arnfjörð Bjarmason
                     ` (17 subsequent siblings)
  20 siblings, 1 reply; 193+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2022-12-30  2:18 UTC (permalink / raw)
  To: git
  Cc: René Scharfe, Junio C Hamano, Eric Sunshine,
	Ævar Arnfjörð Bjarmason

In 0bfb48e6723 (builtin/commit-graph.c: UNLEAK variables, 2018-10-03)
this was made to UNLEAK(), but we can just as easily invoke the
free_commit_graph() function added in c3756d5b7fc (commit-graph: add
free_commit_graph, 2018-07-11) instead.

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 builtin/commit-graph.c | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/builtin/commit-graph.c b/builtin/commit-graph.c
index e8f77f535f3..0102ac8540e 100644
--- a/builtin/commit-graph.c
+++ b/builtin/commit-graph.c
@@ -67,6 +67,7 @@ static int graph_verify(int argc, const char **argv, const char *prefix)
 	int fd;
 	struct stat st;
 	int flags = 0;
+	int ret;
 
 	static struct option builtin_commit_graph_verify_options[] = {
 		OPT_BOOL(0, "shallow", &opts.shallow,
@@ -111,8 +112,9 @@ static int graph_verify(int argc, const char **argv, const char *prefix)
 	if (!graph)
 		return !!open_ok;
 
-	UNLEAK(graph);
-	return verify_commit_graph(the_repository, graph, flags);
+	ret = verify_commit_graph(the_repository, graph, flags);
+	free_commit_graph(graph);
+	return ret;
 }
 
 extern int read_replace_refs;
-- 
2.39.0.1153.g589e4efe9dc


^ permalink raw reply related	[flat|nested] 193+ messages in thread

* [PATCH v2 04/20] clone: use free() instead of UNLEAK()
  2022-12-30  2:18 ` [PATCH v2 00/20] leak fixes: various simple leak fixes Ævar Arnfjörð Bjarmason
                     ` (2 preceding siblings ...)
  2022-12-30  2:18   ` [PATCH v2 03/20] commit-graph: use free() instead of UNLEAK() Ævar Arnfjörð Bjarmason
@ 2022-12-30  2:18   ` Ævar Arnfjörð Bjarmason
  2022-12-30  2:18   ` [PATCH v2 05/20] various: add missing clear_pathspec(), fix leaks Ævar Arnfjörð Bjarmason
                     ` (16 subsequent siblings)
  20 siblings, 0 replies; 193+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2022-12-30  2:18 UTC (permalink / raw)
  To: git
  Cc: René Scharfe, Junio C Hamano, Eric Sunshine,
	Ævar Arnfjörð Bjarmason

Change an UNLEAK() added in 0c4542738e6 (clone: free or UNLEAK further
pointers when finished, 2021-03-14) to use a "to_free" pattern
instead. In this case the "repo" can be either this absolute_pathdup()
value, or in the "else if" branch seen in the context the the
"argv[0]" argument to "main()".

We can only free() the value in the former case, hence the "to_free"
pattern.

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 builtin/clone.c | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/builtin/clone.c b/builtin/clone.c
index f518bb2dc1f..48156a4f2c2 100644
--- a/builtin/clone.c
+++ b/builtin/clone.c
@@ -892,6 +892,7 @@ int cmd_clone(int argc, const char **argv, const char *prefix)
 	int is_bundle = 0, is_local;
 	int reject_shallow = 0;
 	const char *repo_name, *repo, *work_tree, *git_dir;
+	char *repo_to_free = NULL;
 	char *path = NULL, *dir, *display_repo = NULL;
 	int dest_exists, real_dest_exists = 0;
 	const struct ref *refs, *remote_head;
@@ -949,7 +950,7 @@ int cmd_clone(int argc, const char **argv, const char *prefix)
 	path = get_repo_path(repo_name, &is_bundle);
 	if (path) {
 		FREE_AND_NULL(path);
-		repo = absolute_pathdup(repo_name);
+		repo = repo_to_free = absolute_pathdup(repo_name);
 	} else if (strchr(repo_name, ':')) {
 		repo = repo_name;
 		display_repo = transport_anonymize_url(repo);
@@ -1392,7 +1393,7 @@ int cmd_clone(int argc, const char **argv, const char *prefix)
 	free(unborn_head);
 	free(dir);
 	free(path);
-	UNLEAK(repo);
+	free(repo_to_free);
 	junk_mode = JUNK_LEAVE_ALL;
 
 	transport_ls_refs_options_release(&transport_ls_refs_options);
-- 
2.39.0.1153.g589e4efe9dc


^ permalink raw reply related	[flat|nested] 193+ messages in thread

* [PATCH v2 05/20] various: add missing clear_pathspec(), fix leaks
  2022-12-30  2:18 ` [PATCH v2 00/20] leak fixes: various simple leak fixes Ævar Arnfjörð Bjarmason
                     ` (3 preceding siblings ...)
  2022-12-30  2:18   ` [PATCH v2 04/20] clone: " Ævar Arnfjörð Bjarmason
@ 2022-12-30  2:18   ` Ævar Arnfjörð Bjarmason
  2022-12-30  2:18   ` [PATCH v2 06/20] name-rev: don't xstrdup() an already dup'd string Ævar Arnfjörð Bjarmason
                     ` (15 subsequent siblings)
  20 siblings, 0 replies; 193+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2022-12-30  2:18 UTC (permalink / raw)
  To: git
  Cc: René Scharfe, Junio C Hamano, Eric Sunshine,
	Ævar Arnfjörð Bjarmason

Fix memory leaks resulting from a missing clear_pathspec().

- archive.c: Plug a leak in the "struct archiver_args", and
  clear_pathspec() the "pathspec" member that the "parse_pathspec_arg()"
  call in this function populates.

- builtin/clean.c: Fix a memory leak that's been with us since
  893d839970c (clean: convert to use parse_pathspec, 2013-07-14).

- builtin/reset.c: Add clear_pathspec() calls to cmd_reset(),
  including to the codepaths where we'd return early.

- builtin/stash.c: Call clear_pathspec() on the pathspec initialized
  in push_stash().

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 archive.c                       |  1 +
 builtin/clean.c                 |  1 +
 builtin/reset.c                 | 11 ++++++++---
 builtin/stash.c                 |  7 +++++--
 t/t5001-archive-attr.sh         |  1 +
 t/t5004-archive-corner-cases.sh |  2 ++
 t/t7105-reset-patch.sh          |  2 ++
 t/t7106-reset-unborn-branch.sh  |  2 ++
 t/t7107-reset-pathspec-file.sh  |  1 +
 t/t7301-clean-interactive.sh    |  1 +
 10 files changed, 24 insertions(+), 5 deletions(-)

diff --git a/archive.c b/archive.c
index 941495f5d78..a2d813e50db 100644
--- a/archive.c
+++ b/archive.c
@@ -710,6 +710,7 @@ int write_archive(int argc, const char **argv, const char *prefix,
 
 	string_list_clear_func(&args.extra_files, extra_file_info_clear);
 	free(args.refname);
+	clear_pathspec(&args.pathspec);
 
 	return rc;
 }
diff --git a/builtin/clean.c b/builtin/clean.c
index b2701a28158..b15eab328b7 100644
--- a/builtin/clean.c
+++ b/builtin/clean.c
@@ -1092,5 +1092,6 @@ int cmd_clean(int argc, const char **argv, const char *prefix)
 	strbuf_release(&buf);
 	string_list_clear(&del_list, 0);
 	string_list_clear(&exclude_list, 0);
+	clear_pathspec(&pathspec);
 	return (errors != 0);
 }
diff --git a/builtin/reset.c b/builtin/reset.c
index fea20a9ba0b..e9c10618cd3 100644
--- a/builtin/reset.c
+++ b/builtin/reset.c
@@ -390,7 +390,8 @@ int cmd_reset(int argc, const char **argv, const char *prefix)
 		if (reset_type != NONE)
 			die(_("options '%s' and '%s' cannot be used together"), "--patch", "--{hard,mixed,soft}");
 		trace2_cmd_mode("patch-interactive");
-		return run_add_interactive(rev, "--patch=reset", &pathspec);
+		update_ref_status = run_add_interactive(rev, "--patch=reset", &pathspec);
+		goto cleanup;
 	}
 
 	/* git reset tree [--] paths... can be used to
@@ -439,8 +440,10 @@ int cmd_reset(int argc, const char **argv, const char *prefix)
 				       LOCK_DIE_ON_ERROR);
 		if (reset_type == MIXED) {
 			int flags = quiet ? REFRESH_QUIET : REFRESH_IN_PORCELAIN;
-			if (read_from_tree(&pathspec, &oid, intent_to_add))
-				return 1;
+			if (read_from_tree(&pathspec, &oid, intent_to_add)) {
+				update_ref_status = 1;
+				goto cleanup;
+			}
 			the_index.updated_skipworktree = 1;
 			if (!no_refresh && get_git_work_tree()) {
 				uint64_t t_begin, t_delta_in_ms;
@@ -488,5 +491,7 @@ int cmd_reset(int argc, const char **argv, const char *prefix)
 
 	discard_index(&the_index);
 
+cleanup:
+	clear_pathspec(&pathspec);
 	return update_ref_status;
 }
diff --git a/builtin/stash.c b/builtin/stash.c
index bb0fd861434..45bffdf54bb 100644
--- a/builtin/stash.c
+++ b/builtin/stash.c
@@ -1727,6 +1727,7 @@ static int push_stash(int argc, const char **argv, const char *prefix,
 		OPT_PATHSPEC_FILE_NUL(&pathspec_file_nul),
 		OPT_END()
 	};
+	int ret;
 
 	if (argc) {
 		force_assume = !strcmp(argv[0], "-p");
@@ -1766,8 +1767,10 @@ static int push_stash(int argc, const char **argv, const char *prefix,
 		die(_("the option '%s' requires '%s'"), "--pathspec-file-nul", "--pathspec-from-file");
 	}
 
-	return do_push_stash(&ps, stash_msg, quiet, keep_index, patch_mode,
-			     include_untracked, only_staged);
+	ret = do_push_stash(&ps, stash_msg, quiet, keep_index, patch_mode,
+			    include_untracked, only_staged);
+	clear_pathspec(&ps);
+	return ret;
 }
 
 static int push_stash_unassumed(int argc, const char **argv, const char *prefix)
diff --git a/t/t5001-archive-attr.sh b/t/t5001-archive-attr.sh
index 2f6eef5e372..04d300eeda7 100755
--- a/t/t5001-archive-attr.sh
+++ b/t/t5001-archive-attr.sh
@@ -3,6 +3,7 @@
 test_description='git archive attribute tests'
 
 TEST_CREATE_REPO_NO_TEMPLATE=1
+TEST_PASSES_SANITIZE_LEAK=true
 . ./test-lib.sh
 
 SUBSTFORMAT='%H (%h)%n'
diff --git a/t/t5004-archive-corner-cases.sh b/t/t5004-archive-corner-cases.sh
index ae508e21623..9f2c6da80e8 100755
--- a/t/t5004-archive-corner-cases.sh
+++ b/t/t5004-archive-corner-cases.sh
@@ -1,6 +1,8 @@
 #!/bin/sh
 
 test_description='test corner cases of git-archive'
+
+TEST_PASSES_SANITIZE_LEAK=true
 . ./test-lib.sh
 
 # the 10knuls.tar file is used to test for an empty git generated tar
diff --git a/t/t7105-reset-patch.sh b/t/t7105-reset-patch.sh
index fc2a6cf5c7a..9b46da7aaa7 100755
--- a/t/t7105-reset-patch.sh
+++ b/t/t7105-reset-patch.sh
@@ -1,6 +1,8 @@
 #!/bin/sh
 
 test_description='git reset --patch'
+
+TEST_PASSES_SANITIZE_LEAK=true
 . ./lib-patch-mode.sh
 
 test_expect_success PERL 'setup' '
diff --git a/t/t7106-reset-unborn-branch.sh b/t/t7106-reset-unborn-branch.sh
index ecb85c3b823..a0b67a0b843 100755
--- a/t/t7106-reset-unborn-branch.sh
+++ b/t/t7106-reset-unborn-branch.sh
@@ -1,6 +1,8 @@
 #!/bin/sh
 
 test_description='git reset should work on unborn branch'
+
+TEST_PASSES_SANITIZE_LEAK=true
 . ./test-lib.sh
 
 test_expect_success 'setup' '
diff --git a/t/t7107-reset-pathspec-file.sh b/t/t7107-reset-pathspec-file.sh
index 523efbecde1..af5ea406db3 100755
--- a/t/t7107-reset-pathspec-file.sh
+++ b/t/t7107-reset-pathspec-file.sh
@@ -2,6 +2,7 @@
 
 test_description='reset --pathspec-from-file'
 
+TEST_PASSES_SANITIZE_LEAK=true
 . ./test-lib.sh
 
 test_tick
diff --git a/t/t7301-clean-interactive.sh b/t/t7301-clean-interactive.sh
index a07e8b86de2..d82a3210a1d 100755
--- a/t/t7301-clean-interactive.sh
+++ b/t/t7301-clean-interactive.sh
@@ -2,6 +2,7 @@
 
 test_description='git clean -i basic tests'
 
+TEST_PASSES_SANITIZE_LEAK=true
 . ./test-lib.sh
 . "$TEST_DIRECTORY"/lib-terminal.sh
 
-- 
2.39.0.1153.g589e4efe9dc


^ permalink raw reply related	[flat|nested] 193+ messages in thread

* [PATCH v2 06/20] name-rev: don't xstrdup() an already dup'd string
  2022-12-30  2:18 ` [PATCH v2 00/20] leak fixes: various simple leak fixes Ævar Arnfjörð Bjarmason
                     ` (4 preceding siblings ...)
  2022-12-30  2:18   ` [PATCH v2 05/20] various: add missing clear_pathspec(), fix leaks Ævar Arnfjörð Bjarmason
@ 2022-12-30  2:18   ` Ævar Arnfjörð Bjarmason
  2022-12-30  2:18   ` [PATCH v2 07/20] repack: fix leaks on error with "goto cleanup" Ævar Arnfjörð Bjarmason
                     ` (14 subsequent siblings)
  20 siblings, 0 replies; 193+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2022-12-30  2:18 UTC (permalink / raw)
  To: git
  Cc: René Scharfe, Junio C Hamano, Eric Sunshine,
	Ævar Arnfjörð Bjarmason

When "add_to_tip_table()" is called with a non-zero
"shorten_unambiguous" we always return an xstrdup()'d string, which
we'd then xstrdup() again, leaking memory. See [1] and [2] for how
this leak came about.

We could xstrdup() only if "shorten_unambiguous" wasn't true, but
let's instead inline this code, so that information on whether we need
to xstrdup() is contained within add_to_tip_table().

1. 98c5c4ad015 (name-rev: allow to specify a subpath for --refs
   option, 2013-06-18)
2. b23e0b9353e (name-rev: allow converting the exact object name at
   the tip of a ref, 2013-07-07)

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 builtin/name-rev.c | 23 ++++++++++-------------
 1 file changed, 10 insertions(+), 13 deletions(-)

diff --git a/builtin/name-rev.c b/builtin/name-rev.c
index 15535e914a6..49fae523694 100644
--- a/builtin/name-rev.c
+++ b/builtin/name-rev.c
@@ -273,17 +273,6 @@ static int subpath_matches(const char *path, const char *filter)
 	return -1;
 }
 
-static const char *name_ref_abbrev(const char *refname, int shorten_unambiguous)
-{
-	if (shorten_unambiguous)
-		refname = shorten_unambiguous_ref(refname, 0);
-	else if (skip_prefix(refname, "refs/heads/", &refname))
-		; /* refname already advanced */
-	else
-		skip_prefix(refname, "refs/", &refname);
-	return refname;
-}
-
 struct name_ref_data {
 	int tags_only;
 	int name_only;
@@ -309,11 +298,19 @@ static void add_to_tip_table(const struct object_id *oid, const char *refname,
 			     int shorten_unambiguous, struct commit *commit,
 			     timestamp_t taggerdate, int from_tag, int deref)
 {
-	refname = name_ref_abbrev(refname, shorten_unambiguous);
+	char *short_refname = NULL;
+
+	if (shorten_unambiguous)
+		short_refname = shorten_unambiguous_ref(refname, 0);
+	else if (skip_prefix(refname, "refs/heads/", &refname))
+		; /* refname already advanced */
+	else
+		skip_prefix(refname, "refs/", &refname);
 
 	ALLOC_GROW(tip_table.table, tip_table.nr + 1, tip_table.alloc);
 	oidcpy(&tip_table.table[tip_table.nr].oid, oid);
-	tip_table.table[tip_table.nr].refname = xstrdup(refname);
+	tip_table.table[tip_table.nr].refname = short_refname ?
+		short_refname : xstrdup(refname);
 	tip_table.table[tip_table.nr].commit = commit;
 	tip_table.table[tip_table.nr].taggerdate = taggerdate;
 	tip_table.table[tip_table.nr].from_tag = from_tag;
-- 
2.39.0.1153.g589e4efe9dc


^ permalink raw reply related	[flat|nested] 193+ messages in thread

* [PATCH v2 07/20] repack: fix leaks on error with "goto cleanup"
  2022-12-30  2:18 ` [PATCH v2 00/20] leak fixes: various simple leak fixes Ævar Arnfjörð Bjarmason
                     ` (5 preceding siblings ...)
  2022-12-30  2:18   ` [PATCH v2 06/20] name-rev: don't xstrdup() an already dup'd string Ævar Arnfjörð Bjarmason
@ 2022-12-30  2:18   ` Ævar Arnfjörð Bjarmason
  2022-12-30  2:18   ` [PATCH v2 08/20] worktree: fix a trivial leak in prune_worktrees() Ævar Arnfjörð Bjarmason
                     ` (13 subsequent siblings)
  20 siblings, 0 replies; 193+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2022-12-30  2:18 UTC (permalink / raw)
  To: git
  Cc: René Scharfe, Junio C Hamano, Eric Sunshine,
	Ævar Arnfjörð Bjarmason

Change cmd_repack() to "goto cleanup" rather than "return ret" on
error, when we returned we'd potentially skip cleaning up the
string_lists and other data we'd allocated in this function.

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 builtin/repack.c                    | 13 +++++++------
 t/t6011-rev-list-with-bad-commit.sh |  1 +
 2 files changed, 8 insertions(+), 6 deletions(-)

diff --git a/builtin/repack.c b/builtin/repack.c
index c1402ad038f..f6493795318 100644
--- a/builtin/repack.c
+++ b/builtin/repack.c
@@ -948,7 +948,7 @@ int cmd_repack(int argc, const char **argv, const char *prefix)
 
 	ret = start_command(&cmd);
 	if (ret)
-		return ret;
+		goto cleanup;
 
 	if (geometry) {
 		FILE *in = xfdopen(cmd.in, "w");
@@ -977,7 +977,7 @@ int cmd_repack(int argc, const char **argv, const char *prefix)
 	fclose(out);
 	ret = finish_command(&cmd);
 	if (ret)
-		return ret;
+		goto cleanup;
 
 	if (!names.nr && !po_args.quiet)
 		printf_ln(_("Nothing new to pack."));
@@ -1007,7 +1007,7 @@ int cmd_repack(int argc, const char **argv, const char *prefix)
 				       &existing_nonkept_packs,
 				       &existing_kept_packs);
 		if (ret)
-			return ret;
+			goto cleanup;
 
 		if (delete_redundant && expire_to) {
 			/*
@@ -1039,7 +1039,7 @@ int cmd_repack(int argc, const char **argv, const char *prefix)
 					       &existing_nonkept_packs,
 					       &existing_kept_packs);
 			if (ret)
-				return ret;
+				goto cleanup;
 		}
 	}
 
@@ -1115,7 +1115,7 @@ int cmd_repack(int argc, const char **argv, const char *prefix)
 		string_list_clear(&include, 0);
 
 		if (ret)
-			return ret;
+			goto cleanup;
 	}
 
 	reprepare_packed_git(the_repository);
@@ -1172,10 +1172,11 @@ int cmd_repack(int argc, const char **argv, const char *prefix)
 		write_midx_file(get_object_directory(), NULL, NULL, flags);
 	}
 
+cleanup:
 	string_list_clear(&names, 1);
 	string_list_clear(&existing_nonkept_packs, 0);
 	string_list_clear(&existing_kept_packs, 0);
 	clear_pack_geometry(geometry);
 
-	return 0;
+	return ret;
 }
diff --git a/t/t6011-rev-list-with-bad-commit.sh b/t/t6011-rev-list-with-bad-commit.sh
index bad02cf5b83..b2e422cf0f7 100755
--- a/t/t6011-rev-list-with-bad-commit.sh
+++ b/t/t6011-rev-list-with-bad-commit.sh
@@ -2,6 +2,7 @@
 
 test_description='git rev-list should notice bad commits'
 
+TEST_PASSES_SANITIZE_LEAK=true
 . ./test-lib.sh
 
 # Note:
-- 
2.39.0.1153.g589e4efe9dc


^ permalink raw reply related	[flat|nested] 193+ messages in thread

* [PATCH v2 08/20] worktree: fix a trivial leak in prune_worktrees()
  2022-12-30  2:18 ` [PATCH v2 00/20] leak fixes: various simple leak fixes Ævar Arnfjörð Bjarmason
                     ` (6 preceding siblings ...)
  2022-12-30  2:18   ` [PATCH v2 07/20] repack: fix leaks on error with "goto cleanup" Ævar Arnfjörð Bjarmason
@ 2022-12-30  2:18   ` Ævar Arnfjörð Bjarmason
  2022-12-30  2:18   ` [PATCH v2 09/20] http-backend.c: fix "dir" and "cmd_arg" leaks in cmd_main() Ævar Arnfjörð Bjarmason
                     ` (12 subsequent siblings)
  20 siblings, 0 replies; 193+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2022-12-30  2:18 UTC (permalink / raw)
  To: git
  Cc: René Scharfe, Junio C Hamano, Eric Sunshine,
	Ævar Arnfjörð Bjarmason

We were leaking both the "struct strbuf" in prune_worktrees(), as well
as the "path" we got from should_prune_worktree(). Since these were
the only two uses of the "struct string_list" let's change it to a
"DUP" and push these to it with "string_list_append_nodup()".

For the string_list_append_nodup() we could also string_list_append()
the main_path.buf, and then strbuf_release(&main_path) right away. But
doing it this way avoids an allocation, as we already have the "struct
strbuf" prepared for appending to "kept".

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 builtin/worktree.c         | 6 +++---
 t/t2401-worktree-prune.sh  | 1 +
 t/t2406-worktree-repair.sh | 1 +
 3 files changed, 5 insertions(+), 3 deletions(-)

diff --git a/builtin/worktree.c b/builtin/worktree.c
index 591d659faea..865ce9be22b 100644
--- a/builtin/worktree.c
+++ b/builtin/worktree.c
@@ -173,7 +173,7 @@ static void prune_worktrees(void)
 {
 	struct strbuf reason = STRBUF_INIT;
 	struct strbuf main_path = STRBUF_INIT;
-	struct string_list kept = STRING_LIST_INIT_NODUP;
+	struct string_list kept = STRING_LIST_INIT_DUP;
 	DIR *dir = opendir(git_path("worktrees"));
 	struct dirent *d;
 	if (!dir)
@@ -184,14 +184,14 @@ static void prune_worktrees(void)
 		if (should_prune_worktree(d->d_name, &reason, &path, expire))
 			prune_worktree(d->d_name, reason.buf);
 		else if (path)
-			string_list_append(&kept, path)->util = xstrdup(d->d_name);
+			string_list_append_nodup(&kept, path)->util = xstrdup(d->d_name);
 	}
 	closedir(dir);
 
 	strbuf_add_absolute_path(&main_path, get_git_common_dir());
 	/* massage main worktree absolute path to match 'gitdir' content */
 	strbuf_strip_suffix(&main_path, "/.");
-	string_list_append(&kept, strbuf_detach(&main_path, NULL));
+	string_list_append_nodup(&kept, strbuf_detach(&main_path, NULL));
 	prune_dups(&kept);
 	string_list_clear(&kept, 1);
 
diff --git a/t/t2401-worktree-prune.sh b/t/t2401-worktree-prune.sh
index 3d28c7f06b2..568a47ec426 100755
--- a/t/t2401-worktree-prune.sh
+++ b/t/t2401-worktree-prune.sh
@@ -5,6 +5,7 @@ test_description='prune $GIT_DIR/worktrees'
 GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
 export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
 
+TEST_PASSES_SANITIZE_LEAK=true
 . ./test-lib.sh
 
 test_expect_success initialize '
diff --git a/t/t2406-worktree-repair.sh b/t/t2406-worktree-repair.sh
index 5c44453e1c1..8970780efcc 100755
--- a/t/t2406-worktree-repair.sh
+++ b/t/t2406-worktree-repair.sh
@@ -2,6 +2,7 @@
 
 test_description='test git worktree repair'
 
+TEST_PASSES_SANITIZE_LEAK=true
 . ./test-lib.sh
 
 test_expect_success setup '
-- 
2.39.0.1153.g589e4efe9dc


^ permalink raw reply related	[flat|nested] 193+ messages in thread

* [PATCH v2 09/20] http-backend.c: fix "dir" and "cmd_arg" leaks in cmd_main()
  2022-12-30  2:18 ` [PATCH v2 00/20] leak fixes: various simple leak fixes Ævar Arnfjörð Bjarmason
                     ` (7 preceding siblings ...)
  2022-12-30  2:18   ` [PATCH v2 08/20] worktree: fix a trivial leak in prune_worktrees() Ævar Arnfjörð Bjarmason
@ 2022-12-30  2:18   ` Ævar Arnfjörð Bjarmason
  2022-12-30  2:18   ` [PATCH v2 10/20] http-backend.c: fix cmd_main() memory leak, refactor reg{exec,free}() Ævar Arnfjörð Bjarmason
                     ` (11 subsequent siblings)
  20 siblings, 0 replies; 193+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2022-12-30  2:18 UTC (permalink / raw)
  To: git
  Cc: René Scharfe, Junio C Hamano, Eric Sunshine,
	Ævar Arnfjörð Bjarmason

Free the "dir" variable after we're done with it. Before
917adc03608 (http-backend: add GIT_PROJECT_ROOT environment var,
2009-10-30) there was no leak here, as we'd get it via getenv(), but
since 917adc03608 we've xstrdup()'d it (or the equivalent), so we need
to free() it.

We also need to free the "cmd_arg" variable, which has been leaked
ever since it was added in 2f4038ab337 (Git-aware CGI to provide dumb
HTTP transport, 2009-10-30).

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 http-backend.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/http-backend.c b/http-backend.c
index 6eb3b2fe51c..67819d931ce 100644
--- a/http-backend.c
+++ b/http-backend.c
@@ -786,6 +786,7 @@ int cmd_main(int argc, const char **argv)
 	if (!getenv("GIT_HTTP_EXPORT_ALL") &&
 	    access("git-daemon-export-ok", F_OK) )
 		not_found(&hdr, "Repository not exported: '%s'", dir);
+	free(dir);
 
 	http_config();
 	max_request_buffer = git_env_ulong("GIT_HTTP_MAX_REQUEST_BUFFER",
@@ -795,5 +796,6 @@ int cmd_main(int argc, const char **argv)
 		setenv(GIT_PROTOCOL_ENVIRONMENT, proto_header, 0);
 
 	cmd->imp(&hdr, cmd_arg);
+	free(cmd_arg);
 	return 0;
 }
-- 
2.39.0.1153.g589e4efe9dc


^ permalink raw reply related	[flat|nested] 193+ messages in thread

* [PATCH v2 10/20] http-backend.c: fix cmd_main() memory leak, refactor reg{exec,free}()
  2022-12-30  2:18 ` [PATCH v2 00/20] leak fixes: various simple leak fixes Ævar Arnfjörð Bjarmason
                     ` (8 preceding siblings ...)
  2022-12-30  2:18   ` [PATCH v2 09/20] http-backend.c: fix "dir" and "cmd_arg" leaks in cmd_main() Ævar Arnfjörð Bjarmason
@ 2022-12-30  2:18   ` Ævar Arnfjörð Bjarmason
  2022-12-30  2:18   ` [PATCH v2 11/20] commit-graph: fix a parse_options_concat() leak Ævar Arnfjörð Bjarmason
                     ` (10 subsequent siblings)
  20 siblings, 0 replies; 193+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2022-12-30  2:18 UTC (permalink / raw)
  To: git
  Cc: René Scharfe, Junio C Hamano, Eric Sunshine,
	Ævar Arnfjörð Bjarmason

Fix a memory leak that's been with us ever since
2f4038ab337 (Git-aware CGI to provide dumb HTTP transport,
2009-10-30). In this case we're not calling regerror() after a failed
regexec(), and don't otherwise use "re" afterwards.

We can therefore simplify this code by calling regfree() right after
the regexec(). An alternative fix would be to add a regfree() to both
the "return" and "break" path in this for-loop.

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 http-backend.c | 7 +++++--
 1 file changed, 5 insertions(+), 2 deletions(-)

diff --git a/http-backend.c b/http-backend.c
index 67819d931ce..8ab58e55f85 100644
--- a/http-backend.c
+++ b/http-backend.c
@@ -759,10 +759,14 @@ int cmd_main(int argc, const char **argv)
 		struct service_cmd *c = &services[i];
 		regex_t re;
 		regmatch_t out[1];
+		int ret;
 
 		if (regcomp(&re, c->pattern, REG_EXTENDED))
 			die("Bogus regex in service table: %s", c->pattern);
-		if (!regexec(&re, dir, 1, out, 0)) {
+		ret = regexec(&re, dir, 1, out, 0);
+		regfree(&re);
+
+		if (!ret) {
 			size_t n;
 
 			if (strcmp(method, c->method))
@@ -774,7 +778,6 @@ int cmd_main(int argc, const char **argv)
 			dir[out[0].rm_so] = 0;
 			break;
 		}
-		regfree(&re);
 	}
 
 	if (!cmd)
-- 
2.39.0.1153.g589e4efe9dc


^ permalink raw reply related	[flat|nested] 193+ messages in thread

* [PATCH v2 11/20] commit-graph: fix a parse_options_concat() leak
  2022-12-30  2:18 ` [PATCH v2 00/20] leak fixes: various simple leak fixes Ævar Arnfjörð Bjarmason
                     ` (9 preceding siblings ...)
  2022-12-30  2:18   ` [PATCH v2 10/20] http-backend.c: fix cmd_main() memory leak, refactor reg{exec,free}() Ævar Arnfjörð Bjarmason
@ 2022-12-30  2:18   ` Ævar Arnfjörð Bjarmason
  2022-12-30  2:18   ` [PATCH v2 12/20] show-branch: free() allocated "head" before return Ævar Arnfjörð Bjarmason
                     ` (9 subsequent siblings)
  20 siblings, 0 replies; 193+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2022-12-30  2:18 UTC (permalink / raw)
  To: git
  Cc: René Scharfe, Junio C Hamano, Eric Sunshine,
	Ævar Arnfjörð Bjarmason

When the parse_options_concat() was added to this file in
84e4484f128 (commit-graph: use parse_options_concat(), 2021-08-23) we
wouldn't free() it if we returned early in these cases.

Since "result" is 0 by default we can "goto cleanup" in both cases,
and only need to set "result" if write_commit_graph_reachable() fails.

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 builtin/commit-graph.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/builtin/commit-graph.c b/builtin/commit-graph.c
index 0102ac8540e..93704f95a9d 100644
--- a/builtin/commit-graph.c
+++ b/builtin/commit-graph.c
@@ -269,8 +269,8 @@ static int graph_write(int argc, const char **argv, const char *prefix)
 
 	if (opts.reachable) {
 		if (write_commit_graph_reachable(odb, flags, &write_opts))
-			return 1;
-		return 0;
+			result = 1;
+		goto cleanup;
 	}
 
 	if (opts.stdin_packs) {
-- 
2.39.0.1153.g589e4efe9dc


^ permalink raw reply related	[flat|nested] 193+ messages in thread

* [PATCH v2 12/20] show-branch: free() allocated "head" before return
  2022-12-30  2:18 ` [PATCH v2 00/20] leak fixes: various simple leak fixes Ævar Arnfjörð Bjarmason
                     ` (10 preceding siblings ...)
  2022-12-30  2:18   ` [PATCH v2 11/20] commit-graph: fix a parse_options_concat() leak Ævar Arnfjörð Bjarmason
@ 2022-12-30  2:18   ` Ævar Arnfjörð Bjarmason
  2022-12-30  2:18   ` [PATCH v2 13/20] builtin/merge.c: always free "struct strbuf msg" Ævar Arnfjörð Bjarmason
                     ` (8 subsequent siblings)
  20 siblings, 0 replies; 193+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2022-12-30  2:18 UTC (permalink / raw)
  To: git
  Cc: René Scharfe, Junio C Hamano, Eric Sunshine,
	Ævar Arnfjörð Bjarmason

Stop leaking the "head" variable, which we've been leaking since it
was originally added in [1], and in its current form since [2]

1. ed378ec7e85 (Make ref resolution saner, 2006-09-11)
2. d9e557a320b (show-branch: store resolved head in heap buffer,
   2017-02-14).

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 builtin/show-branch.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/builtin/show-branch.c b/builtin/show-branch.c
index c013abaf942..358ac3e519a 100644
--- a/builtin/show-branch.c
+++ b/builtin/show-branch.c
@@ -956,5 +956,6 @@ int cmd_show_branch(int ac, const char **av, const char *prefix)
 		if (shown_merge_point && --extra < 0)
 			break;
 	}
+	free(head);
 	return 0;
 }
-- 
2.39.0.1153.g589e4efe9dc


^ permalink raw reply related	[flat|nested] 193+ messages in thread

* [PATCH v2 13/20] builtin/merge.c: always free "struct strbuf msg"
  2022-12-30  2:18 ` [PATCH v2 00/20] leak fixes: various simple leak fixes Ævar Arnfjörð Bjarmason
                     ` (11 preceding siblings ...)
  2022-12-30  2:18   ` [PATCH v2 12/20] show-branch: free() allocated "head" before return Ævar Arnfjörð Bjarmason
@ 2022-12-30  2:18   ` Ævar Arnfjörð Bjarmason
  2022-12-30  2:18   ` [PATCH v2 14/20] builtin/merge.c: free "&buf" on "Your local changes..." error Ævar Arnfjörð Bjarmason
                     ` (7 subsequent siblings)
  20 siblings, 0 replies; 193+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2022-12-30  2:18 UTC (permalink / raw)
  To: git
  Cc: René Scharfe, Junio C Hamano, Eric Sunshine,
	Ævar Arnfjörð Bjarmason

Follow-up 465028e0e25 (merge: add missing strbuf_release(),
2021-10-07) and address the "msg" memory leak in this block. We could
free "&msg" before the "goto done" here, but even better is to avoid
allocating it in the first place.

By repeating the "Fast-forward" string here we can avoid using a
"struct strbuf" altogether.

Suggested-by: René Scharfe <l.s.r@web.de>
Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 builtin/merge.c                | 11 ++++-------
 t/t6439-merge-co-error-msgs.sh |  1 +
 2 files changed, 5 insertions(+), 7 deletions(-)

diff --git a/builtin/merge.c b/builtin/merge.c
index 0f093f2a4f2..91dd5435c59 100644
--- a/builtin/merge.c
+++ b/builtin/merge.c
@@ -1560,7 +1560,9 @@ int cmd_merge(int argc, const char **argv, const char *prefix)
 			!common->next &&
 			oideq(&common->item->object.oid, &head_commit->object.oid)) {
 		/* Again the most common case of merging one remote. */
-		struct strbuf msg = STRBUF_INIT;
+		const char *msg = have_message ?
+			"Fast-forward (no commit created; -m option ignored)" :
+			"Fast-forward";
 		struct commit *commit;
 
 		if (verbosity >= 0) {
@@ -1570,10 +1572,6 @@ int cmd_merge(int argc, const char **argv, const char *prefix)
 			       find_unique_abbrev(&remoteheads->item->object.oid,
 						  DEFAULT_ABBREV));
 		}
-		strbuf_addstr(&msg, "Fast-forward");
-		if (have_message)
-			strbuf_addstr(&msg,
-				" (no commit created; -m option ignored)");
 		commit = remoteheads->item;
 		if (!commit) {
 			ret = 1;
@@ -1592,9 +1590,8 @@ int cmd_merge(int argc, const char **argv, const char *prefix)
 			goto done;
 		}
 
-		finish(head_commit, remoteheads, &commit->object.oid, msg.buf);
+		finish(head_commit, remoteheads, &commit->object.oid, msg);
 		remove_merge_branch_state(the_repository);
-		strbuf_release(&msg);
 		goto done;
 	} else if (!remoteheads->next && common->next)
 		;
diff --git a/t/t6439-merge-co-error-msgs.sh b/t/t6439-merge-co-error-msgs.sh
index 52cf0c87690..0cbec57cdab 100755
--- a/t/t6439-merge-co-error-msgs.sh
+++ b/t/t6439-merge-co-error-msgs.sh
@@ -5,6 +5,7 @@ test_description='unpack-trees error messages'
 GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
 export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
 
+TEST_PASSES_SANITIZE_LEAK=true
 . ./test-lib.sh
 
 
-- 
2.39.0.1153.g589e4efe9dc


^ permalink raw reply related	[flat|nested] 193+ messages in thread

* [PATCH v2 14/20] builtin/merge.c: free "&buf" on "Your local changes..." error
  2022-12-30  2:18 ` [PATCH v2 00/20] leak fixes: various simple leak fixes Ævar Arnfjörð Bjarmason
                     ` (12 preceding siblings ...)
  2022-12-30  2:18   ` [PATCH v2 13/20] builtin/merge.c: always free "struct strbuf msg" Ævar Arnfjörð Bjarmason
@ 2022-12-30  2:18   ` Ævar Arnfjörð Bjarmason
  2022-12-30  2:18   ` [PATCH v2 15/20] connected.c: free(new_pack) in check_connected() Ævar Arnfjörð Bjarmason
                     ` (6 subsequent siblings)
  20 siblings, 0 replies; 193+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2022-12-30  2:18 UTC (permalink / raw)
  To: git
  Cc: René Scharfe, Junio C Hamano, Eric Sunshine,
	Ævar Arnfjörð Bjarmason

Plug a memory leak introduced in [1], since that change didn't follow
the "goto done" pattern introduced in [2] we'd leak the "&buf" memory.

1. e4cdfe84a0d (merge: abort if index does not match HEAD for trivial
   merges, 2022-07-23)
2. d5a35c114ab (Copy resolve_ref() return value for longer use,
   2011-11-13)

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 builtin/merge.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/builtin/merge.c b/builtin/merge.c
index 91dd5435c59..2b13124c497 100644
--- a/builtin/merge.c
+++ b/builtin/merge.c
@@ -1618,7 +1618,8 @@ int cmd_merge(int argc, const char **argv, const char *prefix)
 				error(_("Your local changes to the following files would be overwritten by merge:\n  %s"),
 				      sb.buf);
 				strbuf_release(&sb);
-				return 2;
+				ret = 2;
+				goto done;
 			}
 
 			/* See if it is really trivial. */
-- 
2.39.0.1153.g589e4efe9dc


^ permalink raw reply related	[flat|nested] 193+ messages in thread

* [PATCH v2 15/20] connected.c: free(new_pack) in check_connected()
  2022-12-30  2:18 ` [PATCH v2 00/20] leak fixes: various simple leak fixes Ævar Arnfjörð Bjarmason
                     ` (13 preceding siblings ...)
  2022-12-30  2:18   ` [PATCH v2 14/20] builtin/merge.c: free "&buf" on "Your local changes..." error Ævar Arnfjörð Bjarmason
@ 2022-12-30  2:18   ` Ævar Arnfjörð Bjarmason
  2022-12-30 16:17     ` René Scharfe
  2022-12-30  2:18   ` [PATCH v2 16/20] object-file.c: release the "tag" in check_tag() Ævar Arnfjörð Bjarmason
                     ` (5 subsequent siblings)
  20 siblings, 1 reply; 193+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2022-12-30  2:18 UTC (permalink / raw)
  To: git
  Cc: René Scharfe, Junio C Hamano, Eric Sunshine,
	Ævar Arnfjörð Bjarmason

Fix a memory leak that's been with us since this code was introduced
in c6807a40dcd (clone: open a shortcut for connectivity check,
2013-05-26). We'd never free() the "new_pack" that we'd potentially
allocate. Since it's initialized to "NULL" it's safe to call free()
here unconditionally.

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 connected.c | 13 +++++++------
 1 file changed, 7 insertions(+), 6 deletions(-)

diff --git a/connected.c b/connected.c
index b90fd61790c..e4d404e10b2 100644
--- a/connected.c
+++ b/connected.c
@@ -38,7 +38,7 @@ int check_connected(oid_iterate_fn fn, void *cb_data,
 	if (!oid) {
 		if (opt->err_fd)
 			close(opt->err_fd);
-		return err;
+		goto cleanup;
 	}
 
 	if (transport && transport->smart_options &&
@@ -85,8 +85,7 @@ int check_connected(oid_iterate_fn fn, void *cb_data,
 promisor_pack_found:
 			;
 		} while ((oid = fn(cb_data)) != NULL);
-		free(new_pack);
-		return 0;
+		goto cleanup;
 	}
 
 no_promisor_pack_found:
@@ -123,8 +122,8 @@ int check_connected(oid_iterate_fn fn, void *cb_data,
 		rev_list.no_stderr = opt->quiet;
 
 	if (start_command(&rev_list)) {
-		free(new_pack);
-		return error(_("Could not run 'git rev-list'"));
+		err = error(_("Could not run 'git rev-list'"));
+		goto cleanup;
 	}
 
 	sigchain_push(SIGPIPE, SIG_IGN);
@@ -157,6 +156,8 @@ int check_connected(oid_iterate_fn fn, void *cb_data,
 		err = error_errno(_("failed to close rev-list's stdin"));
 
 	sigchain_pop(SIGPIPE);
+	err = finish_command(&rev_list) || err;
+cleanup:
 	free(new_pack);
-	return finish_command(&rev_list) || err;
+	return err;
 }
-- 
2.39.0.1153.g589e4efe9dc


^ permalink raw reply related	[flat|nested] 193+ messages in thread

* [PATCH v2 16/20] object-file.c: release the "tag" in check_tag()
  2022-12-30  2:18 ` [PATCH v2 00/20] leak fixes: various simple leak fixes Ævar Arnfjörð Bjarmason
                     ` (14 preceding siblings ...)
  2022-12-30  2:18   ` [PATCH v2 15/20] connected.c: free(new_pack) in check_connected() Ævar Arnfjörð Bjarmason
@ 2022-12-30  2:18   ` Ævar Arnfjörð Bjarmason
  2022-12-30  2:18   ` [PATCH v2 17/20] grep.c: refactor free_grep_patterns() Ævar Arnfjörð Bjarmason
                     ` (4 subsequent siblings)
  20 siblings, 0 replies; 193+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2022-12-30  2:18 UTC (permalink / raw)
  To: git
  Cc: René Scharfe, Junio C Hamano, Eric Sunshine,
	Ævar Arnfjörð Bjarmason

Fix a memory leak that's been with us ever since c879daa2372 (Make
hash-object more robust against malformed objects, 2011-02-05). With
"HASH_FORMAT_CHECK" (used by "hash-object" and "replace") we'll parse
tags into a throwaway variable on the stack, but weren't freeing the
"item->tag" we might malloc() when doing so.

The clearing that release_tag_memory() does for us is redundant here,
but let's use it as-is anyway. It only has one other existing caller,
which does need the tag to be cleared.

Mark the tests that now pass in their entirety as passing under
"SANITIZE=leak", which means we'll test them as part of the
"linux-leaks" CI job.

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 object-file.c         | 1 +
 t/t3800-mktag.sh      | 1 +
 t/t5302-pack-index.sh | 2 ++
 3 files changed, 4 insertions(+)

diff --git a/object-file.c b/object-file.c
index c1b71c28347..53477a07469 100644
--- a/object-file.c
+++ b/object-file.c
@@ -2331,6 +2331,7 @@ static void check_tag(const void *buf, size_t size)
 	memset(&t, 0, sizeof(t));
 	if (parse_tag_buffer(the_repository, &t, buf, size))
 		die(_("corrupt tag"));
+	release_tag_memory(&t);
 }
 
 static int index_mem(struct index_state *istate,
diff --git a/t/t3800-mktag.sh b/t/t3800-mktag.sh
index e3cf0ffbe59..d3e428ff46e 100755
--- a/t/t3800-mktag.sh
+++ b/t/t3800-mktag.sh
@@ -4,6 +4,7 @@
 
 test_description='git mktag: tag object verify test'
 
+TEST_PASSES_SANITIZE_LEAK=true
 . ./test-lib.sh
 
 ###########################################################
diff --git a/t/t5302-pack-index.sh b/t/t5302-pack-index.sh
index b0095ab41d3..54b11f81c63 100755
--- a/t/t5302-pack-index.sh
+++ b/t/t5302-pack-index.sh
@@ -4,6 +4,8 @@
 #
 
 test_description='pack index with 64-bit offsets and object CRC'
+
+TEST_PASSES_SANITIZE_LEAK=true
 . ./test-lib.sh
 
 test_expect_success 'setup' '
-- 
2.39.0.1153.g589e4efe9dc


^ permalink raw reply related	[flat|nested] 193+ messages in thread

* [PATCH v2 17/20] grep.c: refactor free_grep_patterns()
  2022-12-30  2:18 ` [PATCH v2 00/20] leak fixes: various simple leak fixes Ævar Arnfjörð Bjarmason
                     ` (15 preceding siblings ...)
  2022-12-30  2:18   ` [PATCH v2 16/20] object-file.c: release the "tag" in check_tag() Ævar Arnfjörð Bjarmason
@ 2022-12-30  2:18   ` Ævar Arnfjörð Bjarmason
  2022-12-30  2:18   ` [PATCH v2 18/20] grep API: plug memory leaks by freeing "header_list" Ævar Arnfjörð Bjarmason
                     ` (3 subsequent siblings)
  20 siblings, 0 replies; 193+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2022-12-30  2:18 UTC (permalink / raw)
  To: git
  Cc: René Scharfe, Junio C Hamano, Eric Sunshine,
	Ævar Arnfjörð Bjarmason

Refactor the free_grep_patterns() function to split out the freeing of
the "struct grep_pat" it contains, right now we're only freeing the
"pattern_list", but we should be freeing another member of the same
type, which we'll do in the subsequent commit.

Let's also replace the "return" if we don't have an
"opt->pattern_expression" with a conditional call of
free_pattern_expr().

Before db84376f981 (grep.c: remove "extended" in favor of
"pattern_expression", fix segfault, 2022-10-11) the pattern here was:

	if (!x)
		return;
	free(y);

But after the cleanup in db84376f981 (which was a narrow segfault fix,
and thus avoided refactoring this) we ended up with:

	if (!x)
		return;
	free(x);

Let's instead do:

	if (x)
		free(x);

This doesn't matter for the subsequent change, but as we're
refactoring this function let's make it easier to reason about, and to
extend in the future, i.e. if we start to free free() members that
come after "pattern_expression" in the "struct grep_opt".

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 grep.c | 14 +++++++++-----
 1 file changed, 9 insertions(+), 5 deletions(-)

diff --git a/grep.c b/grep.c
index 06eed694936..a4450df4559 100644
--- a/grep.c
+++ b/grep.c
@@ -769,11 +769,11 @@ static void free_pattern_expr(struct grep_expr *x)
 	free(x);
 }
 
-void free_grep_patterns(struct grep_opt *opt)
+static void free_grep_pat(struct grep_pat *pattern)
 {
 	struct grep_pat *p, *n;
 
-	for (p = opt->pattern_list; p; p = n) {
+	for (p = pattern; p; p = n) {
 		n = p->next;
 		switch (p->token) {
 		case GREP_PATTERN: /* atom */
@@ -790,10 +790,14 @@ void free_grep_patterns(struct grep_opt *opt)
 		}
 		free(p);
 	}
+}
 
-	if (!opt->pattern_expression)
-		return;
-	free_pattern_expr(opt->pattern_expression);
+void free_grep_patterns(struct grep_opt *opt)
+{
+	free_grep_pat(opt->pattern_list);
+
+	if (opt->pattern_expression)
+		free_pattern_expr(opt->pattern_expression);
 }
 
 static const char *end_of_line(const char *cp, unsigned long *left)
-- 
2.39.0.1153.g589e4efe9dc


^ permalink raw reply related	[flat|nested] 193+ messages in thread

* [PATCH v2 18/20] grep API: plug memory leaks by freeing "header_list"
  2022-12-30  2:18 ` [PATCH v2 00/20] leak fixes: various simple leak fixes Ævar Arnfjörð Bjarmason
                     ` (16 preceding siblings ...)
  2022-12-30  2:18   ` [PATCH v2 17/20] grep.c: refactor free_grep_patterns() Ævar Arnfjörð Bjarmason
@ 2022-12-30  2:18   ` Ævar Arnfjörð Bjarmason
  2022-12-30  2:18   ` [PATCH v2 19/20] receive-pack: free() the "ref_name" in "struct command" Ævar Arnfjörð Bjarmason
                     ` (2 subsequent siblings)
  20 siblings, 0 replies; 193+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2022-12-30  2:18 UTC (permalink / raw)
  To: git
  Cc: René Scharfe, Junio C Hamano, Eric Sunshine,
	Ævar Arnfjörð Bjarmason

When the "header_list" struct member was added in [1] it wasn't made
to free the list using loop added for the adjacent "pattern_list"
member, see [2] for when we started freeing it.

This makes e.g. this command leak-free when run on git.git:

	./git -P log -1 --color=always --author=A origin/master

1. 80235ba79ef ("log --author=me --grep=it" should find intersection,
   not union, 2010-01-17)
2. b48fb5b6a95 (grep: free expressions and patterns when done.,
   2006-09-27)

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 grep.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/grep.c b/grep.c
index a4450df4559..c908535e0d8 100644
--- a/grep.c
+++ b/grep.c
@@ -795,6 +795,7 @@ static void free_grep_pat(struct grep_pat *pattern)
 void free_grep_patterns(struct grep_opt *opt)
 {
 	free_grep_pat(opt->pattern_list);
+	free_grep_pat(opt->header_list);
 
 	if (opt->pattern_expression)
 		free_pattern_expr(opt->pattern_expression);
-- 
2.39.0.1153.g589e4efe9dc


^ permalink raw reply related	[flat|nested] 193+ messages in thread

* [PATCH v2 19/20] receive-pack: free() the "ref_name" in "struct command"
  2022-12-30  2:18 ` [PATCH v2 00/20] leak fixes: various simple leak fixes Ævar Arnfjörð Bjarmason
                     ` (17 preceding siblings ...)
  2022-12-30  2:18   ` [PATCH v2 18/20] grep API: plug memory leaks by freeing "header_list" Ævar Arnfjörð Bjarmason
@ 2022-12-30  2:18   ` Ævar Arnfjörð Bjarmason
  2022-12-30  2:18   ` [PATCH v2 20/20] push: free_refs() the "local_refs" in set_refspecs() Ævar Arnfjörð Bjarmason
  2023-01-10  5:43   ` [PATCH v3 00/19] leak fixes: various simple leak fixes Ævar Arnfjörð Bjarmason
  20 siblings, 0 replies; 193+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2022-12-30  2:18 UTC (permalink / raw)
  To: git
  Cc: René Scharfe, Junio C Hamano, Eric Sunshine,
	Ævar Arnfjörð Bjarmason

Fix a memory leak that's been with us since this code was introduced
in 575f497456e (Add first cut at "git-receive-pack", 2005-06-29), see
eb1af2df0b1 (git-receive-pack: start parsing ref update commands,
2005-06-29) for the later change that refactored the code to add the
"ref_name" member.

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 builtin/receive-pack.c                | 10 ++++++++++
 t/t5405-send-pack-rewind.sh           |  1 +
 t/t5406-remote-rejects.sh             |  1 +
 t/t5507-remote-environment.sh         |  2 ++
 t/t5522-pull-symlink.sh               |  1 +
 t/t5527-fetch-odd-refs.sh             |  1 +
 t/t5705-session-id-in-capabilities.sh |  1 +
 7 files changed, 17 insertions(+)

diff --git a/builtin/receive-pack.c b/builtin/receive-pack.c
index a90af303630..451bad776c6 100644
--- a/builtin/receive-pack.c
+++ b/builtin/receive-pack.c
@@ -2032,6 +2032,15 @@ static struct command **queue_command(struct command **tail,
 	return &cmd->next;
 }
 
+static void free_commands(struct command *commands)
+{
+	while (commands) {
+		struct command *next = commands->next;
+		free(commands);
+		commands = next;
+	}
+}
+
 static void queue_commands_from_cert(struct command **tail,
 				     struct strbuf *push_cert)
 {
@@ -2569,6 +2578,7 @@ int cmd_receive_pack(int argc, const char **argv, const char *prefix)
 		run_receive_hook(commands, "post-receive", 1,
 				 &push_options);
 		run_update_post_hook(commands);
+		free_commands(commands);
 		string_list_clear(&push_options, 0);
 		if (auto_gc) {
 			struct child_process proc = CHILD_PROCESS_INIT;
diff --git a/t/t5405-send-pack-rewind.sh b/t/t5405-send-pack-rewind.sh
index 11f03239a06..1686ac13aa6 100755
--- a/t/t5405-send-pack-rewind.sh
+++ b/t/t5405-send-pack-rewind.sh
@@ -5,6 +5,7 @@ test_description='forced push to replace commit we do not have'
 GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
 export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
 
+TEST_PASSES_SANITIZE_LEAK=true
 . ./test-lib.sh
 
 test_expect_success setup '
diff --git a/t/t5406-remote-rejects.sh b/t/t5406-remote-rejects.sh
index dcbeb420827..d6a99466338 100755
--- a/t/t5406-remote-rejects.sh
+++ b/t/t5406-remote-rejects.sh
@@ -2,6 +2,7 @@
 
 test_description='remote push rejects are reported by client'
 
+TEST_PASSES_SANITIZE_LEAK=true
 . ./test-lib.sh
 
 test_expect_success 'setup' '
diff --git a/t/t5507-remote-environment.sh b/t/t5507-remote-environment.sh
index e6149295b18..c6a6957c500 100755
--- a/t/t5507-remote-environment.sh
+++ b/t/t5507-remote-environment.sh
@@ -1,6 +1,8 @@
 #!/bin/sh
 
 test_description='check environment showed to remote side of transports'
+
+TEST_PASSES_SANITIZE_LEAK=true
 . ./test-lib.sh
 
 test_expect_success 'set up "remote" push situation' '
diff --git a/t/t5522-pull-symlink.sh b/t/t5522-pull-symlink.sh
index bcff460d0a2..394bc60cb8e 100755
--- a/t/t5522-pull-symlink.sh
+++ b/t/t5522-pull-symlink.sh
@@ -2,6 +2,7 @@
 
 test_description='pulling from symlinked subdir'
 
+TEST_PASSES_SANITIZE_LEAK=true
 . ./test-lib.sh
 
 # The scenario we are building:
diff --git a/t/t5527-fetch-odd-refs.sh b/t/t5527-fetch-odd-refs.sh
index e2770e4541f..98ece27c6a0 100755
--- a/t/t5527-fetch-odd-refs.sh
+++ b/t/t5527-fetch-odd-refs.sh
@@ -4,6 +4,7 @@ test_description='test fetching of oddly-named refs'
 GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
 export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
 
+TEST_PASSES_SANITIZE_LEAK=true
 . ./test-lib.sh
 
 # afterwards we will have:
diff --git a/t/t5705-session-id-in-capabilities.sh b/t/t5705-session-id-in-capabilities.sh
index ed38c76c290..b8a722ec27e 100755
--- a/t/t5705-session-id-in-capabilities.sh
+++ b/t/t5705-session-id-in-capabilities.sh
@@ -2,6 +2,7 @@
 
 test_description='session ID in capabilities'
 
+TEST_PASSES_SANITIZE_LEAK=true
 . ./test-lib.sh
 
 REPO="$(pwd)/repo"
-- 
2.39.0.1153.g589e4efe9dc


^ permalink raw reply related	[flat|nested] 193+ messages in thread

* [PATCH v2 20/20] push: free_refs() the "local_refs" in set_refspecs()
  2022-12-30  2:18 ` [PATCH v2 00/20] leak fixes: various simple leak fixes Ævar Arnfjörð Bjarmason
                     ` (18 preceding siblings ...)
  2022-12-30  2:18   ` [PATCH v2 19/20] receive-pack: free() the "ref_name" in "struct command" Ævar Arnfjörð Bjarmason
@ 2022-12-30  2:18   ` Ævar Arnfjörð Bjarmason
  2023-01-10  5:43   ` [PATCH v3 00/19] leak fixes: various simple leak fixes Ævar Arnfjörð Bjarmason
  20 siblings, 0 replies; 193+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2022-12-30  2:18 UTC (permalink / raw)
  To: git
  Cc: René Scharfe, Junio C Hamano, Eric Sunshine,
	Ævar Arnfjörð Bjarmason

Fix a memory leak that's been with us since this code was added in
ca02465b413 (push: use remote.$name.push as a refmap, 2013-12-03).

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 builtin/push.c                          | 1 +
 t/t1416-ref-transaction-hooks.sh        | 1 +
 t/t5504-fetch-receive-strict.sh         | 1 +
 t/t5523-push-upstream.sh                | 1 +
 t/t5529-push-errors.sh                  | 2 ++
 t/t5546-receive-limits.sh               | 2 ++
 t/t5547-push-quarantine.sh              | 2 ++
 t/t5606-clone-options.sh                | 1 +
 t/t5810-proto-disable-local.sh          | 2 ++
 t/t5813-proto-disable-ssh.sh            | 2 ++
 t/t7409-submodule-detached-work-tree.sh | 1 +
 t/t7416-submodule-dash-url.sh           | 2 ++
 t/t7450-bad-git-dotfiles.sh             | 2 ++
 13 files changed, 20 insertions(+)

diff --git a/builtin/push.c b/builtin/push.c
index 60ac8017e52..f48e4c6a856 100644
--- a/builtin/push.c
+++ b/builtin/push.c
@@ -129,6 +129,7 @@ static void set_refspecs(const char **refs, int nr, const char *repo)
 		} else
 			refspec_append(&rs, ref);
 	}
+	free_refs(local_refs);
 }
 
 static int push_url_of_remote(struct remote *remote, const char ***url_p)
diff --git a/t/t1416-ref-transaction-hooks.sh b/t/t1416-ref-transaction-hooks.sh
index 27731722a5b..b32ca798f9f 100755
--- a/t/t1416-ref-transaction-hooks.sh
+++ b/t/t1416-ref-transaction-hooks.sh
@@ -5,6 +5,7 @@ test_description='reference transaction hooks'
 GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
 export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
 
+TEST_PASSES_SANITIZE_LEAK=true
 . ./test-lib.sh
 
 test_expect_success setup '
diff --git a/t/t5504-fetch-receive-strict.sh b/t/t5504-fetch-receive-strict.sh
index ac4099ca893..14e8af1f3b7 100755
--- a/t/t5504-fetch-receive-strict.sh
+++ b/t/t5504-fetch-receive-strict.sh
@@ -4,6 +4,7 @@ test_description='fetch/receive strict mode'
 GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
 export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
 
+TEST_PASSES_SANITIZE_LEAK=true
 . ./test-lib.sh
 
 test_expect_success 'setup and inject "corrupt or missing" object' '
diff --git a/t/t5523-push-upstream.sh b/t/t5523-push-upstream.sh
index fdb42920564..c9acc076353 100755
--- a/t/t5523-push-upstream.sh
+++ b/t/t5523-push-upstream.sh
@@ -4,6 +4,7 @@ test_description='push with --set-upstream'
 GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
 export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
 
+TEST_PASSES_SANITIZE_LEAK=true
 . ./test-lib.sh
 . "$TEST_DIRECTORY"/lib-terminal.sh
 
diff --git a/t/t5529-push-errors.sh b/t/t5529-push-errors.sh
index ce85fd30ad1..0247137cb36 100755
--- a/t/t5529-push-errors.sh
+++ b/t/t5529-push-errors.sh
@@ -1,6 +1,8 @@
 #!/bin/sh
 
 test_description='detect some push errors early (before contacting remote)'
+
+TEST_PASSES_SANITIZE_LEAK=true
 . ./test-lib.sh
 
 test_expect_success 'setup commits' '
diff --git a/t/t5546-receive-limits.sh b/t/t5546-receive-limits.sh
index 0b0e987fdb7..eed3c9d81ab 100755
--- a/t/t5546-receive-limits.sh
+++ b/t/t5546-receive-limits.sh
@@ -1,6 +1,8 @@
 #!/bin/sh
 
 test_description='check receive input limits'
+
+TEST_PASSES_SANITIZE_LEAK=true
 . ./test-lib.sh
 
 # Let's run tests with different unpack limits: 1 and 10000
diff --git a/t/t5547-push-quarantine.sh b/t/t5547-push-quarantine.sh
index 1876fb34e51..9f899b8c7d7 100755
--- a/t/t5547-push-quarantine.sh
+++ b/t/t5547-push-quarantine.sh
@@ -1,6 +1,8 @@
 #!/bin/sh
 
 test_description='check quarantine of objects during push'
+
+TEST_PASSES_SANITIZE_LEAK=true
 . ./test-lib.sh
 
 test_expect_success 'create picky dest repo' '
diff --git a/t/t5606-clone-options.sh b/t/t5606-clone-options.sh
index cf221e92c4d..27f9f776389 100755
--- a/t/t5606-clone-options.sh
+++ b/t/t5606-clone-options.sh
@@ -4,6 +4,7 @@ test_description='basic clone options'
 GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
 export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
 
+TEST_PASSES_SANITIZE_LEAK=true
 . ./test-lib.sh
 
 test_expect_success 'setup' '
diff --git a/t/t5810-proto-disable-local.sh b/t/t5810-proto-disable-local.sh
index c1ef99b85c2..862610256fb 100755
--- a/t/t5810-proto-disable-local.sh
+++ b/t/t5810-proto-disable-local.sh
@@ -1,6 +1,8 @@
 #!/bin/sh
 
 test_description='test disabling of local paths in clone/fetch'
+
+TEST_PASSES_SANITIZE_LEAK=true
 . ./test-lib.sh
 . "$TEST_DIRECTORY/lib-proto-disable.sh"
 
diff --git a/t/t5813-proto-disable-ssh.sh b/t/t5813-proto-disable-ssh.sh
index 3f084ee3065..2e975dc70ec 100755
--- a/t/t5813-proto-disable-ssh.sh
+++ b/t/t5813-proto-disable-ssh.sh
@@ -1,6 +1,8 @@
 #!/bin/sh
 
 test_description='test disabling of git-over-ssh in clone/fetch'
+
+TEST_PASSES_SANITIZE_LEAK=true
 . ./test-lib.sh
 . "$TEST_DIRECTORY/lib-proto-disable.sh"
 
diff --git a/t/t7409-submodule-detached-work-tree.sh b/t/t7409-submodule-detached-work-tree.sh
index 374ed481e9c..574a6fc526e 100755
--- a/t/t7409-submodule-detached-work-tree.sh
+++ b/t/t7409-submodule-detached-work-tree.sh
@@ -13,6 +13,7 @@ TEST_NO_CREATE_REPO=1
 GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
 export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
 
+TEST_PASSES_SANITIZE_LEAK=true
 . ./test-lib.sh
 
 test_expect_success 'setup' '
diff --git a/t/t7416-submodule-dash-url.sh b/t/t7416-submodule-dash-url.sh
index 3ebd9859814..7cf72b9a076 100755
--- a/t/t7416-submodule-dash-url.sh
+++ b/t/t7416-submodule-dash-url.sh
@@ -1,6 +1,8 @@
 #!/bin/sh
 
 test_description='check handling of disallowed .gitmodule urls'
+
+TEST_PASSES_SANITIZE_LEAK=true
 . ./test-lib.sh
 
 test_expect_success 'setup' '
diff --git a/t/t7450-bad-git-dotfiles.sh b/t/t7450-bad-git-dotfiles.sh
index ba1f569bcbb..0d0c3f2c683 100755
--- a/t/t7450-bad-git-dotfiles.sh
+++ b/t/t7450-bad-git-dotfiles.sh
@@ -12,6 +12,8 @@ Such as:
 
   - symlinked .gitmodules, etc
 '
+
+TEST_PASSES_SANITIZE_LEAK=true
 . ./test-lib.sh
 . "$TEST_DIRECTORY"/lib-pack.sh
 
-- 
2.39.0.1153.g589e4efe9dc


^ permalink raw reply related	[flat|nested] 193+ messages in thread

* Re: [PATCH v2 15/20] connected.c: free(new_pack) in check_connected()
  2022-12-30  2:18   ` [PATCH v2 15/20] connected.c: free(new_pack) in check_connected() Ævar Arnfjörð Bjarmason
@ 2022-12-30 16:17     ` René Scharfe
  2023-01-10  5:39       ` Ævar Arnfjörð Bjarmason
  0 siblings, 1 reply; 193+ messages in thread
From: René Scharfe @ 2022-12-30 16:17 UTC (permalink / raw)
  To: Ævar Arnfjörð Bjarmason, git; +Cc: Junio C Hamano, Eric Sunshine

Am 30.12.22 um 03:18 schrieb Ævar Arnfjörð Bjarmason:
> Fix a memory leak that's been with us since this code was introduced
> in c6807a40dcd (clone: open a shortcut for connectivity check,
> 2013-05-26). We'd never free() the "new_pack" that we'd potentially
> allocate.

That's obviously not true because the patch removes free() calls for
it, so at least some execution paths were already cleaning it up.

Taking a closer look, though: Is there a leaking execution path
without this patch at all?

   $ git grep -n return connected.c
   connected.c:41:		return err;
   connected.c:89:		return 0;
   connected.c:127:		return error(_("Could not run 'git rev-list'"));
   connected.c:161:	return finish_command(&rev_list) || err;

So there are four returns before.

> Since it's initialized to "NULL" it's safe to call free()
> here unconditionally.
>
> Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
> ---
>  connected.c | 13 +++++++------
>  1 file changed, 7 insertions(+), 6 deletions(-)
>
> diff --git a/connected.c b/connected.c
> index b90fd61790c..e4d404e10b2 100644
> --- a/connected.c
> +++ b/connected.c
> @@ -38,7 +38,7 @@ int check_connected(oid_iterate_fn fn, void *cb_data,
>  	if (!oid) {
>  		if (opt->err_fd)
>  			close(opt->err_fd);
> -		return err;
> +		goto cleanup;

Where are we?

   $ git grep -n new_pack.= connected.c
   connected.c:29:	struct packed_git *new_pack = NULL;
   connected.c:53:		new_pack = add_packed_git(idx_file.buf, idx_file.len, 1);

After new_pack is initialized to NULL, but before it is set to
point to some actual pack object.  So no free() is needed here.

>  	}
>
>  	if (transport && transport->smart_options &&
> @@ -85,8 +85,7 @@ int check_connected(oid_iterate_fn fn, void *cb_data,
>  promisor_pack_found:
>  			;
>  		} while ((oid = fn(cb_data)) != NULL);
> -		free(new_pack);
> -		return 0;
> +		goto cleanup;

free() removed, no leak before.

>  	}
>
>  no_promisor_pack_found:
> @@ -123,8 +122,8 @@ int check_connected(oid_iterate_fn fn, void *cb_data,
>  		rev_list.no_stderr = opt->quiet;
>
>  	if (start_command(&rev_list)) {
> -		free(new_pack);
> -		return error(_("Could not run 'git rev-list'"));
> +		err = error(_("Could not run 'git rev-list'"));
> +		goto cleanup;

Same here.

>  	}
>
>  	sigchain_push(SIGPIPE, SIG_IGN);
> @@ -157,6 +156,8 @@ int check_connected(oid_iterate_fn fn, void *cb_data,
>  		err = error_errno(_("failed to close rev-list's stdin"));
>
>  	sigchain_pop(SIGPIPE);
> +	err = finish_command(&rev_list) || err;
> +cleanup:
>  	free(new_pack);
> -	return finish_command(&rev_list) || err;
> +	return err;

free() kept, no leak before.

And that's all four returns.

So there is no leak to begin with here, or am I missing something?

>  }

^ permalink raw reply	[flat|nested] 193+ messages in thread

* Re: [PATCH v2 03/20] commit-graph: use free() instead of UNLEAK()
  2022-12-30  2:18   ` [PATCH v2 03/20] commit-graph: use free() instead of UNLEAK() Ævar Arnfjörð Bjarmason
@ 2022-12-30 16:26     ` René Scharfe
  0 siblings, 0 replies; 193+ messages in thread
From: René Scharfe @ 2022-12-30 16:26 UTC (permalink / raw)
  To: Ævar Arnfjörð Bjarmason, git; +Cc: Junio C Hamano, Eric Sunshine

Am 30.12.22 um 03:18 schrieb Ævar Arnfjörð Bjarmason:
> In 0bfb48e6723 (builtin/commit-graph.c: UNLEAK variables, 2018-10-03)
> this was made to UNLEAK(), but we can just as easily invoke the
> free_commit_graph() function added in c3756d5b7fc (commit-graph: add
> free_commit_graph, 2018-07-11) instead.

Patch and commit message are about free_commit_graph(), but the subject
still mentions free().

>
> Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
> ---
>  builtin/commit-graph.c | 6 ++++--
>  1 file changed, 4 insertions(+), 2 deletions(-)
>
> diff --git a/builtin/commit-graph.c b/builtin/commit-graph.c
> index e8f77f535f3..0102ac8540e 100644
> --- a/builtin/commit-graph.c
> +++ b/builtin/commit-graph.c
> @@ -67,6 +67,7 @@ static int graph_verify(int argc, const char **argv, const char *prefix)
>  	int fd;
>  	struct stat st;
>  	int flags = 0;
> +	int ret;
>
>  	static struct option builtin_commit_graph_verify_options[] = {
>  		OPT_BOOL(0, "shallow", &opts.shallow,
> @@ -111,8 +112,9 @@ static int graph_verify(int argc, const char **argv, const char *prefix)
>  	if (!graph)
>  		return !!open_ok;
>
> -	UNLEAK(graph);
> -	return verify_commit_graph(the_repository, graph, flags);
> +	ret = verify_commit_graph(the_repository, graph, flags);
> +	free_commit_graph(graph);
> +	return ret;
>  }
>
>  extern int read_replace_refs;

^ permalink raw reply	[flat|nested] 193+ messages in thread

* Re: [PATCH v2 15/20] connected.c: free(new_pack) in check_connected()
  2022-12-30 16:17     ` René Scharfe
@ 2023-01-10  5:39       ` Ævar Arnfjörð Bjarmason
  0 siblings, 0 replies; 193+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2023-01-10  5:39 UTC (permalink / raw)
  To: René Scharfe; +Cc: git, Junio C Hamano, Eric Sunshine


On Fri, Dec 30 2022, René Scharfe wrote:

> Am 30.12.22 um 03:18 schrieb Ævar Arnfjörð Bjarmason:
>> Fix a memory leak that's been with us since this code was introduced
>> in c6807a40dcd (clone: open a shortcut for connectivity check,
>> 2013-05-26). We'd never free() the "new_pack" that we'd potentially
>> allocate.
>
> That's obviously not true because the patch removes free() calls for
> it, so at least some execution paths were already cleaning it up.
>
> Taking a closer look, though: Is there a leaking execution path
> without this patch at all?
>
>    $ git grep -n return connected.c
>    connected.c:41:		return err;
>    connected.c:89:		return 0;
>    connected.c:127:		return error(_("Could not run 'git rev-list'"));
>    connected.c:161:	return finish_command(&rev_list) || err;
>
> So there are four returns before.
>
>> Since it's initialized to "NULL" it's safe to call free()
>> here unconditionally.
>>
>> Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
>> ---
>>  connected.c | 13 +++++++------
>>  1 file changed, 7 insertions(+), 6 deletions(-)
>>
>> diff --git a/connected.c b/connected.c
>> index b90fd61790c..e4d404e10b2 100644
>> --- a/connected.c
>> +++ b/connected.c
>> @@ -38,7 +38,7 @@ int check_connected(oid_iterate_fn fn, void *cb_data,
>>  	if (!oid) {
>>  		if (opt->err_fd)
>>  			close(opt->err_fd);
>> -		return err;
>> +		goto cleanup;
>
> Where are we?
>
>    $ git grep -n new_pack.= connected.c
>    connected.c:29:	struct packed_git *new_pack = NULL;
>    connected.c:53:		new_pack = add_packed_git(idx_file.buf, idx_file.len, 1);
>
> After new_pack is initialized to NULL, but before it is set to
> point to some actual pack object.  So no free() is needed here.
>
>>  	}
>>
>>  	if (transport && transport->smart_options &&
>> @@ -85,8 +85,7 @@ int check_connected(oid_iterate_fn fn, void *cb_data,
>>  promisor_pack_found:
>>  			;
>>  		} while ((oid = fn(cb_data)) != NULL);
>> -		free(new_pack);
>> -		return 0;
>> +		goto cleanup;
>
> free() removed, no leak before.
>
>>  	}
>>
>>  no_promisor_pack_found:
>> @@ -123,8 +122,8 @@ int check_connected(oid_iterate_fn fn, void *cb_data,
>>  		rev_list.no_stderr = opt->quiet;
>>
>>  	if (start_command(&rev_list)) {
>> -		free(new_pack);
>> -		return error(_("Could not run 'git rev-list'"));
>> +		err = error(_("Could not run 'git rev-list'"));
>> +		goto cleanup;
>
> Same here.
>
>>  	}
>>
>>  	sigchain_push(SIGPIPE, SIG_IGN);
>> @@ -157,6 +156,8 @@ int check_connected(oid_iterate_fn fn, void *cb_data,
>>  		err = error_errno(_("failed to close rev-list's stdin"));
>>
>>  	sigchain_pop(SIGPIPE);
>> +	err = finish_command(&rev_list) || err;
>> +cleanup:
>>  	free(new_pack);
>> -	return finish_command(&rev_list) || err;
>> +	return err;
>
> free() kept, no leak before.
>
> And that's all four returns.
>
> So there is no leak to begin with here, or am I missing something?

The commit message was just out of date, this was just the
post-refactoring for the already landed dd4143e7bf4 (connected.c: free
the "struct packed_git", 2022-11-08), but I forgot to update it.

I'll just drop this patch, as this series is meant to be leak fixes, not
such post-refactorings, sorry.

^ permalink raw reply	[flat|nested] 193+ messages in thread

* [PATCH v3 00/19] leak fixes: various simple leak fixes
  2022-12-30  2:18 ` [PATCH v2 00/20] leak fixes: various simple leak fixes Ævar Arnfjörð Bjarmason
                     ` (19 preceding siblings ...)
  2022-12-30  2:18   ` [PATCH v2 20/20] push: free_refs() the "local_refs" in set_refspecs() Ævar Arnfjörð Bjarmason
@ 2023-01-10  5:43   ` Ævar Arnfjörð Bjarmason
  2023-01-10  5:43     ` [PATCH v3 01/19] tests: mark tests as passing with SANITIZE=leak Ævar Arnfjörð Bjarmason
                       ` (19 more replies)
  20 siblings, 20 replies; 193+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2023-01-10  5:43 UTC (permalink / raw)
  To: git
  Cc: René Scharfe, Junio C Hamano, Eric Sunshine,
	Ævar Arnfjörð Bjarmason

A hopefully final version of this collection of simple leak fixes. See
https://lore.kernel.org/git/cover-v2-00.20-00000000000-20221230T020341Z-avarab@gmail.com/
for v2.

Changes since v2:

 * Updated reference to function name in a commit subject, spotted by
   René.

 * Dropped a patch that didn't fix a leak, but just did a post-cleanup
   of an already fixed leak.

Ævar Arnfjörð Bjarmason (19):
  tests: mark tests as passing with SANITIZE=leak
  bundle.c: don't leak the "args" in the "struct child_process"
  commit-graph: use free_commit_graph() instead of UNLEAK()
  clone: use free() instead of UNLEAK()
  various: add missing clear_pathspec(), fix leaks
  name-rev: don't xstrdup() an already dup'd string
  repack: fix leaks on error with "goto cleanup"
  worktree: fix a trivial leak in prune_worktrees()
  http-backend.c: fix "dir" and "cmd_arg" leaks in cmd_main()
  http-backend.c: fix cmd_main() memory leak, refactor reg{exec,free}()
  commit-graph: fix a parse_options_concat() leak
  show-branch: free() allocated "head" before return
  builtin/merge.c: always free "struct strbuf msg"
  builtin/merge.c: free "&buf" on "Your local changes..." error
  object-file.c: release the "tag" in check_tag()
  grep.c: refactor free_grep_patterns()
  grep API: plug memory leaks by freeing "header_list"
  receive-pack: free() the "ref_name" in "struct command"
  push: free_refs() the "local_refs" in set_refspecs()

 archive.c                                  |  1 +
 builtin/clean.c                            |  1 +
 builtin/clone.c                            |  5 +++--
 builtin/commit-graph.c                     | 10 ++++++----
 builtin/merge.c                            | 14 ++++++-------
 builtin/name-rev.c                         | 23 ++++++++++------------
 builtin/push.c                             |  1 +
 builtin/receive-pack.c                     | 10 ++++++++++
 builtin/repack.c                           | 13 ++++++------
 builtin/reset.c                            | 11 ++++++++---
 builtin/show-branch.c                      |  1 +
 builtin/stash.c                            |  7 +++++--
 builtin/worktree.c                         |  6 +++---
 bundle.c                                   |  6 ++++--
 grep.c                                     | 15 +++++++++-----
 http-backend.c                             |  9 +++++++--
 object-file.c                              |  1 +
 t/t0023-crlf-am.sh                         |  1 +
 t/t1301-shared-repo.sh                     |  1 +
 t/t1302-repo-version.sh                    |  1 +
 t/t1304-default-acl.sh                     |  1 +
 t/t1408-packed-refs.sh                     |  1 +
 t/t1410-reflog.sh                          |  1 +
 t/t1416-ref-transaction-hooks.sh           |  1 +
 t/t2401-worktree-prune.sh                  |  1 +
 t/t2406-worktree-repair.sh                 |  1 +
 t/t3210-pack-refs.sh                       |  1 +
 t/t3800-mktag.sh                           |  1 +
 t/t4152-am-subjects.sh                     |  2 ++
 t/t4254-am-corrupt.sh                      |  2 ++
 t/t4256-am-format-flowed.sh                |  1 +
 t/t4257-am-interactive.sh                  |  2 ++
 t/t5001-archive-attr.sh                    |  1 +
 t/t5004-archive-corner-cases.sh            |  2 ++
 t/t5302-pack-index.sh                      |  2 ++
 t/t5317-pack-objects-filter-objects.sh     |  1 +
 t/t5330-no-lazy-fetch-with-commit-graph.sh |  1 +
 t/t5403-post-checkout-hook.sh              |  1 +
 t/t5405-send-pack-rewind.sh                |  1 +
 t/t5406-remote-rejects.sh                  |  1 +
 t/t5502-quickfetch.sh                      |  1 +
 t/t5504-fetch-receive-strict.sh            |  1 +
 t/t5507-remote-environment.sh              |  2 ++
 t/t5522-pull-symlink.sh                    |  1 +
 t/t5523-push-upstream.sh                   |  1 +
 t/t5527-fetch-odd-refs.sh                  |  1 +
 t/t5529-push-errors.sh                     |  2 ++
 t/t5546-receive-limits.sh                  |  2 ++
 t/t5547-push-quarantine.sh                 |  2 ++
 t/t5604-clone-reference.sh                 |  1 +
 t/t5606-clone-options.sh                   |  1 +
 t/t5613-info-alternate.sh                  |  2 ++
 t/t5705-session-id-in-capabilities.sh      |  1 +
 t/t5810-proto-disable-local.sh             |  2 ++
 t/t5813-proto-disable-ssh.sh               |  2 ++
 t/t6011-rev-list-with-bad-commit.sh        |  1 +
 t/t6014-rev-list-all.sh                    |  1 +
 t/t6021-rev-list-exclude-hidden.sh         |  1 +
 t/t6439-merge-co-error-msgs.sh             |  1 +
 t/t7105-reset-patch.sh                     |  2 ++
 t/t7106-reset-unborn-branch.sh             |  2 ++
 t/t7107-reset-pathspec-file.sh             |  1 +
 t/t7301-clean-interactive.sh               |  1 +
 t/t7403-submodule-sync.sh                  |  1 +
 t/t7409-submodule-detached-work-tree.sh    |  1 +
 t/t7416-submodule-dash-url.sh              |  2 ++
 t/t7450-bad-git-dotfiles.sh                |  2 ++
 t/t7701-repack-unpack-unreachable.sh       |  1 +
 68 files changed, 151 insertions(+), 50 deletions(-)

Range-diff against v2:
 1:  3de29c6d75f =  1:  f5b67f44e2d tests: mark tests as passing with SANITIZE=leak
 2:  5036712391d =  2:  88c6b66be3c bundle.c: don't leak the "args" in the "struct child_process"
 3:  a840a1cb330 !  3:  8cc8060cd92 commit-graph: use free() instead of UNLEAK()
    @@ Metadata
     Author: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
     
      ## Commit message ##
    -    commit-graph: use free() instead of UNLEAK()
    +    commit-graph: use free_commit_graph() instead of UNLEAK()
     
         In 0bfb48e6723 (builtin/commit-graph.c: UNLEAK variables, 2018-10-03)
         this was made to UNLEAK(), but we can just as easily invoke the
 4:  c05620cef49 =  4:  765d5cbcf81 clone: use free() instead of UNLEAK()
 5:  62af6557760 =  5:  5087fb73286 various: add missing clear_pathspec(), fix leaks
 6:  7cea3da9fae =  6:  39cb8aefb58 name-rev: don't xstrdup() an already dup'd string
 7:  b5978d75c6a =  7:  a3f1e800127 repack: fix leaks on error with "goto cleanup"
 8:  468615570f4 =  8:  f918a6f2adc worktree: fix a trivial leak in prune_worktrees()
 9:  8c5c964d872 =  9:  56204806dfd http-backend.c: fix "dir" and "cmd_arg" leaks in cmd_main()
10:  fd34c4817f4 = 10:  5355e0fc60b http-backend.c: fix cmd_main() memory leak, refactor reg{exec,free}()
11:  f7005f32cc0 = 11:  dfb52dbd1c4 commit-graph: fix a parse_options_concat() leak
12:  bf0e9bc5fa6 = 12:  e44e74dcc58 show-branch: free() allocated "head" before return
13:  b157092e8d0 = 13:  6d99fdcc44e builtin/merge.c: always free "struct strbuf msg"
14:  bdd2bc9a956 = 14:  a3bf3045597 builtin/merge.c: free "&buf" on "Your local changes..." error
15:  d5210017cab <  -:  ----------- connected.c: free(new_pack) in check_connected()
16:  2016b4ddd0b = 15:  7c70bbdebc8 object-file.c: release the "tag" in check_tag()
17:  fa2e8a7d297 = 16:  17537e1393e grep.c: refactor free_grep_patterns()
18:  3fcf7054708 = 17:  e4bd46a343e grep API: plug memory leaks by freeing "header_list"
19:  fa5d657312f = 18:  3e4b12cb623 receive-pack: free() the "ref_name" in "struct command"
20:  e5af27134df = 19:  d51ed239a8a push: free_refs() the "local_refs" in set_refspecs()
-- 
2.39.0.1195.gabc92c078c4


^ permalink raw reply	[flat|nested] 193+ messages in thread

* [PATCH v3 01/19] tests: mark tests as passing with SANITIZE=leak
  2023-01-10  5:43   ` [PATCH v3 00/19] leak fixes: various simple leak fixes Ævar Arnfjörð Bjarmason
@ 2023-01-10  5:43     ` Ævar Arnfjörð Bjarmason
  2023-01-10  5:43     ` [PATCH v3 02/19] bundle.c: don't leak the "args" in the "struct child_process" Ævar Arnfjörð Bjarmason
                       ` (18 subsequent siblings)
  19 siblings, 0 replies; 193+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2023-01-10  5:43 UTC (permalink / raw)
  To: git
  Cc: René Scharfe, Junio C Hamano, Eric Sunshine,
	Ævar Arnfjörð Bjarmason

When the "ab/various-leak-fixes" topic was merged in [1] only t6021
would fail if the tests were run in the
"GIT_TEST_PASSING_SANITIZE_LEAK=check" mode, i.e. to check whether we
marked all leak-free tests with "TEST_PASSES_SANITIZE_LEAK=true".

Since then we've had various tests starting to pass under
SANITIZE=leak. Let's mark those as passing, this is when they started
to pass, narrowed down with "git bisect":

- t5317-pack-objects-filter-objects.sh: In
  faebba436e6 (list-objects-filter: plug pattern_list leak, 2022-12-01).

- t3210-pack-refs.sh, t5613-info-alternate.sh,
  t7403-submodule-sync.sh: In 189e97bc4ba (diff: remove parseopts member
  from struct diff_options, 2022-12-01).

- t1408-packed-refs.sh: In ab91f6b7c42 (Merge branch
  'rs/diff-parseopts', 2022-12-19).

- t0023-crlf-am.sh, t4152-am-subjects.sh, t4254-am-corrupt.sh,
  t4256-am-format-flowed.sh, t4257-am-interactive.sh,
  t5403-post-checkout-hook.sh: In a658e881c13 (am: don't pass strvec to
  apply_parse_options(), 2022-12-13)

- t1301-shared-repo.sh, t1302-repo-version.sh: In b07a819c05f (reflog:
  clear leftovers in reflog_expiry_cleanup(), 2022-12-13).

- t1304-default-acl.sh, t1410-reflog.sh,
  t5330-no-lazy-fetch-with-commit-graph.sh, t5502-quickfetch.sh,
  t5604-clone-reference.sh, t6014-rev-list-all.sh,
  t7701-repack-unpack-unreachable.sh: In b0c61be3209 (Merge branch
  'rs/reflog-expiry-cleanup', 2022-12-26)

1. 9ea1378d046 (Merge branch 'ab/various-leak-fixes', 2022-12-14)

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 t/t0023-crlf-am.sh                         | 1 +
 t/t1301-shared-repo.sh                     | 1 +
 t/t1302-repo-version.sh                    | 1 +
 t/t1304-default-acl.sh                     | 1 +
 t/t1408-packed-refs.sh                     | 1 +
 t/t1410-reflog.sh                          | 1 +
 t/t3210-pack-refs.sh                       | 1 +
 t/t4152-am-subjects.sh                     | 2 ++
 t/t4254-am-corrupt.sh                      | 2 ++
 t/t4256-am-format-flowed.sh                | 1 +
 t/t4257-am-interactive.sh                  | 2 ++
 t/t5317-pack-objects-filter-objects.sh     | 1 +
 t/t5330-no-lazy-fetch-with-commit-graph.sh | 1 +
 t/t5403-post-checkout-hook.sh              | 1 +
 t/t5502-quickfetch.sh                      | 1 +
 t/t5604-clone-reference.sh                 | 1 +
 t/t5613-info-alternate.sh                  | 2 ++
 t/t6014-rev-list-all.sh                    | 1 +
 t/t6021-rev-list-exclude-hidden.sh         | 1 +
 t/t7403-submodule-sync.sh                  | 1 +
 t/t7701-repack-unpack-unreachable.sh       | 1 +
 21 files changed, 25 insertions(+)

diff --git a/t/t0023-crlf-am.sh b/t/t0023-crlf-am.sh
index f9bbb91f64e..575805513a3 100755
--- a/t/t0023-crlf-am.sh
+++ b/t/t0023-crlf-am.sh
@@ -2,6 +2,7 @@
 
 test_description='Test am with auto.crlf'
 
+TEST_PASSES_SANITIZE_LEAK=true
 . ./test-lib.sh
 
 cat >patchfile <<\EOF
diff --git a/t/t1301-shared-repo.sh b/t/t1301-shared-repo.sh
index 93a2f91f8a5..a1251f65100 100755
--- a/t/t1301-shared-repo.sh
+++ b/t/t1301-shared-repo.sh
@@ -8,6 +8,7 @@ test_description='Test shared repository initialization'
 GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
 export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
 
+TEST_PASSES_SANITIZE_LEAK=true
 . ./test-lib.sh
 
 # Remove a default ACL from the test dir if possible.
diff --git a/t/t1302-repo-version.sh b/t/t1302-repo-version.sh
index 7cf80bf66a6..70389fa2ebb 100755
--- a/t/t1302-repo-version.sh
+++ b/t/t1302-repo-version.sh
@@ -5,6 +5,7 @@
 
 test_description='Test repository version check'
 
+TEST_PASSES_SANITIZE_LEAK=true
 . ./test-lib.sh
 
 test_expect_success 'setup' '
diff --git a/t/t1304-default-acl.sh b/t/t1304-default-acl.sh
index c69ae41306c..31b89dd9693 100755
--- a/t/t1304-default-acl.sh
+++ b/t/t1304-default-acl.sh
@@ -9,6 +9,7 @@ test_description='Test repository with default ACL'
 # => this must come before . ./test-lib.sh
 umask 077
 
+TEST_PASSES_SANITIZE_LEAK=true
 . ./test-lib.sh
 
 # We need an arbitrary other user give permission to using ACLs. root
diff --git a/t/t1408-packed-refs.sh b/t/t1408-packed-refs.sh
index 41ba1f1d7fc..9469c79a585 100755
--- a/t/t1408-packed-refs.sh
+++ b/t/t1408-packed-refs.sh
@@ -5,6 +5,7 @@ test_description='packed-refs entries are covered by loose refs'
 GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
 export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
 
+TEST_PASSES_SANITIZE_LEAK=true
 . ./test-lib.sh
 
 test_expect_success setup '
diff --git a/t/t1410-reflog.sh b/t/t1410-reflog.sh
index aa59954f6c5..6c45965b1e4 100755
--- a/t/t1410-reflog.sh
+++ b/t/t1410-reflog.sh
@@ -7,6 +7,7 @@ test_description='Test prune and reflog expiration'
 GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
 export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
 
+TEST_PASSES_SANITIZE_LEAK=true
 . ./test-lib.sh
 
 check_have () {
diff --git a/t/t3210-pack-refs.sh b/t/t3210-pack-refs.sh
index 577f32dc71f..07a0ff93def 100755
--- a/t/t3210-pack-refs.sh
+++ b/t/t3210-pack-refs.sh
@@ -12,6 +12,7 @@ semantic is still the same.
 GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
 export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
 
+TEST_PASSES_SANITIZE_LEAK=true
 . ./test-lib.sh
 
 test_expect_success 'enable reflogs' '
diff --git a/t/t4152-am-subjects.sh b/t/t4152-am-subjects.sh
index 4c68245acad..9f2edba1f83 100755
--- a/t/t4152-am-subjects.sh
+++ b/t/t4152-am-subjects.sh
@@ -1,6 +1,8 @@
 #!/bin/sh
 
 test_description='test subject preservation with format-patch | am'
+
+TEST_PASSES_SANITIZE_LEAK=true
 . ./test-lib.sh
 
 make_patches() {
diff --git a/t/t4254-am-corrupt.sh b/t/t4254-am-corrupt.sh
index 54be7da1611..45f1d4f95e5 100755
--- a/t/t4254-am-corrupt.sh
+++ b/t/t4254-am-corrupt.sh
@@ -1,6 +1,8 @@
 #!/bin/sh
 
 test_description='git am with corrupt input'
+
+TEST_PASSES_SANITIZE_LEAK=true
 . ./test-lib.sh
 
 make_mbox_with_nul () {
diff --git a/t/t4256-am-format-flowed.sh b/t/t4256-am-format-flowed.sh
index 2369c4e17ad..1015273bc82 100755
--- a/t/t4256-am-format-flowed.sh
+++ b/t/t4256-am-format-flowed.sh
@@ -2,6 +2,7 @@
 
 test_description='test format=flowed support of git am'
 
+TEST_PASSES_SANITIZE_LEAK=true
 . ./test-lib.sh
 
 test_expect_success 'setup' '
diff --git a/t/t4257-am-interactive.sh b/t/t4257-am-interactive.sh
index aed8f4de3d6..f26d7fd2dbd 100755
--- a/t/t4257-am-interactive.sh
+++ b/t/t4257-am-interactive.sh
@@ -1,6 +1,8 @@
 #!/bin/sh
 
 test_description='am --interactive tests'
+
+TEST_PASSES_SANITIZE_LEAK=true
 . ./test-lib.sh
 
 test_expect_success 'set up patches to apply' '
diff --git a/t/t5317-pack-objects-filter-objects.sh b/t/t5317-pack-objects-filter-objects.sh
index 5b707d911b5..b26d476c646 100755
--- a/t/t5317-pack-objects-filter-objects.sh
+++ b/t/t5317-pack-objects-filter-objects.sh
@@ -5,6 +5,7 @@ test_description='git pack-objects using object filtering'
 GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
 export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
 
+TEST_PASSES_SANITIZE_LEAK=true
 . ./test-lib.sh
 
 # Test blob:none filter.
diff --git a/t/t5330-no-lazy-fetch-with-commit-graph.sh b/t/t5330-no-lazy-fetch-with-commit-graph.sh
index 2cc7fd7a476..5eb28f0512d 100755
--- a/t/t5330-no-lazy-fetch-with-commit-graph.sh
+++ b/t/t5330-no-lazy-fetch-with-commit-graph.sh
@@ -2,6 +2,7 @@
 
 test_description='test for no lazy fetch with the commit-graph'
 
+TEST_PASSES_SANITIZE_LEAK=true
 . ./test-lib.sh
 
 test_expect_success 'setup: prepare a repository with a commit' '
diff --git a/t/t5403-post-checkout-hook.sh b/t/t5403-post-checkout-hook.sh
index 978f240cdac..cfaae547398 100755
--- a/t/t5403-post-checkout-hook.sh
+++ b/t/t5403-post-checkout-hook.sh
@@ -7,6 +7,7 @@ test_description='Test the post-checkout hook.'
 GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
 export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
 
+TEST_PASSES_SANITIZE_LEAK=true
 . ./test-lib.sh
 
 test_expect_success setup '
diff --git a/t/t5502-quickfetch.sh b/t/t5502-quickfetch.sh
index b160f8b7fb7..7b3ff21b984 100755
--- a/t/t5502-quickfetch.sh
+++ b/t/t5502-quickfetch.sh
@@ -5,6 +5,7 @@ test_description='test quickfetch from local'
 GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
 export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
 
+TEST_PASSES_SANITIZE_LEAK=true
 . ./test-lib.sh
 
 test_expect_success setup '
diff --git a/t/t5604-clone-reference.sh b/t/t5604-clone-reference.sh
index 2734e37e880..dc86dea1333 100755
--- a/t/t5604-clone-reference.sh
+++ b/t/t5604-clone-reference.sh
@@ -7,6 +7,7 @@ test_description='test clone --reference'
 GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
 export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
 
+TEST_PASSES_SANITIZE_LEAK=true
 . ./test-lib.sh
 
 base_dir=$(pwd)
diff --git a/t/t5613-info-alternate.sh b/t/t5613-info-alternate.sh
index 895f46bb911..7708cbafa98 100755
--- a/t/t5613-info-alternate.sh
+++ b/t/t5613-info-alternate.sh
@@ -4,6 +4,8 @@
 #
 
 test_description='test transitive info/alternate entries'
+
+TEST_PASSES_SANITIZE_LEAK=true
 . ./test-lib.sh
 
 test_expect_success 'preparing first repository' '
diff --git a/t/t6014-rev-list-all.sh b/t/t6014-rev-list-all.sh
index c9bedd29cba..16b8bd1d090 100755
--- a/t/t6014-rev-list-all.sh
+++ b/t/t6014-rev-list-all.sh
@@ -2,6 +2,7 @@
 
 test_description='--all includes detached HEADs'
 
+TEST_PASSES_SANITIZE_LEAK=true
 . ./test-lib.sh
 
 
diff --git a/t/t6021-rev-list-exclude-hidden.sh b/t/t6021-rev-list-exclude-hidden.sh
index 32b2b094138..11c50b7c0dd 100755
--- a/t/t6021-rev-list-exclude-hidden.sh
+++ b/t/t6021-rev-list-exclude-hidden.sh
@@ -2,6 +2,7 @@
 
 test_description='git rev-list --exclude-hidden test'
 
+TEST_PASSES_SANITIZE_LEAK=true
 . ./test-lib.sh
 
 test_expect_success 'setup' '
diff --git a/t/t7403-submodule-sync.sh b/t/t7403-submodule-sync.sh
index ea92ef52a5e..ff09443a0a4 100755
--- a/t/t7403-submodule-sync.sh
+++ b/t/t7403-submodule-sync.sh
@@ -11,6 +11,7 @@ These tests exercise the "git submodule sync" subcommand.
 GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
 export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
 
+TEST_PASSES_SANITIZE_LEAK=true
 . ./test-lib.sh
 
 test_expect_success setup '
diff --git a/t/t7701-repack-unpack-unreachable.sh b/t/t7701-repack-unpack-unreachable.sh
index b7ac4f598a8..ebb267855fe 100755
--- a/t/t7701-repack-unpack-unreachable.sh
+++ b/t/t7701-repack-unpack-unreachable.sh
@@ -5,6 +5,7 @@ test_description='git repack works correctly'
 GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
 export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
 
+TEST_PASSES_SANITIZE_LEAK=true
 . ./test-lib.sh
 
 fsha1=
-- 
2.39.0.1195.gabc92c078c4


^ permalink raw reply related	[flat|nested] 193+ messages in thread

* [PATCH v3 02/19] bundle.c: don't leak the "args" in the "struct child_process"
  2023-01-10  5:43   ` [PATCH v3 00/19] leak fixes: various simple leak fixes Ævar Arnfjörð Bjarmason
  2023-01-10  5:43     ` [PATCH v3 01/19] tests: mark tests as passing with SANITIZE=leak Ævar Arnfjörð Bjarmason
@ 2023-01-10  5:43     ` Ævar Arnfjörð Bjarmason
  2023-01-10  5:43     ` [PATCH v3 03/19] commit-graph: use free_commit_graph() instead of UNLEAK() Ævar Arnfjörð Bjarmason
                       ` (17 subsequent siblings)
  19 siblings, 0 replies; 193+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2023-01-10  5:43 UTC (permalink / raw)
  To: git
  Cc: René Scharfe, Junio C Hamano, Eric Sunshine,
	Ævar Arnfjörð Bjarmason

Fix a leak that's been here since 7366096de9d (bundle API: change
"flags" to be "extra_index_pack_args", 2021-09-05), if can't verify
the bundle we didn't call child_process_clear() to clear the "args".

But rather than doing that let's verify the bundle before we start
preparing the process we're going to spawn, if we get an error we
don't need to push anything to the "args".

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 bundle.c | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/bundle.c b/bundle.c
index 4ef7256aa11..9ebb10a8f72 100644
--- a/bundle.c
+++ b/bundle.c
@@ -627,6 +627,10 @@ int unbundle(struct repository *r, struct bundle_header *header,
 	     enum verify_bundle_flags flags)
 {
 	struct child_process ip = CHILD_PROCESS_INIT;
+
+	if (verify_bundle(r, header, flags))
+		return -1;
+
 	strvec_pushl(&ip.args, "index-pack", "--fix-thin", "--stdin", NULL);
 
 	/* If there is a filter, then we need to create the promisor pack. */
@@ -638,8 +642,6 @@ int unbundle(struct repository *r, struct bundle_header *header,
 		strvec_clear(extra_index_pack_args);
 	}
 
-	if (verify_bundle(r, header, flags))
-		return -1;
 	ip.in = bundle_fd;
 	ip.no_stdout = 1;
 	ip.git_cmd = 1;
-- 
2.39.0.1195.gabc92c078c4


^ permalink raw reply related	[flat|nested] 193+ messages in thread

* [PATCH v3 03/19] commit-graph: use free_commit_graph() instead of UNLEAK()
  2023-01-10  5:43   ` [PATCH v3 00/19] leak fixes: various simple leak fixes Ævar Arnfjörð Bjarmason
  2023-01-10  5:43     ` [PATCH v3 01/19] tests: mark tests as passing with SANITIZE=leak Ævar Arnfjörð Bjarmason
  2023-01-10  5:43     ` [PATCH v3 02/19] bundle.c: don't leak the "args" in the "struct child_process" Ævar Arnfjörð Bjarmason
@ 2023-01-10  5:43     ` Ævar Arnfjörð Bjarmason
  2023-01-10  5:43     ` [PATCH v3 04/19] clone: use free() " Ævar Arnfjörð Bjarmason
                       ` (16 subsequent siblings)
  19 siblings, 0 replies; 193+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2023-01-10  5:43 UTC (permalink / raw)
  To: git
  Cc: René Scharfe, Junio C Hamano, Eric Sunshine,
	Ævar Arnfjörð Bjarmason

In 0bfb48e6723 (builtin/commit-graph.c: UNLEAK variables, 2018-10-03)
this was made to UNLEAK(), but we can just as easily invoke the
free_commit_graph() function added in c3756d5b7fc (commit-graph: add
free_commit_graph, 2018-07-11) instead.

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 builtin/commit-graph.c | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/builtin/commit-graph.c b/builtin/commit-graph.c
index e8f77f535f3..0102ac8540e 100644
--- a/builtin/commit-graph.c
+++ b/builtin/commit-graph.c
@@ -67,6 +67,7 @@ static int graph_verify(int argc, const char **argv, const char *prefix)
 	int fd;
 	struct stat st;
 	int flags = 0;
+	int ret;
 
 	static struct option builtin_commit_graph_verify_options[] = {
 		OPT_BOOL(0, "shallow", &opts.shallow,
@@ -111,8 +112,9 @@ static int graph_verify(int argc, const char **argv, const char *prefix)
 	if (!graph)
 		return !!open_ok;
 
-	UNLEAK(graph);
-	return verify_commit_graph(the_repository, graph, flags);
+	ret = verify_commit_graph(the_repository, graph, flags);
+	free_commit_graph(graph);
+	return ret;
 }
 
 extern int read_replace_refs;
-- 
2.39.0.1195.gabc92c078c4


^ permalink raw reply related	[flat|nested] 193+ messages in thread

* [PATCH v3 04/19] clone: use free() instead of UNLEAK()
  2023-01-10  5:43   ` [PATCH v3 00/19] leak fixes: various simple leak fixes Ævar Arnfjörð Bjarmason
                       ` (2 preceding siblings ...)
  2023-01-10  5:43     ` [PATCH v3 03/19] commit-graph: use free_commit_graph() instead of UNLEAK() Ævar Arnfjörð Bjarmason
@ 2023-01-10  5:43     ` Ævar Arnfjörð Bjarmason
  2023-01-10  5:43     ` [PATCH v3 05/19] various: add missing clear_pathspec(), fix leaks Ævar Arnfjörð Bjarmason
                       ` (15 subsequent siblings)
  19 siblings, 0 replies; 193+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2023-01-10  5:43 UTC (permalink / raw)
  To: git
  Cc: René Scharfe, Junio C Hamano, Eric Sunshine,
	Ævar Arnfjörð Bjarmason

Change an UNLEAK() added in 0c4542738e6 (clone: free or UNLEAK further
pointers when finished, 2021-03-14) to use a "to_free" pattern
instead. In this case the "repo" can be either this absolute_pathdup()
value, or in the "else if" branch seen in the context the the
"argv[0]" argument to "main()".

We can only free() the value in the former case, hence the "to_free"
pattern.

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 builtin/clone.c | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/builtin/clone.c b/builtin/clone.c
index 5453ba5277f..ba82f5e4108 100644
--- a/builtin/clone.c
+++ b/builtin/clone.c
@@ -892,6 +892,7 @@ int cmd_clone(int argc, const char **argv, const char *prefix)
 	int is_bundle = 0, is_local;
 	int reject_shallow = 0;
 	const char *repo_name, *repo, *work_tree, *git_dir;
+	char *repo_to_free = NULL;
 	char *path = NULL, *dir, *display_repo = NULL;
 	int dest_exists, real_dest_exists = 0;
 	const struct ref *refs, *remote_head;
@@ -949,7 +950,7 @@ int cmd_clone(int argc, const char **argv, const char *prefix)
 	path = get_repo_path(repo_name, &is_bundle);
 	if (path) {
 		FREE_AND_NULL(path);
-		repo = absolute_pathdup(repo_name);
+		repo = repo_to_free = absolute_pathdup(repo_name);
 	} else if (strchr(repo_name, ':')) {
 		repo = repo_name;
 		display_repo = transport_anonymize_url(repo);
@@ -1413,7 +1414,7 @@ int cmd_clone(int argc, const char **argv, const char *prefix)
 	free(unborn_head);
 	free(dir);
 	free(path);
-	UNLEAK(repo);
+	free(repo_to_free);
 	junk_mode = JUNK_LEAVE_ALL;
 
 	transport_ls_refs_options_release(&transport_ls_refs_options);
-- 
2.39.0.1195.gabc92c078c4


^ permalink raw reply related	[flat|nested] 193+ messages in thread

* [PATCH v3 05/19] various: add missing clear_pathspec(), fix leaks
  2023-01-10  5:43   ` [PATCH v3 00/19] leak fixes: various simple leak fixes Ævar Arnfjörð Bjarmason
                       ` (3 preceding siblings ...)
  2023-01-10  5:43     ` [PATCH v3 04/19] clone: use free() " Ævar Arnfjörð Bjarmason
@ 2023-01-10  5:43     ` Ævar Arnfjörð Bjarmason
  2023-01-10  5:43     ` [PATCH v3 06/19] name-rev: don't xstrdup() an already dup'd string Ævar Arnfjörð Bjarmason
                       ` (14 subsequent siblings)
  19 siblings, 0 replies; 193+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2023-01-10  5:43 UTC (permalink / raw)
  To: git
  Cc: René Scharfe, Junio C Hamano, Eric Sunshine,
	Ævar Arnfjörð Bjarmason

Fix memory leaks resulting from a missing clear_pathspec().

- archive.c: Plug a leak in the "struct archiver_args", and
  clear_pathspec() the "pathspec" member that the "parse_pathspec_arg()"
  call in this function populates.

- builtin/clean.c: Fix a memory leak that's been with us since
  893d839970c (clean: convert to use parse_pathspec, 2013-07-14).

- builtin/reset.c: Add clear_pathspec() calls to cmd_reset(),
  including to the codepaths where we'd return early.

- builtin/stash.c: Call clear_pathspec() on the pathspec initialized
  in push_stash().

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 archive.c                       |  1 +
 builtin/clean.c                 |  1 +
 builtin/reset.c                 | 11 ++++++++---
 builtin/stash.c                 |  7 +++++--
 t/t5001-archive-attr.sh         |  1 +
 t/t5004-archive-corner-cases.sh |  2 ++
 t/t7105-reset-patch.sh          |  2 ++
 t/t7106-reset-unborn-branch.sh  |  2 ++
 t/t7107-reset-pathspec-file.sh  |  1 +
 t/t7301-clean-interactive.sh    |  1 +
 10 files changed, 24 insertions(+), 5 deletions(-)

diff --git a/archive.c b/archive.c
index 941495f5d78..a2d813e50db 100644
--- a/archive.c
+++ b/archive.c
@@ -710,6 +710,7 @@ int write_archive(int argc, const char **argv, const char *prefix,
 
 	string_list_clear_func(&args.extra_files, extra_file_info_clear);
 	free(args.refname);
+	clear_pathspec(&args.pathspec);
 
 	return rc;
 }
diff --git a/builtin/clean.c b/builtin/clean.c
index b2701a28158..b15eab328b7 100644
--- a/builtin/clean.c
+++ b/builtin/clean.c
@@ -1092,5 +1092,6 @@ int cmd_clean(int argc, const char **argv, const char *prefix)
 	strbuf_release(&buf);
 	string_list_clear(&del_list, 0);
 	string_list_clear(&exclude_list, 0);
+	clear_pathspec(&pathspec);
 	return (errors != 0);
 }
diff --git a/builtin/reset.c b/builtin/reset.c
index fea20a9ba0b..e9c10618cd3 100644
--- a/builtin/reset.c
+++ b/builtin/reset.c
@@ -390,7 +390,8 @@ int cmd_reset(int argc, const char **argv, const char *prefix)
 		if (reset_type != NONE)
 			die(_("options '%s' and '%s' cannot be used together"), "--patch", "--{hard,mixed,soft}");
 		trace2_cmd_mode("patch-interactive");
-		return run_add_interactive(rev, "--patch=reset", &pathspec);
+		update_ref_status = run_add_interactive(rev, "--patch=reset", &pathspec);
+		goto cleanup;
 	}
 
 	/* git reset tree [--] paths... can be used to
@@ -439,8 +440,10 @@ int cmd_reset(int argc, const char **argv, const char *prefix)
 				       LOCK_DIE_ON_ERROR);
 		if (reset_type == MIXED) {
 			int flags = quiet ? REFRESH_QUIET : REFRESH_IN_PORCELAIN;
-			if (read_from_tree(&pathspec, &oid, intent_to_add))
-				return 1;
+			if (read_from_tree(&pathspec, &oid, intent_to_add)) {
+				update_ref_status = 1;
+				goto cleanup;
+			}
 			the_index.updated_skipworktree = 1;
 			if (!no_refresh && get_git_work_tree()) {
 				uint64_t t_begin, t_delta_in_ms;
@@ -488,5 +491,7 @@ int cmd_reset(int argc, const char **argv, const char *prefix)
 
 	discard_index(&the_index);
 
+cleanup:
+	clear_pathspec(&pathspec);
 	return update_ref_status;
 }
diff --git a/builtin/stash.c b/builtin/stash.c
index bb0fd861434..45bffdf54bb 100644
--- a/builtin/stash.c
+++ b/builtin/stash.c
@@ -1727,6 +1727,7 @@ static int push_stash(int argc, const char **argv, const char *prefix,
 		OPT_PATHSPEC_FILE_NUL(&pathspec_file_nul),
 		OPT_END()
 	};
+	int ret;
 
 	if (argc) {
 		force_assume = !strcmp(argv[0], "-p");
@@ -1766,8 +1767,10 @@ static int push_stash(int argc, const char **argv, const char *prefix,
 		die(_("the option '%s' requires '%s'"), "--pathspec-file-nul", "--pathspec-from-file");
 	}
 
-	return do_push_stash(&ps, stash_msg, quiet, keep_index, patch_mode,
-			     include_untracked, only_staged);
+	ret = do_push_stash(&ps, stash_msg, quiet, keep_index, patch_mode,
+			    include_untracked, only_staged);
+	clear_pathspec(&ps);
+	return ret;
 }
 
 static int push_stash_unassumed(int argc, const char **argv, const char *prefix)
diff --git a/t/t5001-archive-attr.sh b/t/t5001-archive-attr.sh
index 2f6eef5e372..04d300eeda7 100755
--- a/t/t5001-archive-attr.sh
+++ b/t/t5001-archive-attr.sh
@@ -3,6 +3,7 @@
 test_description='git archive attribute tests'
 
 TEST_CREATE_REPO_NO_TEMPLATE=1
+TEST_PASSES_SANITIZE_LEAK=true
 . ./test-lib.sh
 
 SUBSTFORMAT='%H (%h)%n'
diff --git a/t/t5004-archive-corner-cases.sh b/t/t5004-archive-corner-cases.sh
index ae508e21623..9f2c6da80e8 100755
--- a/t/t5004-archive-corner-cases.sh
+++ b/t/t5004-archive-corner-cases.sh
@@ -1,6 +1,8 @@
 #!/bin/sh
 
 test_description='test corner cases of git-archive'
+
+TEST_PASSES_SANITIZE_LEAK=true
 . ./test-lib.sh
 
 # the 10knuls.tar file is used to test for an empty git generated tar
diff --git a/t/t7105-reset-patch.sh b/t/t7105-reset-patch.sh
index fc2a6cf5c7a..9b46da7aaa7 100755
--- a/t/t7105-reset-patch.sh
+++ b/t/t7105-reset-patch.sh
@@ -1,6 +1,8 @@
 #!/bin/sh
 
 test_description='git reset --patch'
+
+TEST_PASSES_SANITIZE_LEAK=true
 . ./lib-patch-mode.sh
 
 test_expect_success PERL 'setup' '
diff --git a/t/t7106-reset-unborn-branch.sh b/t/t7106-reset-unborn-branch.sh
index ecb85c3b823..a0b67a0b843 100755
--- a/t/t7106-reset-unborn-branch.sh
+++ b/t/t7106-reset-unborn-branch.sh
@@ -1,6 +1,8 @@
 #!/bin/sh
 
 test_description='git reset should work on unborn branch'
+
+TEST_PASSES_SANITIZE_LEAK=true
 . ./test-lib.sh
 
 test_expect_success 'setup' '
diff --git a/t/t7107-reset-pathspec-file.sh b/t/t7107-reset-pathspec-file.sh
index 523efbecde1..af5ea406db3 100755
--- a/t/t7107-reset-pathspec-file.sh
+++ b/t/t7107-reset-pathspec-file.sh
@@ -2,6 +2,7 @@
 
 test_description='reset --pathspec-from-file'
 
+TEST_PASSES_SANITIZE_LEAK=true
 . ./test-lib.sh
 
 test_tick
diff --git a/t/t7301-clean-interactive.sh b/t/t7301-clean-interactive.sh
index a07e8b86de2..d82a3210a1d 100755
--- a/t/t7301-clean-interactive.sh
+++ b/t/t7301-clean-interactive.sh
@@ -2,6 +2,7 @@
 
 test_description='git clean -i basic tests'
 
+TEST_PASSES_SANITIZE_LEAK=true
 . ./test-lib.sh
 . "$TEST_DIRECTORY"/lib-terminal.sh
 
-- 
2.39.0.1195.gabc92c078c4


^ permalink raw reply related	[flat|nested] 193+ messages in thread

* [PATCH v3 06/19] name-rev: don't xstrdup() an already dup'd string
  2023-01-10  5:43   ` [PATCH v3 00/19] leak fixes: various simple leak fixes Ævar Arnfjörð Bjarmason
                       ` (4 preceding siblings ...)
  2023-01-10  5:43     ` [PATCH v3 05/19] various: add missing clear_pathspec(), fix leaks Ævar Arnfjörð Bjarmason
@ 2023-01-10  5:43     ` Ævar Arnfjörð Bjarmason
  2023-01-10  5:43     ` [PATCH v3 07/19] repack: fix leaks on error with "goto cleanup" Ævar Arnfjörð Bjarmason
                       ` (13 subsequent siblings)
  19 siblings, 0 replies; 193+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2023-01-10  5:43 UTC (permalink / raw)
  To: git
  Cc: René Scharfe, Junio C Hamano, Eric Sunshine,
	Ævar Arnfjörð Bjarmason

When "add_to_tip_table()" is called with a non-zero
"shorten_unambiguous" we always return an xstrdup()'d string, which
we'd then xstrdup() again, leaking memory. See [1] and [2] for how
this leak came about.

We could xstrdup() only if "shorten_unambiguous" wasn't true, but
let's instead inline this code, so that information on whether we need
to xstrdup() is contained within add_to_tip_table().

1. 98c5c4ad015 (name-rev: allow to specify a subpath for --refs
   option, 2013-06-18)
2. b23e0b9353e (name-rev: allow converting the exact object name at
   the tip of a ref, 2013-07-07)

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 builtin/name-rev.c | 23 ++++++++++-------------
 1 file changed, 10 insertions(+), 13 deletions(-)

diff --git a/builtin/name-rev.c b/builtin/name-rev.c
index 15535e914a6..49fae523694 100644
--- a/builtin/name-rev.c
+++ b/builtin/name-rev.c
@@ -273,17 +273,6 @@ static int subpath_matches(const char *path, const char *filter)
 	return -1;
 }
 
-static const char *name_ref_abbrev(const char *refname, int shorten_unambiguous)
-{
-	if (shorten_unambiguous)
-		refname = shorten_unambiguous_ref(refname, 0);
-	else if (skip_prefix(refname, "refs/heads/", &refname))
-		; /* refname already advanced */
-	else
-		skip_prefix(refname, "refs/", &refname);
-	return refname;
-}
-
 struct name_ref_data {
 	int tags_only;
 	int name_only;
@@ -309,11 +298,19 @@ static void add_to_tip_table(const struct object_id *oid, const char *refname,
 			     int shorten_unambiguous, struct commit *commit,
 			     timestamp_t taggerdate, int from_tag, int deref)
 {
-	refname = name_ref_abbrev(refname, shorten_unambiguous);
+	char *short_refname = NULL;
+
+	if (shorten_unambiguous)
+		short_refname = shorten_unambiguous_ref(refname, 0);
+	else if (skip_prefix(refname, "refs/heads/", &refname))
+		; /* refname already advanced */
+	else
+		skip_prefix(refname, "refs/", &refname);
 
 	ALLOC_GROW(tip_table.table, tip_table.nr + 1, tip_table.alloc);
 	oidcpy(&tip_table.table[tip_table.nr].oid, oid);
-	tip_table.table[tip_table.nr].refname = xstrdup(refname);
+	tip_table.table[tip_table.nr].refname = short_refname ?
+		short_refname : xstrdup(refname);
 	tip_table.table[tip_table.nr].commit = commit;
 	tip_table.table[tip_table.nr].taggerdate = taggerdate;
 	tip_table.table[tip_table.nr].from_tag = from_tag;
-- 
2.39.0.1195.gabc92c078c4


^ permalink raw reply related	[flat|nested] 193+ messages in thread

* [PATCH v3 07/19] repack: fix leaks on error with "goto cleanup"
  2023-01-10  5:43   ` [PATCH v3 00/19] leak fixes: various simple leak fixes Ævar Arnfjörð Bjarmason
                       ` (5 preceding siblings ...)
  2023-01-10  5:43     ` [PATCH v3 06/19] name-rev: don't xstrdup() an already dup'd string Ævar Arnfjörð Bjarmason
@ 2023-01-10  5:43     ` Ævar Arnfjörð Bjarmason
  2023-01-10  5:43     ` [PATCH v3 08/19] worktree: fix a trivial leak in prune_worktrees() Ævar Arnfjörð Bjarmason
                       ` (12 subsequent siblings)
  19 siblings, 0 replies; 193+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2023-01-10  5:43 UTC (permalink / raw)
  To: git
  Cc: René Scharfe, Junio C Hamano, Eric Sunshine,
	Ævar Arnfjörð Bjarmason

Change cmd_repack() to "goto cleanup" rather than "return ret" on
error, when we returned we'd potentially skip cleaning up the
string_lists and other data we'd allocated in this function.

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 builtin/repack.c                    | 13 +++++++------
 t/t6011-rev-list-with-bad-commit.sh |  1 +
 2 files changed, 8 insertions(+), 6 deletions(-)

diff --git a/builtin/repack.c b/builtin/repack.c
index c1402ad038f..f6493795318 100644
--- a/builtin/repack.c
+++ b/builtin/repack.c
@@ -948,7 +948,7 @@ int cmd_repack(int argc, const char **argv, const char *prefix)
 
 	ret = start_command(&cmd);
 	if (ret)
-		return ret;
+		goto cleanup;
 
 	if (geometry) {
 		FILE *in = xfdopen(cmd.in, "w");
@@ -977,7 +977,7 @@ int cmd_repack(int argc, const char **argv, const char *prefix)
 	fclose(out);
 	ret = finish_command(&cmd);
 	if (ret)
-		return ret;
+		goto cleanup;
 
 	if (!names.nr && !po_args.quiet)
 		printf_ln(_("Nothing new to pack."));
@@ -1007,7 +1007,7 @@ int cmd_repack(int argc, const char **argv, const char *prefix)
 				       &existing_nonkept_packs,
 				       &existing_kept_packs);
 		if (ret)
-			return ret;
+			goto cleanup;
 
 		if (delete_redundant && expire_to) {
 			/*
@@ -1039,7 +1039,7 @@ int cmd_repack(int argc, const char **argv, const char *prefix)
 					       &existing_nonkept_packs,
 					       &existing_kept_packs);
 			if (ret)
-				return ret;
+				goto cleanup;
 		}
 	}
 
@@ -1115,7 +1115,7 @@ int cmd_repack(int argc, const char **argv, const char *prefix)
 		string_list_clear(&include, 0);
 
 		if (ret)
-			return ret;
+			goto cleanup;
 	}
 
 	reprepare_packed_git(the_repository);
@@ -1172,10 +1172,11 @@ int cmd_repack(int argc, const char **argv, const char *prefix)
 		write_midx_file(get_object_directory(), NULL, NULL, flags);
 	}
 
+cleanup:
 	string_list_clear(&names, 1);
 	string_list_clear(&existing_nonkept_packs, 0);
 	string_list_clear(&existing_kept_packs, 0);
 	clear_pack_geometry(geometry);
 
-	return 0;
+	return ret;
 }
diff --git a/t/t6011-rev-list-with-bad-commit.sh b/t/t6011-rev-list-with-bad-commit.sh
index bad02cf5b83..b2e422cf0f7 100755
--- a/t/t6011-rev-list-with-bad-commit.sh
+++ b/t/t6011-rev-list-with-bad-commit.sh
@@ -2,6 +2,7 @@
 
 test_description='git rev-list should notice bad commits'
 
+TEST_PASSES_SANITIZE_LEAK=true
 . ./test-lib.sh
 
 # Note:
-- 
2.39.0.1195.gabc92c078c4


^ permalink raw reply related	[flat|nested] 193+ messages in thread

* [PATCH v3 08/19] worktree: fix a trivial leak in prune_worktrees()
  2023-01-10  5:43   ` [PATCH v3 00/19] leak fixes: various simple leak fixes Ævar Arnfjörð Bjarmason
                       ` (6 preceding siblings ...)
  2023-01-10  5:43     ` [PATCH v3 07/19] repack: fix leaks on error with "goto cleanup" Ævar Arnfjörð Bjarmason
@ 2023-01-10  5:43     ` Ævar Arnfjörð Bjarmason
  2023-01-10  5:43     ` [PATCH v3 09/19] http-backend.c: fix "dir" and "cmd_arg" leaks in cmd_main() Ævar Arnfjörð Bjarmason
                       ` (11 subsequent siblings)
  19 siblings, 0 replies; 193+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2023-01-10  5:43 UTC (permalink / raw)
  To: git
  Cc: René Scharfe, Junio C Hamano, Eric Sunshine,
	Ævar Arnfjörð Bjarmason

We were leaking both the "struct strbuf" in prune_worktrees(), as well
as the "path" we got from should_prune_worktree(). Since these were
the only two uses of the "struct string_list" let's change it to a
"DUP" and push these to it with "string_list_append_nodup()".

For the string_list_append_nodup() we could also string_list_append()
the main_path.buf, and then strbuf_release(&main_path) right away. But
doing it this way avoids an allocation, as we already have the "struct
strbuf" prepared for appending to "kept".

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 builtin/worktree.c         | 6 +++---
 t/t2401-worktree-prune.sh  | 1 +
 t/t2406-worktree-repair.sh | 1 +
 3 files changed, 5 insertions(+), 3 deletions(-)

diff --git a/builtin/worktree.c b/builtin/worktree.c
index 591d659faea..865ce9be22b 100644
--- a/builtin/worktree.c
+++ b/builtin/worktree.c
@@ -173,7 +173,7 @@ static void prune_worktrees(void)
 {
 	struct strbuf reason = STRBUF_INIT;
 	struct strbuf main_path = STRBUF_INIT;
-	struct string_list kept = STRING_LIST_INIT_NODUP;
+	struct string_list kept = STRING_LIST_INIT_DUP;
 	DIR *dir = opendir(git_path("worktrees"));
 	struct dirent *d;
 	if (!dir)
@@ -184,14 +184,14 @@ static void prune_worktrees(void)
 		if (should_prune_worktree(d->d_name, &reason, &path, expire))
 			prune_worktree(d->d_name, reason.buf);
 		else if (path)
-			string_list_append(&kept, path)->util = xstrdup(d->d_name);
+			string_list_append_nodup(&kept, path)->util = xstrdup(d->d_name);
 	}
 	closedir(dir);
 
 	strbuf_add_absolute_path(&main_path, get_git_common_dir());
 	/* massage main worktree absolute path to match 'gitdir' content */
 	strbuf_strip_suffix(&main_path, "/.");
-	string_list_append(&kept, strbuf_detach(&main_path, NULL));
+	string_list_append_nodup(&kept, strbuf_detach(&main_path, NULL));
 	prune_dups(&kept);
 	string_list_clear(&kept, 1);
 
diff --git a/t/t2401-worktree-prune.sh b/t/t2401-worktree-prune.sh
index 3d28c7f06b2..568a47ec426 100755
--- a/t/t2401-worktree-prune.sh
+++ b/t/t2401-worktree-prune.sh
@@ -5,6 +5,7 @@ test_description='prune $GIT_DIR/worktrees'
 GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
 export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
 
+TEST_PASSES_SANITIZE_LEAK=true
 . ./test-lib.sh
 
 test_expect_success initialize '
diff --git a/t/t2406-worktree-repair.sh b/t/t2406-worktree-repair.sh
index 5c44453e1c1..8970780efcc 100755
--- a/t/t2406-worktree-repair.sh
+++ b/t/t2406-worktree-repair.sh
@@ -2,6 +2,7 @@
 
 test_description='test git worktree repair'
 
+TEST_PASSES_SANITIZE_LEAK=true
 . ./test-lib.sh
 
 test_expect_success setup '
-- 
2.39.0.1195.gabc92c078c4


^ permalink raw reply related	[flat|nested] 193+ messages in thread

* [PATCH v3 09/19] http-backend.c: fix "dir" and "cmd_arg" leaks in cmd_main()
  2023-01-10  5:43   ` [PATCH v3 00/19] leak fixes: various simple leak fixes Ævar Arnfjörð Bjarmason
                       ` (7 preceding siblings ...)
  2023-01-10  5:43     ` [PATCH v3 08/19] worktree: fix a trivial leak in prune_worktrees() Ævar Arnfjörð Bjarmason
@ 2023-01-10  5:43     ` Ævar Arnfjörð Bjarmason
  2023-01-10  5:43     ` [PATCH v3 10/19] http-backend.c: fix cmd_main() memory leak, refactor reg{exec,free}() Ævar Arnfjörð Bjarmason
                       ` (10 subsequent siblings)
  19 siblings, 0 replies; 193+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2023-01-10  5:43 UTC (permalink / raw)
  To: git
  Cc: René Scharfe, Junio C Hamano, Eric Sunshine,
	Ævar Arnfjörð Bjarmason

Free the "dir" variable after we're done with it. Before
917adc03608 (http-backend: add GIT_PROJECT_ROOT environment var,
2009-10-30) there was no leak here, as we'd get it via getenv(), but
since 917adc03608 we've xstrdup()'d it (or the equivalent), so we need
to free() it.

We also need to free the "cmd_arg" variable, which has been leaked
ever since it was added in 2f4038ab337 (Git-aware CGI to provide dumb
HTTP transport, 2009-10-30).

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 http-backend.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/http-backend.c b/http-backend.c
index 6eb3b2fe51c..67819d931ce 100644
--- a/http-backend.c
+++ b/http-backend.c
@@ -786,6 +786,7 @@ int cmd_main(int argc, const char **argv)
 	if (!getenv("GIT_HTTP_EXPORT_ALL") &&
 	    access("git-daemon-export-ok", F_OK) )
 		not_found(&hdr, "Repository not exported: '%s'", dir);
+	free(dir);
 
 	http_config();
 	max_request_buffer = git_env_ulong("GIT_HTTP_MAX_REQUEST_BUFFER",
@@ -795,5 +796,6 @@ int cmd_main(int argc, const char **argv)
 		setenv(GIT_PROTOCOL_ENVIRONMENT, proto_header, 0);
 
 	cmd->imp(&hdr, cmd_arg);
+	free(cmd_arg);
 	return 0;
 }
-- 
2.39.0.1195.gabc92c078c4


^ permalink raw reply related	[flat|nested] 193+ messages in thread

* [PATCH v3 10/19] http-backend.c: fix cmd_main() memory leak, refactor reg{exec,free}()
  2023-01-10  5:43   ` [PATCH v3 00/19] leak fixes: various simple leak fixes Ævar Arnfjörð Bjarmason
                       ` (8 preceding siblings ...)
  2023-01-10  5:43     ` [PATCH v3 09/19] http-backend.c: fix "dir" and "cmd_arg" leaks in cmd_main() Ævar Arnfjörð Bjarmason
@ 2023-01-10  5:43     ` Ævar Arnfjörð Bjarmason
  2023-01-10  5:43     ` [PATCH v3 11/19] commit-graph: fix a parse_options_concat() leak Ævar Arnfjörð Bjarmason
                       ` (9 subsequent siblings)
  19 siblings, 0 replies; 193+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2023-01-10  5:43 UTC (permalink / raw)
  To: git
  Cc: René Scharfe, Junio C Hamano, Eric Sunshine,
	Ævar Arnfjörð Bjarmason

Fix a memory leak that's been with us ever since
2f4038ab337 (Git-aware CGI to provide dumb HTTP transport,
2009-10-30). In this case we're not calling regerror() after a failed
regexec(), and don't otherwise use "re" afterwards.

We can therefore simplify this code by calling regfree() right after
the regexec(). An alternative fix would be to add a regfree() to both
the "return" and "break" path in this for-loop.

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 http-backend.c | 7 +++++--
 1 file changed, 5 insertions(+), 2 deletions(-)

diff --git a/http-backend.c b/http-backend.c
index 67819d931ce..8ab58e55f85 100644
--- a/http-backend.c
+++ b/http-backend.c
@@ -759,10 +759,14 @@ int cmd_main(int argc, const char **argv)
 		struct service_cmd *c = &services[i];
 		regex_t re;
 		regmatch_t out[1];
+		int ret;
 
 		if (regcomp(&re, c->pattern, REG_EXTENDED))
 			die("Bogus regex in service table: %s", c->pattern);
-		if (!regexec(&re, dir, 1, out, 0)) {
+		ret = regexec(&re, dir, 1, out, 0);
+		regfree(&re);
+
+		if (!ret) {
 			size_t n;
 
 			if (strcmp(method, c->method))
@@ -774,7 +778,6 @@ int cmd_main(int argc, const char **argv)
 			dir[out[0].rm_so] = 0;
 			break;
 		}
-		regfree(&re);
 	}
 
 	if (!cmd)
-- 
2.39.0.1195.gabc92c078c4


^ permalink raw reply related	[flat|nested] 193+ messages in thread

* [PATCH v3 11/19] commit-graph: fix a parse_options_concat() leak
  2023-01-10  5:43   ` [PATCH v3 00/19] leak fixes: various simple leak fixes Ævar Arnfjörð Bjarmason
                       ` (9 preceding siblings ...)
  2023-01-10  5:43     ` [PATCH v3 10/19] http-backend.c: fix cmd_main() memory leak, refactor reg{exec,free}() Ævar Arnfjörð Bjarmason
@ 2023-01-10  5:43     ` Ævar Arnfjörð Bjarmason
  2023-01-10  5:43     ` [PATCH v3 12/19] show-branch: free() allocated "head" before return Ævar Arnfjörð Bjarmason
                       ` (8 subsequent siblings)
  19 siblings, 0 replies; 193+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2023-01-10  5:43 UTC (permalink / raw)
  To: git
  Cc: René Scharfe, Junio C Hamano, Eric Sunshine,
	Ævar Arnfjörð Bjarmason

When the parse_options_concat() was added to this file in
84e4484f128 (commit-graph: use parse_options_concat(), 2021-08-23) we
wouldn't free() it if we returned early in these cases.

Since "result" is 0 by default we can "goto cleanup" in both cases,
and only need to set "result" if write_commit_graph_reachable() fails.

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 builtin/commit-graph.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/builtin/commit-graph.c b/builtin/commit-graph.c
index 0102ac8540e..93704f95a9d 100644
--- a/builtin/commit-graph.c
+++ b/builtin/commit-graph.c
@@ -269,8 +269,8 @@ static int graph_write(int argc, const char **argv, const char *prefix)
 
 	if (opts.reachable) {
 		if (write_commit_graph_reachable(odb, flags, &write_opts))
-			return 1;
-		return 0;
+			result = 1;
+		goto cleanup;
 	}
 
 	if (opts.stdin_packs) {
-- 
2.39.0.1195.gabc92c078c4


^ permalink raw reply related	[flat|nested] 193+ messages in thread

* [PATCH v3 12/19] show-branch: free() allocated "head" before return
  2023-01-10  5:43   ` [PATCH v3 00/19] leak fixes: various simple leak fixes Ævar Arnfjörð Bjarmason
                       ` (10 preceding siblings ...)
  2023-01-10  5:43     ` [PATCH v3 11/19] commit-graph: fix a parse_options_concat() leak Ævar Arnfjörð Bjarmason
@ 2023-01-10  5:43     ` Ævar Arnfjörð Bjarmason
  2023-01-10  5:43     ` [PATCH v3 13/19] builtin/merge.c: always free "struct strbuf msg" Ævar Arnfjörð Bjarmason
                       ` (7 subsequent siblings)
  19 siblings, 0 replies; 193+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2023-01-10  5:43 UTC (permalink / raw)
  To: git
  Cc: René Scharfe, Junio C Hamano, Eric Sunshine,
	Ævar Arnfjörð Bjarmason

Stop leaking the "head" variable, which we've been leaking since it
was originally added in [1], and in its current form since [2]

1. ed378ec7e85 (Make ref resolution saner, 2006-09-11)
2. d9e557a320b (show-branch: store resolved head in heap buffer,
   2017-02-14).

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 builtin/show-branch.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/builtin/show-branch.c b/builtin/show-branch.c
index c013abaf942..358ac3e519a 100644
--- a/builtin/show-branch.c
+++ b/builtin/show-branch.c
@@ -956,5 +956,6 @@ int cmd_show_branch(int ac, const char **av, const char *prefix)
 		if (shown_merge_point && --extra < 0)
 			break;
 	}
+	free(head);
 	return 0;
 }
-- 
2.39.0.1195.gabc92c078c4


^ permalink raw reply related	[flat|nested] 193+ messages in thread

* [PATCH v3 13/19] builtin/merge.c: always free "struct strbuf msg"
  2023-01-10  5:43   ` [PATCH v3 00/19] leak fixes: various simple leak fixes Ævar Arnfjörð Bjarmason
                       ` (11 preceding siblings ...)
  2023-01-10  5:43     ` [PATCH v3 12/19] show-branch: free() allocated "head" before return Ævar Arnfjörð Bjarmason
@ 2023-01-10  5:43     ` Ævar Arnfjörð Bjarmason
  2023-01-10 18:52       ` René Scharfe
  2023-01-10  5:43     ` [PATCH v3 14/19] builtin/merge.c: free "&buf" on "Your local changes..." error Ævar Arnfjörð Bjarmason
                       ` (6 subsequent siblings)
  19 siblings, 1 reply; 193+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2023-01-10  5:43 UTC (permalink / raw)
  To: git
  Cc: René Scharfe, Junio C Hamano, Eric Sunshine,
	Ævar Arnfjörð Bjarmason

Follow-up 465028e0e25 (merge: add missing strbuf_release(),
2021-10-07) and address the "msg" memory leak in this block. We could
free "&msg" before the "goto done" here, but even better is to avoid
allocating it in the first place.

By repeating the "Fast-forward" string here we can avoid using a
"struct strbuf" altogether.

Suggested-by: René Scharfe <l.s.r@web.de>
Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 builtin/merge.c                | 11 ++++-------
 t/t6439-merge-co-error-msgs.sh |  1 +
 2 files changed, 5 insertions(+), 7 deletions(-)

diff --git a/builtin/merge.c b/builtin/merge.c
index 0f093f2a4f2..91dd5435c59 100644
--- a/builtin/merge.c
+++ b/builtin/merge.c
@@ -1560,7 +1560,9 @@ int cmd_merge(int argc, const char **argv, const char *prefix)
 			!common->next &&
 			oideq(&common->item->object.oid, &head_commit->object.oid)) {
 		/* Again the most common case of merging one remote. */
-		struct strbuf msg = STRBUF_INIT;
+		const char *msg = have_message ?
+			"Fast-forward (no commit created; -m option ignored)" :
+			"Fast-forward";
 		struct commit *commit;
 
 		if (verbosity >= 0) {
@@ -1570,10 +1572,6 @@ int cmd_merge(int argc, const char **argv, const char *prefix)
 			       find_unique_abbrev(&remoteheads->item->object.oid,
 						  DEFAULT_ABBREV));
 		}
-		strbuf_addstr(&msg, "Fast-forward");
-		if (have_message)
-			strbuf_addstr(&msg,
-				" (no commit created; -m option ignored)");
 		commit = remoteheads->item;
 		if (!commit) {
 			ret = 1;
@@ -1592,9 +1590,8 @@ int cmd_merge(int argc, const char **argv, const char *prefix)
 			goto done;
 		}
 
-		finish(head_commit, remoteheads, &commit->object.oid, msg.buf);
+		finish(head_commit, remoteheads, &commit->object.oid, msg);
 		remove_merge_branch_state(the_repository);
-		strbuf_release(&msg);
 		goto done;
 	} else if (!remoteheads->next && common->next)
 		;
diff --git a/t/t6439-merge-co-error-msgs.sh b/t/t6439-merge-co-error-msgs.sh
index 52cf0c87690..0cbec57cdab 100755
--- a/t/t6439-merge-co-error-msgs.sh
+++ b/t/t6439-merge-co-error-msgs.sh
@@ -5,6 +5,7 @@ test_description='unpack-trees error messages'
 GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
 export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
 
+TEST_PASSES_SANITIZE_LEAK=true
 . ./test-lib.sh
 
 
-- 
2.39.0.1195.gabc92c078c4


^ permalink raw reply related	[flat|nested] 193+ messages in thread

* [PATCH v3 14/19] builtin/merge.c: free "&buf" on "Your local changes..." error
  2023-01-10  5:43   ` [PATCH v3 00/19] leak fixes: various simple leak fixes Ævar Arnfjörð Bjarmason
                       ` (12 preceding siblings ...)
  2023-01-10  5:43     ` [PATCH v3 13/19] builtin/merge.c: always free "struct strbuf msg" Ævar Arnfjörð Bjarmason
@ 2023-01-10  5:43     ` Ævar Arnfjörð Bjarmason
  2023-01-10  5:43     ` [PATCH v3 15/19] object-file.c: release the "tag" in check_tag() Ævar Arnfjörð Bjarmason
                       ` (5 subsequent siblings)
  19 siblings, 0 replies; 193+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2023-01-10  5:43 UTC (permalink / raw)
  To: git
  Cc: René Scharfe, Junio C Hamano, Eric Sunshine,
	Ævar Arnfjörð Bjarmason

Plug a memory leak introduced in [1], since that change didn't follow
the "goto done" pattern introduced in [2] we'd leak the "&buf" memory.

1. e4cdfe84a0d (merge: abort if index does not match HEAD for trivial
   merges, 2022-07-23)
2. d5a35c114ab (Copy resolve_ref() return value for longer use,
   2011-11-13)

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 builtin/merge.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/builtin/merge.c b/builtin/merge.c
index 91dd5435c59..2b13124c497 100644
--- a/builtin/merge.c
+++ b/builtin/merge.c
@@ -1618,7 +1618,8 @@ int cmd_merge(int argc, const char **argv, const char *prefix)
 				error(_("Your local changes to the following files would be overwritten by merge:\n  %s"),
 				      sb.buf);
 				strbuf_release(&sb);
-				return 2;
+				ret = 2;
+				goto done;
 			}
 
 			/* See if it is really trivial. */
-- 
2.39.0.1195.gabc92c078c4


^ permalink raw reply related	[flat|nested] 193+ messages in thread

* [PATCH v3 15/19] object-file.c: release the "tag" in check_tag()
  2023-01-10  5:43   ` [PATCH v3 00/19] leak fixes: various simple leak fixes Ævar Arnfjörð Bjarmason
                       ` (13 preceding siblings ...)
  2023-01-10  5:43     ` [PATCH v3 14/19] builtin/merge.c: free "&buf" on "Your local changes..." error Ævar Arnfjörð Bjarmason
@ 2023-01-10  5:43     ` Ævar Arnfjörð Bjarmason
  2023-01-10  5:43     ` [PATCH v3 16/19] grep.c: refactor free_grep_patterns() Ævar Arnfjörð Bjarmason
                       ` (4 subsequent siblings)
  19 siblings, 0 replies; 193+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2023-01-10  5:43 UTC (permalink / raw)
  To: git
  Cc: René Scharfe, Junio C Hamano, Eric Sunshine,
	Ævar Arnfjörð Bjarmason

Fix a memory leak that's been with us ever since c879daa2372 (Make
hash-object more robust against malformed objects, 2011-02-05). With
"HASH_FORMAT_CHECK" (used by "hash-object" and "replace") we'll parse
tags into a throwaway variable on the stack, but weren't freeing the
"item->tag" we might malloc() when doing so.

The clearing that release_tag_memory() does for us is redundant here,
but let's use it as-is anyway. It only has one other existing caller,
which does need the tag to be cleared.

Mark the tests that now pass in their entirety as passing under
"SANITIZE=leak", which means we'll test them as part of the
"linux-leaks" CI job.

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 object-file.c         | 1 +
 t/t3800-mktag.sh      | 1 +
 t/t5302-pack-index.sh | 2 ++
 3 files changed, 4 insertions(+)

diff --git a/object-file.c b/object-file.c
index 80a0cd3b351..b554266aff4 100644
--- a/object-file.c
+++ b/object-file.c
@@ -2324,6 +2324,7 @@ static void check_tag(const void *buf, size_t size)
 	memset(&t, 0, sizeof(t));
 	if (parse_tag_buffer(the_repository, &t, buf, size))
 		die(_("corrupt tag"));
+	release_tag_memory(&t);
 }
 
 static int index_mem(struct index_state *istate,
diff --git a/t/t3800-mktag.sh b/t/t3800-mktag.sh
index e3cf0ffbe59..d3e428ff46e 100755
--- a/t/t3800-mktag.sh
+++ b/t/t3800-mktag.sh
@@ -4,6 +4,7 @@
 
 test_description='git mktag: tag object verify test'
 
+TEST_PASSES_SANITIZE_LEAK=true
 . ./test-lib.sh
 
 ###########################################################
diff --git a/t/t5302-pack-index.sh b/t/t5302-pack-index.sh
index b0095ab41d3..54b11f81c63 100755
--- a/t/t5302-pack-index.sh
+++ b/t/t5302-pack-index.sh
@@ -4,6 +4,8 @@
 #
 
 test_description='pack index with 64-bit offsets and object CRC'
+
+TEST_PASSES_SANITIZE_LEAK=true
 . ./test-lib.sh
 
 test_expect_success 'setup' '
-- 
2.39.0.1195.gabc92c078c4


^ permalink raw reply related	[flat|nested] 193+ messages in thread

* [PATCH v3 16/19] grep.c: refactor free_grep_patterns()
  2023-01-10  5:43   ` [PATCH v3 00/19] leak fixes: various simple leak fixes Ævar Arnfjörð Bjarmason
                       ` (14 preceding siblings ...)
  2023-01-10  5:43     ` [PATCH v3 15/19] object-file.c: release the "tag" in check_tag() Ævar Arnfjörð Bjarmason
@ 2023-01-10  5:43     ` Ævar Arnfjörð Bjarmason
  2023-01-10  5:43     ` [PATCH v3 17/19] grep API: plug memory leaks by freeing "header_list" Ævar Arnfjörð Bjarmason
                       ` (3 subsequent siblings)
  19 siblings, 0 replies; 193+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2023-01-10  5:43 UTC (permalink / raw)
  To: git
  Cc: René Scharfe, Junio C Hamano, Eric Sunshine,
	Ævar Arnfjörð Bjarmason

Refactor the free_grep_patterns() function to split out the freeing of
the "struct grep_pat" it contains, right now we're only freeing the
"pattern_list", but we should be freeing another member of the same
type, which we'll do in the subsequent commit.

Let's also replace the "return" if we don't have an
"opt->pattern_expression" with a conditional call of
free_pattern_expr().

Before db84376f981 (grep.c: remove "extended" in favor of
"pattern_expression", fix segfault, 2022-10-11) the pattern here was:

	if (!x)
		return;
	free(y);

But after the cleanup in db84376f981 (which was a narrow segfault fix,
and thus avoided refactoring this) we ended up with:

	if (!x)
		return;
	free(x);

Let's instead do:

	if (x)
		free(x);

This doesn't matter for the subsequent change, but as we're
refactoring this function let's make it easier to reason about, and to
extend in the future, i.e. if we start to free free() members that
come after "pattern_expression" in the "struct grep_opt".

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 grep.c | 14 +++++++++-----
 1 file changed, 9 insertions(+), 5 deletions(-)

diff --git a/grep.c b/grep.c
index 06eed694936..a4450df4559 100644
--- a/grep.c
+++ b/grep.c
@@ -769,11 +769,11 @@ static void free_pattern_expr(struct grep_expr *x)
 	free(x);
 }
 
-void free_grep_patterns(struct grep_opt *opt)
+static void free_grep_pat(struct grep_pat *pattern)
 {
 	struct grep_pat *p, *n;
 
-	for (p = opt->pattern_list; p; p = n) {
+	for (p = pattern; p; p = n) {
 		n = p->next;
 		switch (p->token) {
 		case GREP_PATTERN: /* atom */
@@ -790,10 +790,14 @@ void free_grep_patterns(struct grep_opt *opt)
 		}
 		free(p);
 	}
+}
 
-	if (!opt->pattern_expression)
-		return;
-	free_pattern_expr(opt->pattern_expression);
+void free_grep_patterns(struct grep_opt *opt)
+{
+	free_grep_pat(opt->pattern_list);
+
+	if (opt->pattern_expression)
+		free_pattern_expr(opt->pattern_expression);
 }
 
 static const char *end_of_line(const char *cp, unsigned long *left)
-- 
2.39.0.1195.gabc92c078c4


^ permalink raw reply related	[flat|nested] 193+ messages in thread

* [PATCH v3 17/19] grep API: plug memory leaks by freeing "header_list"
  2023-01-10  5:43   ` [PATCH v3 00/19] leak fixes: various simple leak fixes Ævar Arnfjörð Bjarmason
                       ` (15 preceding siblings ...)
  2023-01-10  5:43     ` [PATCH v3 16/19] grep.c: refactor free_grep_patterns() Ævar Arnfjörð Bjarmason
@ 2023-01-10  5:43     ` Ævar Arnfjörð Bjarmason
  2023-01-10  5:43     ` [PATCH v3 18/19] receive-pack: free() the "ref_name" in "struct command" Ævar Arnfjörð Bjarmason
                       ` (2 subsequent siblings)
  19 siblings, 0 replies; 193+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2023-01-10  5:43 UTC (permalink / raw)
  To: git
  Cc: René Scharfe, Junio C Hamano, Eric Sunshine,
	Ævar Arnfjörð Bjarmason

When the "header_list" struct member was added in [1] it wasn't made
to free the list using loop added for the adjacent "pattern_list"
member, see [2] for when we started freeing it.

This makes e.g. this command leak-free when run on git.git:

	./git -P log -1 --color=always --author=A origin/master

1. 80235ba79ef ("log --author=me --grep=it" should find intersection,
   not union, 2010-01-17)
2. b48fb5b6a95 (grep: free expressions and patterns when done.,
   2006-09-27)

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 grep.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/grep.c b/grep.c
index a4450df4559..c908535e0d8 100644
--- a/grep.c
+++ b/grep.c
@@ -795,6 +795,7 @@ static void free_grep_pat(struct grep_pat *pattern)
 void free_grep_patterns(struct grep_opt *opt)
 {
 	free_grep_pat(opt->pattern_list);
+	free_grep_pat(opt->header_list);
 
 	if (opt->pattern_expression)
 		free_pattern_expr(opt->pattern_expression);
-- 
2.39.0.1195.gabc92c078c4


^ permalink raw reply related	[flat|nested] 193+ messages in thread

* [PATCH v3 18/19] receive-pack: free() the "ref_name" in "struct command"
  2023-01-10  5:43   ` [PATCH v3 00/19] leak fixes: various simple leak fixes Ævar Arnfjörð Bjarmason
                       ` (16 preceding siblings ...)
  2023-01-10  5:43     ` [PATCH v3 17/19] grep API: plug memory leaks by freeing "header_list" Ævar Arnfjörð Bjarmason
@ 2023-01-10  5:43     ` Ævar Arnfjörð Bjarmason
  2023-01-10  5:43     ` [PATCH v3 19/19] push: free_refs() the "local_refs" in set_refspecs() Ævar Arnfjörð Bjarmason
  2023-01-17 17:11     ` [PATCH v4 00/19] leak fixes: various simple leak fixes Ævar Arnfjörð Bjarmason
  19 siblings, 0 replies; 193+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2023-01-10  5:43 UTC (permalink / raw)
  To: git
  Cc: René Scharfe, Junio C Hamano, Eric Sunshine,
	Ævar Arnfjörð Bjarmason

Fix a memory leak that's been with us since this code was introduced
in 575f497456e (Add first cut at "git-receive-pack", 2005-06-29), see
eb1af2df0b1 (git-receive-pack: start parsing ref update commands,
2005-06-29) for the later change that refactored the code to add the
"ref_name" member.

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 builtin/receive-pack.c                | 10 ++++++++++
 t/t5405-send-pack-rewind.sh           |  1 +
 t/t5406-remote-rejects.sh             |  1 +
 t/t5507-remote-environment.sh         |  2 ++
 t/t5522-pull-symlink.sh               |  1 +
 t/t5527-fetch-odd-refs.sh             |  1 +
 t/t5705-session-id-in-capabilities.sh |  1 +
 7 files changed, 17 insertions(+)

diff --git a/builtin/receive-pack.c b/builtin/receive-pack.c
index a90af303630..451bad776c6 100644
--- a/builtin/receive-pack.c
+++ b/builtin/receive-pack.c
@@ -2032,6 +2032,15 @@ static struct command **queue_command(struct command **tail,
 	return &cmd->next;
 }
 
+static void free_commands(struct command *commands)
+{
+	while (commands) {
+		struct command *next = commands->next;
+		free(commands);
+		commands = next;
+	}
+}
+
 static void queue_commands_from_cert(struct command **tail,
 				     struct strbuf *push_cert)
 {
@@ -2569,6 +2578,7 @@ int cmd_receive_pack(int argc, const char **argv, const char *prefix)
 		run_receive_hook(commands, "post-receive", 1,
 				 &push_options);
 		run_update_post_hook(commands);
+		free_commands(commands);
 		string_list_clear(&push_options, 0);
 		if (auto_gc) {
 			struct child_process proc = CHILD_PROCESS_INIT;
diff --git a/t/t5405-send-pack-rewind.sh b/t/t5405-send-pack-rewind.sh
index 11f03239a06..1686ac13aa6 100755
--- a/t/t5405-send-pack-rewind.sh
+++ b/t/t5405-send-pack-rewind.sh
@@ -5,6 +5,7 @@ test_description='forced push to replace commit we do not have'
 GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
 export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
 
+TEST_PASSES_SANITIZE_LEAK=true
 . ./test-lib.sh
 
 test_expect_success setup '
diff --git a/t/t5406-remote-rejects.sh b/t/t5406-remote-rejects.sh
index dcbeb420827..d6a99466338 100755
--- a/t/t5406-remote-rejects.sh
+++ b/t/t5406-remote-rejects.sh
@@ -2,6 +2,7 @@
 
 test_description='remote push rejects are reported by client'
 
+TEST_PASSES_SANITIZE_LEAK=true
 . ./test-lib.sh
 
 test_expect_success 'setup' '
diff --git a/t/t5507-remote-environment.sh b/t/t5507-remote-environment.sh
index e6149295b18..c6a6957c500 100755
--- a/t/t5507-remote-environment.sh
+++ b/t/t5507-remote-environment.sh
@@ -1,6 +1,8 @@
 #!/bin/sh
 
 test_description='check environment showed to remote side of transports'
+
+TEST_PASSES_SANITIZE_LEAK=true
 . ./test-lib.sh
 
 test_expect_success 'set up "remote" push situation' '
diff --git a/t/t5522-pull-symlink.sh b/t/t5522-pull-symlink.sh
index bcff460d0a2..394bc60cb8e 100755
--- a/t/t5522-pull-symlink.sh
+++ b/t/t5522-pull-symlink.sh
@@ -2,6 +2,7 @@
 
 test_description='pulling from symlinked subdir'
 
+TEST_PASSES_SANITIZE_LEAK=true
 . ./test-lib.sh
 
 # The scenario we are building:
diff --git a/t/t5527-fetch-odd-refs.sh b/t/t5527-fetch-odd-refs.sh
index e2770e4541f..98ece27c6a0 100755
--- a/t/t5527-fetch-odd-refs.sh
+++ b/t/t5527-fetch-odd-refs.sh
@@ -4,6 +4,7 @@ test_description='test fetching of oddly-named refs'
 GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
 export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
 
+TEST_PASSES_SANITIZE_LEAK=true
 . ./test-lib.sh
 
 # afterwards we will have:
diff --git a/t/t5705-session-id-in-capabilities.sh b/t/t5705-session-id-in-capabilities.sh
index ed38c76c290..b8a722ec27e 100755
--- a/t/t5705-session-id-in-capabilities.sh
+++ b/t/t5705-session-id-in-capabilities.sh
@@ -2,6 +2,7 @@
 
 test_description='session ID in capabilities'
 
+TEST_PASSES_SANITIZE_LEAK=true
 . ./test-lib.sh
 
 REPO="$(pwd)/repo"
-- 
2.39.0.1195.gabc92c078c4


^ permalink raw reply related	[flat|nested] 193+ messages in thread

* [PATCH v3 19/19] push: free_refs() the "local_refs" in set_refspecs()
  2023-01-10  5:43   ` [PATCH v3 00/19] leak fixes: various simple leak fixes Ævar Arnfjörð Bjarmason
                       ` (17 preceding siblings ...)
  2023-01-10  5:43     ` [PATCH v3 18/19] receive-pack: free() the "ref_name" in "struct command" Ævar Arnfjörð Bjarmason
@ 2023-01-10  5:43     ` Ævar Arnfjörð Bjarmason
  2023-01-17 17:11     ` [PATCH v4 00/19] leak fixes: various simple leak fixes Ævar Arnfjörð Bjarmason
  19 siblings, 0 replies; 193+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2023-01-10  5:43 UTC (permalink / raw)
  To: git
  Cc: René Scharfe, Junio C Hamano, Eric Sunshine,
	Ævar Arnfjörð Bjarmason

Fix a memory leak that's been with us since this code was added in
ca02465b413 (push: use remote.$name.push as a refmap, 2013-12-03).

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 builtin/push.c                          | 1 +
 t/t1416-ref-transaction-hooks.sh        | 1 +
 t/t5504-fetch-receive-strict.sh         | 1 +
 t/t5523-push-upstream.sh                | 1 +
 t/t5529-push-errors.sh                  | 2 ++
 t/t5546-receive-limits.sh               | 2 ++
 t/t5547-push-quarantine.sh              | 2 ++
 t/t5606-clone-options.sh                | 1 +
 t/t5810-proto-disable-local.sh          | 2 ++
 t/t5813-proto-disable-ssh.sh            | 2 ++
 t/t7409-submodule-detached-work-tree.sh | 1 +
 t/t7416-submodule-dash-url.sh           | 2 ++
 t/t7450-bad-git-dotfiles.sh             | 2 ++
 13 files changed, 20 insertions(+)

diff --git a/builtin/push.c b/builtin/push.c
index 60ac8017e52..f48e4c6a856 100644
--- a/builtin/push.c
+++ b/builtin/push.c
@@ -129,6 +129,7 @@ static void set_refspecs(const char **refs, int nr, const char *repo)
 		} else
 			refspec_append(&rs, ref);
 	}
+	free_refs(local_refs);
 }
 
 static int push_url_of_remote(struct remote *remote, const char ***url_p)
diff --git a/t/t1416-ref-transaction-hooks.sh b/t/t1416-ref-transaction-hooks.sh
index 27731722a5b..b32ca798f9f 100755
--- a/t/t1416-ref-transaction-hooks.sh
+++ b/t/t1416-ref-transaction-hooks.sh
@@ -5,6 +5,7 @@ test_description='reference transaction hooks'
 GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
 export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
 
+TEST_PASSES_SANITIZE_LEAK=true
 . ./test-lib.sh
 
 test_expect_success setup '
diff --git a/t/t5504-fetch-receive-strict.sh b/t/t5504-fetch-receive-strict.sh
index ac4099ca893..14e8af1f3b7 100755
--- a/t/t5504-fetch-receive-strict.sh
+++ b/t/t5504-fetch-receive-strict.sh
@@ -4,6 +4,7 @@ test_description='fetch/receive strict mode'
 GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
 export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
 
+TEST_PASSES_SANITIZE_LEAK=true
 . ./test-lib.sh
 
 test_expect_success 'setup and inject "corrupt or missing" object' '
diff --git a/t/t5523-push-upstream.sh b/t/t5523-push-upstream.sh
index fdb42920564..c9acc076353 100755
--- a/t/t5523-push-upstream.sh
+++ b/t/t5523-push-upstream.sh
@@ -4,6 +4,7 @@ test_description='push with --set-upstream'
 GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
 export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
 
+TEST_PASSES_SANITIZE_LEAK=true
 . ./test-lib.sh
 . "$TEST_DIRECTORY"/lib-terminal.sh
 
diff --git a/t/t5529-push-errors.sh b/t/t5529-push-errors.sh
index ce85fd30ad1..0247137cb36 100755
--- a/t/t5529-push-errors.sh
+++ b/t/t5529-push-errors.sh
@@ -1,6 +1,8 @@
 #!/bin/sh
 
 test_description='detect some push errors early (before contacting remote)'
+
+TEST_PASSES_SANITIZE_LEAK=true
 . ./test-lib.sh
 
 test_expect_success 'setup commits' '
diff --git a/t/t5546-receive-limits.sh b/t/t5546-receive-limits.sh
index 0b0e987fdb7..eed3c9d81ab 100755
--- a/t/t5546-receive-limits.sh
+++ b/t/t5546-receive-limits.sh
@@ -1,6 +1,8 @@
 #!/bin/sh
 
 test_description='check receive input limits'
+
+TEST_PASSES_SANITIZE_LEAK=true
 . ./test-lib.sh
 
 # Let's run tests with different unpack limits: 1 and 10000
diff --git a/t/t5547-push-quarantine.sh b/t/t5547-push-quarantine.sh
index 1876fb34e51..9f899b8c7d7 100755
--- a/t/t5547-push-quarantine.sh
+++ b/t/t5547-push-quarantine.sh
@@ -1,6 +1,8 @@
 #!/bin/sh
 
 test_description='check quarantine of objects during push'
+
+TEST_PASSES_SANITIZE_LEAK=true
 . ./test-lib.sh
 
 test_expect_success 'create picky dest repo' '
diff --git a/t/t5606-clone-options.sh b/t/t5606-clone-options.sh
index cf221e92c4d..27f9f776389 100755
--- a/t/t5606-clone-options.sh
+++ b/t/t5606-clone-options.sh
@@ -4,6 +4,7 @@ test_description='basic clone options'
 GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
 export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
 
+TEST_PASSES_SANITIZE_LEAK=true
 . ./test-lib.sh
 
 test_expect_success 'setup' '
diff --git a/t/t5810-proto-disable-local.sh b/t/t5810-proto-disable-local.sh
index c1ef99b85c2..862610256fb 100755
--- a/t/t5810-proto-disable-local.sh
+++ b/t/t5810-proto-disable-local.sh
@@ -1,6 +1,8 @@
 #!/bin/sh
 
 test_description='test disabling of local paths in clone/fetch'
+
+TEST_PASSES_SANITIZE_LEAK=true
 . ./test-lib.sh
 . "$TEST_DIRECTORY/lib-proto-disable.sh"
 
diff --git a/t/t5813-proto-disable-ssh.sh b/t/t5813-proto-disable-ssh.sh
index 3f084ee3065..2e975dc70ec 100755
--- a/t/t5813-proto-disable-ssh.sh
+++ b/t/t5813-proto-disable-ssh.sh
@@ -1,6 +1,8 @@
 #!/bin/sh
 
 test_description='test disabling of git-over-ssh in clone/fetch'
+
+TEST_PASSES_SANITIZE_LEAK=true
 . ./test-lib.sh
 . "$TEST_DIRECTORY/lib-proto-disable.sh"
 
diff --git a/t/t7409-submodule-detached-work-tree.sh b/t/t7409-submodule-detached-work-tree.sh
index 374ed481e9c..574a6fc526e 100755
--- a/t/t7409-submodule-detached-work-tree.sh
+++ b/t/t7409-submodule-detached-work-tree.sh
@@ -13,6 +13,7 @@ TEST_NO_CREATE_REPO=1
 GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
 export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
 
+TEST_PASSES_SANITIZE_LEAK=true
 . ./test-lib.sh
 
 test_expect_success 'setup' '
diff --git a/t/t7416-submodule-dash-url.sh b/t/t7416-submodule-dash-url.sh
index 3ebd9859814..7cf72b9a076 100755
--- a/t/t7416-submodule-dash-url.sh
+++ b/t/t7416-submodule-dash-url.sh
@@ -1,6 +1,8 @@
 #!/bin/sh
 
 test_description='check handling of disallowed .gitmodule urls'
+
+TEST_PASSES_SANITIZE_LEAK=true
 . ./test-lib.sh
 
 test_expect_success 'setup' '
diff --git a/t/t7450-bad-git-dotfiles.sh b/t/t7450-bad-git-dotfiles.sh
index ba1f569bcbb..0d0c3f2c683 100755
--- a/t/t7450-bad-git-dotfiles.sh
+++ b/t/t7450-bad-git-dotfiles.sh
@@ -12,6 +12,8 @@ Such as:
 
   - symlinked .gitmodules, etc
 '
+
+TEST_PASSES_SANITIZE_LEAK=true
 . ./test-lib.sh
 . "$TEST_DIRECTORY"/lib-pack.sh
 
-- 
2.39.0.1195.gabc92c078c4


^ permalink raw reply related	[flat|nested] 193+ messages in thread

* Re: [PATCH v3 13/19] builtin/merge.c: always free "struct strbuf msg"
  2023-01-10  5:43     ` [PATCH v3 13/19] builtin/merge.c: always free "struct strbuf msg" Ævar Arnfjörð Bjarmason
@ 2023-01-10 18:52       ` René Scharfe
  2023-01-13 19:57         ` Junio C Hamano
  0 siblings, 1 reply; 193+ messages in thread
From: René Scharfe @ 2023-01-10 18:52 UTC (permalink / raw)
  To: Ævar Arnfjörð Bjarmason, git; +Cc: Junio C Hamano, Eric Sunshine

Am 10.01.23 um 06:43 schrieb Ævar Arnfjörð Bjarmason:
> Follow-up 465028e0e25 (merge: add missing strbuf_release(),
> 2021-10-07) and address the "msg" memory leak in this block. We could
> free "&msg" before the "goto done" here, but even better is to avoid
> allocating it in the first place.

So contrary to the subject we don't need to free it anymore.

>
> By repeating the "Fast-forward" string here we can avoid using a
> "struct strbuf" altogether.
>
> Suggested-by: René Scharfe <l.s.r@web.de>
> Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
> ---
>  builtin/merge.c                | 11 ++++-------
>  t/t6439-merge-co-error-msgs.sh |  1 +
>  2 files changed, 5 insertions(+), 7 deletions(-)
>
> diff --git a/builtin/merge.c b/builtin/merge.c
> index 0f093f2a4f2..91dd5435c59 100644
> --- a/builtin/merge.c
> +++ b/builtin/merge.c
> @@ -1560,7 +1560,9 @@ int cmd_merge(int argc, const char **argv, const char *prefix)
>  			!common->next &&
>  			oideq(&common->item->object.oid, &head_commit->object.oid)) {
>  		/* Again the most common case of merging one remote. */
> -		struct strbuf msg = STRBUF_INIT;
> +		const char *msg = have_message ?
> +			"Fast-forward (no commit created; -m option ignored)" :
> +			"Fast-forward";
>  		struct commit *commit;
>
>  		if (verbosity >= 0) {
> @@ -1570,10 +1572,6 @@ int cmd_merge(int argc, const char **argv, const char *prefix)
>  			       find_unique_abbrev(&remoteheads->item->object.oid,
>  						  DEFAULT_ABBREV));
>  		}
> -		strbuf_addstr(&msg, "Fast-forward");
> -		if (have_message)
> -			strbuf_addstr(&msg,
> -				" (no commit created; -m option ignored)");
>  		commit = remoteheads->item;
>  		if (!commit) {
>  			ret = 1;
> @@ -1592,9 +1590,8 @@ int cmd_merge(int argc, const char **argv, const char *prefix)
>  			goto done;
>  		}
>
> -		finish(head_commit, remoteheads, &commit->object.oid, msg.buf);
> +		finish(head_commit, remoteheads, &commit->object.oid, msg);
>  		remove_merge_branch_state(the_repository);
> -		strbuf_release(&msg);
>  		goto done;
>  	} else if (!remoteheads->next && common->next)
>  		;
> diff --git a/t/t6439-merge-co-error-msgs.sh b/t/t6439-merge-co-error-msgs.sh
> index 52cf0c87690..0cbec57cdab 100755
> --- a/t/t6439-merge-co-error-msgs.sh
> +++ b/t/t6439-merge-co-error-msgs.sh
> @@ -5,6 +5,7 @@ test_description='unpack-trees error messages'
>  GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
>  export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
>
> +TEST_PASSES_SANITIZE_LEAK=true
>  . ./test-lib.sh
>
>

^ permalink raw reply	[flat|nested] 193+ messages in thread

* Re: [PATCH v3 13/19] builtin/merge.c: always free "struct strbuf msg"
  2023-01-10 18:52       ` René Scharfe
@ 2023-01-13 19:57         ` Junio C Hamano
  0 siblings, 0 replies; 193+ messages in thread
From: Junio C Hamano @ 2023-01-13 19:57 UTC (permalink / raw)
  To: René Scharfe
  Cc: Ævar Arnfjörð Bjarmason, git, Eric Sunshine

René Scharfe <l.s.r@web.de> writes:

> Am 10.01.23 um 06:43 schrieb Ævar Arnfjörð Bjarmason:
>> Follow-up 465028e0e25 (merge: add missing strbuf_release(),
>> 2021-10-07) and address the "msg" memory leak in this block. We could
>> free "&msg" before the "goto done" here, but even better is to avoid
>> allocating it in the first place.
>
> So contrary to the subject we don't need to free it anymore.

;-)  I appreciate such careful reading.

^ permalink raw reply	[flat|nested] 193+ messages in thread

* [PATCH v4 00/19] leak fixes: various simple leak fixes
  2023-01-10  5:43   ` [PATCH v3 00/19] leak fixes: various simple leak fixes Ævar Arnfjörð Bjarmason
                       ` (18 preceding siblings ...)
  2023-01-10  5:43     ` [PATCH v3 19/19] push: free_refs() the "local_refs" in set_refspecs() Ævar Arnfjörð Bjarmason
@ 2023-01-17 17:11     ` Ævar Arnfjörð Bjarmason
  2023-01-17 17:11       ` [PATCH v4 01/19] tests: mark tests as passing with SANITIZE=leak Ævar Arnfjörð Bjarmason
                         ` (19 more replies)
  19 siblings, 20 replies; 193+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2023-01-17 17:11 UTC (permalink / raw)
  To: git
  Cc: René Scharfe, Junio C Hamano, Eric Sunshine,
	Ævar Arnfjörð Bjarmason

See
https://lore.kernel.org/git/cover-v3-00.19-00000000000-20230110T054138Z-avarab@gmail.com/
for the v3. Change since then:

 * Reword the subject of a commit message that no longer matched its
   content/body (thanks René).

 * Re-ran "GIT_TEST_PASSING_SANITIZE_LEAK=check
   GIT_TEST_SANITIZE_LEAK_LOG=true make SANITIZE=leak test" with "git
   rebase -i -x", so and updated the leak markings for other fixes
   that have landed on "master" since they were last updated. The tip
   of this (and all intermediate commits) pass the "check" mode.

Ævar Arnfjörð Bjarmason (19):
  tests: mark tests as passing with SANITIZE=leak
  bundle.c: don't leak the "args" in the "struct child_process"
  commit-graph: use free_commit_graph() instead of UNLEAK()
  clone: use free() instead of UNLEAK()
  various: add missing clear_pathspec(), fix leaks
  name-rev: don't xstrdup() an already dup'd string
  repack: fix leaks on error with "goto cleanup"
  worktree: fix a trivial leak in prune_worktrees()
  http-backend.c: fix "dir" and "cmd_arg" leaks in cmd_main()
  http-backend.c: fix cmd_main() memory leak, refactor reg{exec,free}()
  commit-graph: fix a parse_options_concat() leak
  show-branch: free() allocated "head" before return
  builtin/merge.c: use fixed strings, not "strbuf", fix leak
  builtin/merge.c: free "&buf" on "Your local changes..." error
  object-file.c: release the "tag" in check_tag()
  grep.c: refactor free_grep_patterns()
  grep API: plug memory leaks by freeing "header_list"
  receive-pack: free() the "ref_name" in "struct command"
  push: free_refs() the "local_refs" in set_refspecs()

 archive.c                                  |  1 +
 builtin/clean.c                            |  1 +
 builtin/clone.c                            |  5 +++--
 builtin/commit-graph.c                     | 10 ++++++----
 builtin/merge.c                            | 14 ++++++-------
 builtin/name-rev.c                         | 23 ++++++++++------------
 builtin/push.c                             |  1 +
 builtin/receive-pack.c                     | 10 ++++++++++
 builtin/repack.c                           | 13 ++++++------
 builtin/reset.c                            | 11 ++++++++---
 builtin/show-branch.c                      |  1 +
 builtin/stash.c                            |  7 +++++--
 builtin/worktree.c                         |  6 +++---
 bundle.c                                   |  6 ++++--
 grep.c                                     | 15 +++++++++-----
 http-backend.c                             |  9 +++++++--
 object-file.c                              |  1 +
 t/t0023-crlf-am.sh                         |  1 +
 t/t1301-shared-repo.sh                     |  1 +
 t/t1302-repo-version.sh                    |  1 +
 t/t1304-default-acl.sh                     |  1 +
 t/t1408-packed-refs.sh                     |  1 +
 t/t1410-reflog.sh                          |  1 +
 t/t1416-ref-transaction-hooks.sh           |  1 +
 t/t2401-worktree-prune.sh                  |  1 +
 t/t2402-worktree-list.sh                   |  1 +
 t/t2406-worktree-repair.sh                 |  1 +
 t/t3203-branch-output.sh                   |  2 ++
 t/t3210-pack-refs.sh                       |  1 +
 t/t3800-mktag.sh                           |  1 +
 t/t4152-am-subjects.sh                     |  2 ++
 t/t4254-am-corrupt.sh                      |  2 ++
 t/t4256-am-format-flowed.sh                |  1 +
 t/t4257-am-interactive.sh                  |  2 ++
 t/t5001-archive-attr.sh                    |  1 +
 t/t5004-archive-corner-cases.sh            |  2 ++
 t/t5302-pack-index.sh                      |  2 ++
 t/t5317-pack-objects-filter-objects.sh     |  1 +
 t/t5330-no-lazy-fetch-with-commit-graph.sh |  1 +
 t/t5403-post-checkout-hook.sh              |  1 +
 t/t5405-send-pack-rewind.sh                |  1 +
 t/t5406-remote-rejects.sh                  |  1 +
 t/t5502-quickfetch.sh                      |  1 +
 t/t5504-fetch-receive-strict.sh            |  1 +
 t/t5507-remote-environment.sh              |  2 ++
 t/t5522-pull-symlink.sh                    |  1 +
 t/t5523-push-upstream.sh                   |  1 +
 t/t5527-fetch-odd-refs.sh                  |  1 +
 t/t5529-push-errors.sh                     |  2 ++
 t/t5546-receive-limits.sh                  |  2 ++
 t/t5547-push-quarantine.sh                 |  2 ++
 t/t5560-http-backend-noserver.sh           |  1 +
 t/t5561-http-backend.sh                    |  1 +
 t/t5562-http-backend-content-length.sh     |  2 ++
 t/t5604-clone-reference.sh                 |  1 +
 t/t5606-clone-options.sh                   |  1 +
 t/t5613-info-alternate.sh                  |  2 ++
 t/t5705-session-id-in-capabilities.sh      |  1 +
 t/t5810-proto-disable-local.sh             |  2 ++
 t/t5813-proto-disable-ssh.sh               |  2 ++
 t/t6011-rev-list-with-bad-commit.sh        |  1 +
 t/t6014-rev-list-all.sh                    |  1 +
 t/t6021-rev-list-exclude-hidden.sh         |  1 +
 t/t6439-merge-co-error-msgs.sh             |  1 +
 t/t7105-reset-patch.sh                     |  2 ++
 t/t7106-reset-unborn-branch.sh             |  2 ++
 t/t7107-reset-pathspec-file.sh             |  1 +
 t/t7301-clean-interactive.sh               |  1 +
 t/t7403-submodule-sync.sh                  |  1 +
 t/t7409-submodule-detached-work-tree.sh    |  1 +
 t/t7416-submodule-dash-url.sh              |  2 ++
 t/t7450-bad-git-dotfiles.sh                |  2 ++
 t/t7701-repack-unpack-unreachable.sh       |  1 +
 73 files changed, 158 insertions(+), 50 deletions(-)

Range-diff against v3:
 1:  f5b67f44e2d =  1:  2ed69e3cda3 tests: mark tests as passing with SANITIZE=leak
 2:  88c6b66be3c =  2:  9993786ba0d bundle.c: don't leak the "args" in the "struct child_process"
 3:  8cc8060cd92 =  3:  8e98d7c4ebf commit-graph: use free_commit_graph() instead of UNLEAK()
 4:  765d5cbcf81 =  4:  966d7657d54 clone: use free() instead of UNLEAK()
 5:  5087fb73286 =  5:  93a8f8fa1b9 various: add missing clear_pathspec(), fix leaks
 6:  39cb8aefb58 =  6:  bd15d991ac7 name-rev: don't xstrdup() an already dup'd string
 7:  a3f1e800127 =  7:  fd890121ebe repack: fix leaks on error with "goto cleanup"
 8:  f918a6f2adc !  8:  1fe25bc6981 worktree: fix a trivial leak in prune_worktrees()
    @@ t/t2406-worktree-repair.sh
      . ./test-lib.sh
      
      test_expect_success setup '
    +
    + ## t/t3203-branch-output.sh ##
    +@@
    + #!/bin/sh
    + 
    + test_description='git branch display tests'
    ++
    ++TEST_PASSES_SANITIZE_LEAK=true
    + . ./test-lib.sh
    + . "$TEST_DIRECTORY"/lib-terminal.sh
    + 
 9:  56204806dfd =  9:  6b3dd9b15f0 http-backend.c: fix "dir" and "cmd_arg" leaks in cmd_main()
10:  5355e0fc60b = 10:  246f71bb447 http-backend.c: fix cmd_main() memory leak, refactor reg{exec,free}()
11:  dfb52dbd1c4 = 11:  ab31d8d10da commit-graph: fix a parse_options_concat() leak
12:  e44e74dcc58 = 12:  9054b353220 show-branch: free() allocated "head" before return
13:  6d99fdcc44e ! 13:  05836b08e0f builtin/merge.c: always free "struct strbuf msg"
    @@ Metadata
     Author: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
     
      ## Commit message ##
    -    builtin/merge.c: always free "struct strbuf msg"
    +    builtin/merge.c: use fixed strings, not "strbuf", fix leak
     
         Follow-up 465028e0e25 (merge: add missing strbuf_release(),
         2021-10-07) and address the "msg" memory leak in this block. We could
14:  a3bf3045597 = 14:  e8ea18b08c2 builtin/merge.c: free "&buf" on "Your local changes..." error
15:  7c70bbdebc8 = 15:  66c24afb893 object-file.c: release the "tag" in check_tag()
16:  17537e1393e = 16:  52744d9690f grep.c: refactor free_grep_patterns()
17:  e4bd46a343e = 17:  8ff63d9095c grep API: plug memory leaks by freeing "header_list"
18:  3e4b12cb623 ! 18:  0ad7d59b881 receive-pack: free() the "ref_name" in "struct command"
    @@ t/t5527-fetch-odd-refs.sh: test_description='test fetching of oddly-named refs'
      
      # afterwards we will have:
     
    + ## t/t5560-http-backend-noserver.sh ##
    +@@ t/t5560-http-backend-noserver.sh: test_description='test git-http-backend-noserver'
    + GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
    + export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
    + 
    ++TEST_PASSES_SANITIZE_LEAK=true
    + . ./test-lib.sh
    + 
    + HTTPD_DOCUMENT_ROOT_PATH="$TRASH_DIRECTORY"
    +
    + ## t/t5561-http-backend.sh ##
    +@@ t/t5561-http-backend.sh: test_description='test git-http-backend'
    + GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
    + export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
    + 
    ++TEST_PASSES_SANITIZE_LEAK=true
    + . ./test-lib.sh
    + . "$TEST_DIRECTORY"/lib-httpd.sh
    + 
    +
    + ## t/t5562-http-backend-content-length.sh ##
    +@@
    + #!/bin/sh
    + 
    + test_description='test git-http-backend respects CONTENT_LENGTH'
    ++
    ++TEST_PASSES_SANITIZE_LEAK=true
    + . ./test-lib.sh
    + 
    + test_lazy_prereq GZIP 'gzip --version'
    +
      ## t/t5705-session-id-in-capabilities.sh ##
     @@
      
19:  d51ed239a8a ! 19:  b3aee41d0b4 push: free_refs() the "local_refs" in set_refspecs()
    @@ t/t1416-ref-transaction-hooks.sh: test_description='reference transaction hooks'
      
      test_expect_success setup '
     
    + ## t/t2402-worktree-list.sh ##
    +@@ t/t2402-worktree-list.sh: test_description='test git worktree list'
    + GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
    + export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
    + 
    ++TEST_PASSES_SANITIZE_LEAK=true
    + . ./test-lib.sh
    + 
    + test_expect_success 'setup' '
    +
      ## t/t5504-fetch-receive-strict.sh ##
     @@ t/t5504-fetch-receive-strict.sh: test_description='fetch/receive strict mode'
      GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
-- 
2.39.0.1225.g30a3d88132d


^ permalink raw reply	[flat|nested] 193+ messages in thread

* [PATCH v4 01/19] tests: mark tests as passing with SANITIZE=leak
  2023-01-17 17:11     ` [PATCH v4 00/19] leak fixes: various simple leak fixes Ævar Arnfjörð Bjarmason
@ 2023-01-17 17:11       ` Ævar Arnfjörð Bjarmason
  2023-01-17 17:11       ` [PATCH v4 02/19] bundle.c: don't leak the "args" in the "struct child_process" Ævar Arnfjörð Bjarmason
                         ` (18 subsequent siblings)
  19 siblings, 0 replies; 193+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2023-01-17 17:11 UTC (permalink / raw)
  To: git
  Cc: René Scharfe, Junio C Hamano, Eric Sunshine,
	Ævar Arnfjörð Bjarmason

When the "ab/various-leak-fixes" topic was merged in [1] only t6021
would fail if the tests were run in the
"GIT_TEST_PASSING_SANITIZE_LEAK=check" mode, i.e. to check whether we
marked all leak-free tests with "TEST_PASSES_SANITIZE_LEAK=true".

Since then we've had various tests starting to pass under
SANITIZE=leak. Let's mark those as passing, this is when they started
to pass, narrowed down with "git bisect":

- t5317-pack-objects-filter-objects.sh: In
  faebba436e6 (list-objects-filter: plug pattern_list leak, 2022-12-01).

- t3210-pack-refs.sh, t5613-info-alternate.sh,
  t7403-submodule-sync.sh: In 189e97bc4ba (diff: remove parseopts member
  from struct diff_options, 2022-12-01).

- t1408-packed-refs.sh: In ab91f6b7c42 (Merge branch
  'rs/diff-parseopts', 2022-12-19).

- t0023-crlf-am.sh, t4152-am-subjects.sh, t4254-am-corrupt.sh,
  t4256-am-format-flowed.sh, t4257-am-interactive.sh,
  t5403-post-checkout-hook.sh: In a658e881c13 (am: don't pass strvec to
  apply_parse_options(), 2022-12-13)

- t1301-shared-repo.sh, t1302-repo-version.sh: In b07a819c05f (reflog:
  clear leftovers in reflog_expiry_cleanup(), 2022-12-13).

- t1304-default-acl.sh, t1410-reflog.sh,
  t5330-no-lazy-fetch-with-commit-graph.sh, t5502-quickfetch.sh,
  t5604-clone-reference.sh, t6014-rev-list-all.sh,
  t7701-repack-unpack-unreachable.sh: In b0c61be3209 (Merge branch
  'rs/reflog-expiry-cleanup', 2022-12-26)

1. 9ea1378d046 (Merge branch 'ab/various-leak-fixes', 2022-12-14)

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 t/t0023-crlf-am.sh                         | 1 +
 t/t1301-shared-repo.sh                     | 1 +
 t/t1302-repo-version.sh                    | 1 +
 t/t1304-default-acl.sh                     | 1 +
 t/t1408-packed-refs.sh                     | 1 +
 t/t1410-reflog.sh                          | 1 +
 t/t3210-pack-refs.sh                       | 1 +
 t/t4152-am-subjects.sh                     | 2 ++
 t/t4254-am-corrupt.sh                      | 2 ++
 t/t4256-am-format-flowed.sh                | 1 +
 t/t4257-am-interactive.sh                  | 2 ++
 t/t5317-pack-objects-filter-objects.sh     | 1 +
 t/t5330-no-lazy-fetch-with-commit-graph.sh | 1 +
 t/t5403-post-checkout-hook.sh              | 1 +
 t/t5502-quickfetch.sh                      | 1 +
 t/t5604-clone-reference.sh                 | 1 +
 t/t5613-info-alternate.sh                  | 2 ++
 t/t6014-rev-list-all.sh                    | 1 +
 t/t6021-rev-list-exclude-hidden.sh         | 1 +
 t/t7403-submodule-sync.sh                  | 1 +
 t/t7701-repack-unpack-unreachable.sh       | 1 +
 21 files changed, 25 insertions(+)

diff --git a/t/t0023-crlf-am.sh b/t/t0023-crlf-am.sh
index f9bbb91f64e..575805513a3 100755
--- a/t/t0023-crlf-am.sh
+++ b/t/t0023-crlf-am.sh
@@ -2,6 +2,7 @@
 
 test_description='Test am with auto.crlf'
 
+TEST_PASSES_SANITIZE_LEAK=true
 . ./test-lib.sh
 
 cat >patchfile <<\EOF
diff --git a/t/t1301-shared-repo.sh b/t/t1301-shared-repo.sh
index 93a2f91f8a5..a1251f65100 100755
--- a/t/t1301-shared-repo.sh
+++ b/t/t1301-shared-repo.sh
@@ -8,6 +8,7 @@ test_description='Test shared repository initialization'
 GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
 export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
 
+TEST_PASSES_SANITIZE_LEAK=true
 . ./test-lib.sh
 
 # Remove a default ACL from the test dir if possible.
diff --git a/t/t1302-repo-version.sh b/t/t1302-repo-version.sh
index 7cf80bf66a6..70389fa2ebb 100755
--- a/t/t1302-repo-version.sh
+++ b/t/t1302-repo-version.sh
@@ -5,6 +5,7 @@
 
 test_description='Test repository version check'
 
+TEST_PASSES_SANITIZE_LEAK=true
 . ./test-lib.sh
 
 test_expect_success 'setup' '
diff --git a/t/t1304-default-acl.sh b/t/t1304-default-acl.sh
index c69ae41306c..31b89dd9693 100755
--- a/t/t1304-default-acl.sh
+++ b/t/t1304-default-acl.sh
@@ -9,6 +9,7 @@ test_description='Test repository with default ACL'
 # => this must come before . ./test-lib.sh
 umask 077
 
+TEST_PASSES_SANITIZE_LEAK=true
 . ./test-lib.sh
 
 # We need an arbitrary other user give permission to using ACLs. root
diff --git a/t/t1408-packed-refs.sh b/t/t1408-packed-refs.sh
index 41ba1f1d7fc..9469c79a585 100755
--- a/t/t1408-packed-refs.sh
+++ b/t/t1408-packed-refs.sh
@@ -5,6 +5,7 @@ test_description='packed-refs entries are covered by loose refs'
 GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
 export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
 
+TEST_PASSES_SANITIZE_LEAK=true
 . ./test-lib.sh
 
 test_expect_success setup '
diff --git a/t/t1410-reflog.sh b/t/t1410-reflog.sh
index aa59954f6c5..6c45965b1e4 100755
--- a/t/t1410-reflog.sh
+++ b/t/t1410-reflog.sh
@@ -7,6 +7,7 @@ test_description='Test prune and reflog expiration'
 GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
 export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
 
+TEST_PASSES_SANITIZE_LEAK=true
 . ./test-lib.sh
 
 check_have () {
diff --git a/t/t3210-pack-refs.sh b/t/t3210-pack-refs.sh
index 577f32dc71f..07a0ff93def 100755
--- a/t/t3210-pack-refs.sh
+++ b/t/t3210-pack-refs.sh
@@ -12,6 +12,7 @@ semantic is still the same.
 GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
 export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
 
+TEST_PASSES_SANITIZE_LEAK=true
 . ./test-lib.sh
 
 test_expect_success 'enable reflogs' '
diff --git a/t/t4152-am-subjects.sh b/t/t4152-am-subjects.sh
index 4c68245acad..9f2edba1f83 100755
--- a/t/t4152-am-subjects.sh
+++ b/t/t4152-am-subjects.sh
@@ -1,6 +1,8 @@
 #!/bin/sh
 
 test_description='test subject preservation with format-patch | am'
+
+TEST_PASSES_SANITIZE_LEAK=true
 . ./test-lib.sh
 
 make_patches() {
diff --git a/t/t4254-am-corrupt.sh b/t/t4254-am-corrupt.sh
index 54be7da1611..45f1d4f95e5 100755
--- a/t/t4254-am-corrupt.sh
+++ b/t/t4254-am-corrupt.sh
@@ -1,6 +1,8 @@
 #!/bin/sh
 
 test_description='git am with corrupt input'
+
+TEST_PASSES_SANITIZE_LEAK=true
 . ./test-lib.sh
 
 make_mbox_with_nul () {
diff --git a/t/t4256-am-format-flowed.sh b/t/t4256-am-format-flowed.sh
index 2369c4e17ad..1015273bc82 100755
--- a/t/t4256-am-format-flowed.sh
+++ b/t/t4256-am-format-flowed.sh
@@ -2,6 +2,7 @@
 
 test_description='test format=flowed support of git am'
 
+TEST_PASSES_SANITIZE_LEAK=true
 . ./test-lib.sh
 
 test_expect_success 'setup' '
diff --git a/t/t4257-am-interactive.sh b/t/t4257-am-interactive.sh
index aed8f4de3d6..f26d7fd2dbd 100755
--- a/t/t4257-am-interactive.sh
+++ b/t/t4257-am-interactive.sh
@@ -1,6 +1,8 @@
 #!/bin/sh
 
 test_description='am --interactive tests'
+
+TEST_PASSES_SANITIZE_LEAK=true
 . ./test-lib.sh
 
 test_expect_success 'set up patches to apply' '
diff --git a/t/t5317-pack-objects-filter-objects.sh b/t/t5317-pack-objects-filter-objects.sh
index 5b707d911b5..b26d476c646 100755
--- a/t/t5317-pack-objects-filter-objects.sh
+++ b/t/t5317-pack-objects-filter-objects.sh
@@ -5,6 +5,7 @@ test_description='git pack-objects using object filtering'
 GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
 export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
 
+TEST_PASSES_SANITIZE_LEAK=true
 . ./test-lib.sh
 
 # Test blob:none filter.
diff --git a/t/t5330-no-lazy-fetch-with-commit-graph.sh b/t/t5330-no-lazy-fetch-with-commit-graph.sh
index 2cc7fd7a476..5eb28f0512d 100755
--- a/t/t5330-no-lazy-fetch-with-commit-graph.sh
+++ b/t/t5330-no-lazy-fetch-with-commit-graph.sh
@@ -2,6 +2,7 @@
 
 test_description='test for no lazy fetch with the commit-graph'
 
+TEST_PASSES_SANITIZE_LEAK=true
 . ./test-lib.sh
 
 test_expect_success 'setup: prepare a repository with a commit' '
diff --git a/t/t5403-post-checkout-hook.sh b/t/t5403-post-checkout-hook.sh
index 978f240cdac..cfaae547398 100755
--- a/t/t5403-post-checkout-hook.sh
+++ b/t/t5403-post-checkout-hook.sh
@@ -7,6 +7,7 @@ test_description='Test the post-checkout hook.'
 GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
 export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
 
+TEST_PASSES_SANITIZE_LEAK=true
 . ./test-lib.sh
 
 test_expect_success setup '
diff --git a/t/t5502-quickfetch.sh b/t/t5502-quickfetch.sh
index b160f8b7fb7..7b3ff21b984 100755
--- a/t/t5502-quickfetch.sh
+++ b/t/t5502-quickfetch.sh
@@ -5,6 +5,7 @@ test_description='test quickfetch from local'
 GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
 export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
 
+TEST_PASSES_SANITIZE_LEAK=true
 . ./test-lib.sh
 
 test_expect_success setup '
diff --git a/t/t5604-clone-reference.sh b/t/t5604-clone-reference.sh
index 2734e37e880..dc86dea1333 100755
--- a/t/t5604-clone-reference.sh
+++ b/t/t5604-clone-reference.sh
@@ -7,6 +7,7 @@ test_description='test clone --reference'
 GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
 export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
 
+TEST_PASSES_SANITIZE_LEAK=true
 . ./test-lib.sh
 
 base_dir=$(pwd)
diff --git a/t/t5613-info-alternate.sh b/t/t5613-info-alternate.sh
index 895f46bb911..7708cbafa98 100755
--- a/t/t5613-info-alternate.sh
+++ b/t/t5613-info-alternate.sh
@@ -4,6 +4,8 @@
 #
 
 test_description='test transitive info/alternate entries'
+
+TEST_PASSES_SANITIZE_LEAK=true
 . ./test-lib.sh
 
 test_expect_success 'preparing first repository' '
diff --git a/t/t6014-rev-list-all.sh b/t/t6014-rev-list-all.sh
index c9bedd29cba..16b8bd1d090 100755
--- a/t/t6014-rev-list-all.sh
+++ b/t/t6014-rev-list-all.sh
@@ -2,6 +2,7 @@
 
 test_description='--all includes detached HEADs'
 
+TEST_PASSES_SANITIZE_LEAK=true
 . ./test-lib.sh
 
 
diff --git a/t/t6021-rev-list-exclude-hidden.sh b/t/t6021-rev-list-exclude-hidden.sh
index 32b2b094138..11c50b7c0dd 100755
--- a/t/t6021-rev-list-exclude-hidden.sh
+++ b/t/t6021-rev-list-exclude-hidden.sh
@@ -2,6 +2,7 @@
 
 test_description='git rev-list --exclude-hidden test'
 
+TEST_PASSES_SANITIZE_LEAK=true
 . ./test-lib.sh
 
 test_expect_success 'setup' '
diff --git a/t/t7403-submodule-sync.sh b/t/t7403-submodule-sync.sh
index ea92ef52a5e..ff09443a0a4 100755
--- a/t/t7403-submodule-sync.sh
+++ b/t/t7403-submodule-sync.sh
@@ -11,6 +11,7 @@ These tests exercise the "git submodule sync" subcommand.
 GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
 export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
 
+TEST_PASSES_SANITIZE_LEAK=true
 . ./test-lib.sh
 
 test_expect_success setup '
diff --git a/t/t7701-repack-unpack-unreachable.sh b/t/t7701-repack-unpack-unreachable.sh
index b7ac4f598a8..ebb267855fe 100755
--- a/t/t7701-repack-unpack-unreachable.sh
+++ b/t/t7701-repack-unpack-unreachable.sh
@@ -5,6 +5,7 @@ test_description='git repack works correctly'
 GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
 export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
 
+TEST_PASSES_SANITIZE_LEAK=true
 . ./test-lib.sh
 
 fsha1=
-- 
2.39.0.1225.g30a3d88132d


^ permalink raw reply related	[flat|nested] 193+ messages in thread

* [PATCH v4 02/19] bundle.c: don't leak the "args" in the "struct child_process"
  2023-01-17 17:11     ` [PATCH v4 00/19] leak fixes: various simple leak fixes Ævar Arnfjörð Bjarmason
  2023-01-17 17:11       ` [PATCH v4 01/19] tests: mark tests as passing with SANITIZE=leak Ævar Arnfjörð Bjarmason
@ 2023-01-17 17:11       ` Ævar Arnfjörð Bjarmason
  2023-01-17 17:11       ` [PATCH v4 03/19] commit-graph: use free_commit_graph() instead of UNLEAK() Ævar Arnfjörð Bjarmason
                         ` (17 subsequent siblings)
  19 siblings, 0 replies; 193+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2023-01-17 17:11 UTC (permalink / raw)
  To: git
  Cc: René Scharfe, Junio C Hamano, Eric Sunshine,
	Ævar Arnfjörð Bjarmason

Fix a leak that's been here since 7366096de9d (bundle API: change
"flags" to be "extra_index_pack_args", 2021-09-05), if can't verify
the bundle we didn't call child_process_clear() to clear the "args".

But rather than doing that let's verify the bundle before we start
preparing the process we're going to spawn, if we get an error we
don't need to push anything to the "args".

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 bundle.c | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/bundle.c b/bundle.c
index 4ef7256aa11..9ebb10a8f72 100644
--- a/bundle.c
+++ b/bundle.c
@@ -627,6 +627,10 @@ int unbundle(struct repository *r, struct bundle_header *header,
 	     enum verify_bundle_flags flags)
 {
 	struct child_process ip = CHILD_PROCESS_INIT;
+
+	if (verify_bundle(r, header, flags))
+		return -1;
+
 	strvec_pushl(&ip.args, "index-pack", "--fix-thin", "--stdin", NULL);
 
 	/* If there is a filter, then we need to create the promisor pack. */
@@ -638,8 +642,6 @@ int unbundle(struct repository *r, struct bundle_header *header,
 		strvec_clear(extra_index_pack_args);
 	}
 
-	if (verify_bundle(r, header, flags))
-		return -1;
 	ip.in = bundle_fd;
 	ip.no_stdout = 1;
 	ip.git_cmd = 1;
-- 
2.39.0.1225.g30a3d88132d


^ permalink raw reply related	[flat|nested] 193+ messages in thread

* [PATCH v4 03/19] commit-graph: use free_commit_graph() instead of UNLEAK()
  2023-01-17 17:11     ` [PATCH v4 00/19] leak fixes: various simple leak fixes Ævar Arnfjörð Bjarmason
  2023-01-17 17:11       ` [PATCH v4 01/19] tests: mark tests as passing with SANITIZE=leak Ævar Arnfjörð Bjarmason
  2023-01-17 17:11       ` [PATCH v4 02/19] bundle.c: don't leak the "args" in the "struct child_process" Ævar Arnfjörð Bjarmason
@ 2023-01-17 17:11       ` Ævar Arnfjörð Bjarmason
  2023-01-17 17:11       ` [PATCH v4 04/19] clone: use free() " Ævar Arnfjörð Bjarmason
                         ` (16 subsequent siblings)
  19 siblings, 0 replies; 193+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2023-01-17 17:11 UTC (permalink / raw)
  To: git
  Cc: René Scharfe, Junio C Hamano, Eric Sunshine,
	Ævar Arnfjörð Bjarmason

In 0bfb48e6723 (builtin/commit-graph.c: UNLEAK variables, 2018-10-03)
this was made to UNLEAK(), but we can just as easily invoke the
free_commit_graph() function added in c3756d5b7fc (commit-graph: add
free_commit_graph, 2018-07-11) instead.

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 builtin/commit-graph.c | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/builtin/commit-graph.c b/builtin/commit-graph.c
index e8f77f535f3..0102ac8540e 100644
--- a/builtin/commit-graph.c
+++ b/builtin/commit-graph.c
@@ -67,6 +67,7 @@ static int graph_verify(int argc, const char **argv, const char *prefix)
 	int fd;
 	struct stat st;
 	int flags = 0;
+	int ret;
 
 	static struct option builtin_commit_graph_verify_options[] = {
 		OPT_BOOL(0, "shallow", &opts.shallow,
@@ -111,8 +112,9 @@ static int graph_verify(int argc, const char **argv, const char *prefix)
 	if (!graph)
 		return !!open_ok;
 
-	UNLEAK(graph);
-	return verify_commit_graph(the_repository, graph, flags);
+	ret = verify_commit_graph(the_repository, graph, flags);
+	free_commit_graph(graph);
+	return ret;
 }
 
 extern int read_replace_refs;
-- 
2.39.0.1225.g30a3d88132d


^ permalink raw reply related	[flat|nested] 193+ messages in thread

* [PATCH v4 04/19] clone: use free() instead of UNLEAK()
  2023-01-17 17:11     ` [PATCH v4 00/19] leak fixes: various simple leak fixes Ævar Arnfjörð Bjarmason
                         ` (2 preceding siblings ...)
  2023-01-17 17:11       ` [PATCH v4 03/19] commit-graph: use free_commit_graph() instead of UNLEAK() Ævar Arnfjörð Bjarmason
@ 2023-01-17 17:11       ` Ævar Arnfjörð Bjarmason
  2023-01-17 17:11       ` [PATCH v4 05/19] various: add missing clear_pathspec(), fix leaks Ævar Arnfjörð Bjarmason
                         ` (15 subsequent siblings)
  19 siblings, 0 replies; 193+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2023-01-17 17:11 UTC (permalink / raw)
  To: git
  Cc: René Scharfe, Junio C Hamano, Eric Sunshine,
	Ævar Arnfjörð Bjarmason

Change an UNLEAK() added in 0c4542738e6 (clone: free or UNLEAK further
pointers when finished, 2021-03-14) to use a "to_free" pattern
instead. In this case the "repo" can be either this absolute_pathdup()
value, or in the "else if" branch seen in the context the the
"argv[0]" argument to "main()".

We can only free() the value in the former case, hence the "to_free"
pattern.

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 builtin/clone.c | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/builtin/clone.c b/builtin/clone.c
index 5453ba5277f..ba82f5e4108 100644
--- a/builtin/clone.c
+++ b/builtin/clone.c
@@ -892,6 +892,7 @@ int cmd_clone(int argc, const char **argv, const char *prefix)
 	int is_bundle = 0, is_local;
 	int reject_shallow = 0;
 	const char *repo_name, *repo, *work_tree, *git_dir;
+	char *repo_to_free = NULL;
 	char *path = NULL, *dir, *display_repo = NULL;
 	int dest_exists, real_dest_exists = 0;
 	const struct ref *refs, *remote_head;
@@ -949,7 +950,7 @@ int cmd_clone(int argc, const char **argv, const char *prefix)
 	path = get_repo_path(repo_name, &is_bundle);
 	if (path) {
 		FREE_AND_NULL(path);
-		repo = absolute_pathdup(repo_name);
+		repo = repo_to_free = absolute_pathdup(repo_name);
 	} else if (strchr(repo_name, ':')) {
 		repo = repo_name;
 		display_repo = transport_anonymize_url(repo);
@@ -1413,7 +1414,7 @@ int cmd_clone(int argc, const char **argv, const char *prefix)
 	free(unborn_head);
 	free(dir);
 	free(path);
-	UNLEAK(repo);
+	free(repo_to_free);
 	junk_mode = JUNK_LEAVE_ALL;
 
 	transport_ls_refs_options_release(&transport_ls_refs_options);
-- 
2.39.0.1225.g30a3d88132d


^ permalink raw reply related	[flat|nested] 193+ messages in thread

* [PATCH v4 05/19] various: add missing clear_pathspec(), fix leaks
  2023-01-17 17:11     ` [PATCH v4 00/19] leak fixes: various simple leak fixes Ævar Arnfjörð Bjarmason
                         ` (3 preceding siblings ...)
  2023-01-17 17:11       ` [PATCH v4 04/19] clone: use free() " Ævar Arnfjörð Bjarmason
@ 2023-01-17 17:11       ` Ævar Arnfjörð Bjarmason
  2023-01-17 17:11       ` [PATCH v4 06/19] name-rev: don't xstrdup() an already dup'd string Ævar Arnfjörð Bjarmason
                         ` (14 subsequent siblings)
  19 siblings, 0 replies; 193+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2023-01-17 17:11 UTC (permalink / raw)
  To: git
  Cc: René Scharfe, Junio C Hamano, Eric Sunshine,
	Ævar Arnfjörð Bjarmason

Fix memory leaks resulting from a missing clear_pathspec().

- archive.c: Plug a leak in the "struct archiver_args", and
  clear_pathspec() the "pathspec" member that the "parse_pathspec_arg()"
  call in this function populates.

- builtin/clean.c: Fix a memory leak that's been with us since
  893d839970c (clean: convert to use parse_pathspec, 2013-07-14).

- builtin/reset.c: Add clear_pathspec() calls to cmd_reset(),
  including to the codepaths where we'd return early.

- builtin/stash.c: Call clear_pathspec() on the pathspec initialized
  in push_stash().

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 archive.c                       |  1 +
 builtin/clean.c                 |  1 +
 builtin/reset.c                 | 11 ++++++++---
 builtin/stash.c                 |  7 +++++--
 t/t5001-archive-attr.sh         |  1 +
 t/t5004-archive-corner-cases.sh |  2 ++
 t/t7105-reset-patch.sh          |  2 ++
 t/t7106-reset-unborn-branch.sh  |  2 ++
 t/t7107-reset-pathspec-file.sh  |  1 +
 t/t7301-clean-interactive.sh    |  1 +
 10 files changed, 24 insertions(+), 5 deletions(-)

diff --git a/archive.c b/archive.c
index 941495f5d78..a2d813e50db 100644
--- a/archive.c
+++ b/archive.c
@@ -710,6 +710,7 @@ int write_archive(int argc, const char **argv, const char *prefix,
 
 	string_list_clear_func(&args.extra_files, extra_file_info_clear);
 	free(args.refname);
+	clear_pathspec(&args.pathspec);
 
 	return rc;
 }
diff --git a/builtin/clean.c b/builtin/clean.c
index b2701a28158..b15eab328b7 100644
--- a/builtin/clean.c
+++ b/builtin/clean.c
@@ -1092,5 +1092,6 @@ int cmd_clean(int argc, const char **argv, const char *prefix)
 	strbuf_release(&buf);
 	string_list_clear(&del_list, 0);
 	string_list_clear(&exclude_list, 0);
+	clear_pathspec(&pathspec);
 	return (errors != 0);
 }
diff --git a/builtin/reset.c b/builtin/reset.c
index fea20a9ba0b..e9c10618cd3 100644
--- a/builtin/reset.c
+++ b/builtin/reset.c
@@ -390,7 +390,8 @@ int cmd_reset(int argc, const char **argv, const char *prefix)
 		if (reset_type != NONE)
 			die(_("options '%s' and '%s' cannot be used together"), "--patch", "--{hard,mixed,soft}");
 		trace2_cmd_mode("patch-interactive");
-		return run_add_interactive(rev, "--patch=reset", &pathspec);
+		update_ref_status = run_add_interactive(rev, "--patch=reset", &pathspec);
+		goto cleanup;
 	}
 
 	/* git reset tree [--] paths... can be used to
@@ -439,8 +440,10 @@ int cmd_reset(int argc, const char **argv, const char *prefix)
 				       LOCK_DIE_ON_ERROR);
 		if (reset_type == MIXED) {
 			int flags = quiet ? REFRESH_QUIET : REFRESH_IN_PORCELAIN;
-			if (read_from_tree(&pathspec, &oid, intent_to_add))
-				return 1;
+			if (read_from_tree(&pathspec, &oid, intent_to_add)) {
+				update_ref_status = 1;
+				goto cleanup;
+			}
 			the_index.updated_skipworktree = 1;
 			if (!no_refresh && get_git_work_tree()) {
 				uint64_t t_begin, t_delta_in_ms;
@@ -488,5 +491,7 @@ int cmd_reset(int argc, const char **argv, const char *prefix)
 
 	discard_index(&the_index);
 
+cleanup:
+	clear_pathspec(&pathspec);
 	return update_ref_status;
 }
diff --git a/builtin/stash.c b/builtin/stash.c
index bb0fd861434..45bffdf54bb 100644
--- a/builtin/stash.c
+++ b/builtin/stash.c
@@ -1727,6 +1727,7 @@ static int push_stash(int argc, const char **argv, const char *prefix,
 		OPT_PATHSPEC_FILE_NUL(&pathspec_file_nul),
 		OPT_END()
 	};
+	int ret;
 
 	if (argc) {
 		force_assume = !strcmp(argv[0], "-p");
@@ -1766,8 +1767,10 @@ static int push_stash(int argc, const char **argv, const char *prefix,
 		die(_("the option '%s' requires '%s'"), "--pathspec-file-nul", "--pathspec-from-file");
 	}
 
-	return do_push_stash(&ps, stash_msg, quiet, keep_index, patch_mode,
-			     include_untracked, only_staged);
+	ret = do_push_stash(&ps, stash_msg, quiet, keep_index, patch_mode,
+			    include_untracked, only_staged);
+	clear_pathspec(&ps);
+	return ret;
 }
 
 static int push_stash_unassumed(int argc, const char **argv, const char *prefix)
diff --git a/t/t5001-archive-attr.sh b/t/t5001-archive-attr.sh
index 2f6eef5e372..04d300eeda7 100755
--- a/t/t5001-archive-attr.sh
+++ b/t/t5001-archive-attr.sh
@@ -3,6 +3,7 @@
 test_description='git archive attribute tests'
 
 TEST_CREATE_REPO_NO_TEMPLATE=1
+TEST_PASSES_SANITIZE_LEAK=true
 . ./test-lib.sh
 
 SUBSTFORMAT='%H (%h)%n'
diff --git a/t/t5004-archive-corner-cases.sh b/t/t5004-archive-corner-cases.sh
index ae508e21623..9f2c6da80e8 100755
--- a/t/t5004-archive-corner-cases.sh
+++ b/t/t5004-archive-corner-cases.sh
@@ -1,6 +1,8 @@
 #!/bin/sh
 
 test_description='test corner cases of git-archive'
+
+TEST_PASSES_SANITIZE_LEAK=true
 . ./test-lib.sh
 
 # the 10knuls.tar file is used to test for an empty git generated tar
diff --git a/t/t7105-reset-patch.sh b/t/t7105-reset-patch.sh
index fc2a6cf5c7a..9b46da7aaa7 100755
--- a/t/t7105-reset-patch.sh
+++ b/t/t7105-reset-patch.sh
@@ -1,6 +1,8 @@
 #!/bin/sh
 
 test_description='git reset --patch'
+
+TEST_PASSES_SANITIZE_LEAK=true
 . ./lib-patch-mode.sh
 
 test_expect_success PERL 'setup' '
diff --git a/t/t7106-reset-unborn-branch.sh b/t/t7106-reset-unborn-branch.sh
index ecb85c3b823..a0b67a0b843 100755
--- a/t/t7106-reset-unborn-branch.sh
+++ b/t/t7106-reset-unborn-branch.sh
@@ -1,6 +1,8 @@
 #!/bin/sh
 
 test_description='git reset should work on unborn branch'
+
+TEST_PASSES_SANITIZE_LEAK=true
 . ./test-lib.sh
 
 test_expect_success 'setup' '
diff --git a/t/t7107-reset-pathspec-file.sh b/t/t7107-reset-pathspec-file.sh
index 523efbecde1..af5ea406db3 100755
--- a/t/t7107-reset-pathspec-file.sh
+++ b/t/t7107-reset-pathspec-file.sh
@@ -2,6 +2,7 @@
 
 test_description='reset --pathspec-from-file'
 
+TEST_PASSES_SANITIZE_LEAK=true
 . ./test-lib.sh
 
 test_tick
diff --git a/t/t7301-clean-interactive.sh b/t/t7301-clean-interactive.sh
index a07e8b86de2..d82a3210a1d 100755
--- a/t/t7301-clean-interactive.sh
+++ b/t/t7301-clean-interactive.sh
@@ -2,6 +2,7 @@
 
 test_description='git clean -i basic tests'
 
+TEST_PASSES_SANITIZE_LEAK=true
 . ./test-lib.sh
 . "$TEST_DIRECTORY"/lib-terminal.sh
 
-- 
2.39.0.1225.g30a3d88132d


^ permalink raw reply related	[flat|nested] 193+ messages in thread

* [PATCH v4 06/19] name-rev: don't xstrdup() an already dup'd string
  2023-01-17 17:11     ` [PATCH v4 00/19] leak fixes: various simple leak fixes Ævar Arnfjörð Bjarmason
                         ` (4 preceding siblings ...)
  2023-01-17 17:11       ` [PATCH v4 05/19] various: add missing clear_pathspec(), fix leaks Ævar Arnfjörð Bjarmason
@ 2023-01-17 17:11       ` Ævar Arnfjörð Bjarmason
  2023-01-17 17:11       ` [PATCH v4 07/19] repack: fix leaks on error with "goto cleanup" Ævar Arnfjörð Bjarmason
                         ` (13 subsequent siblings)
  19 siblings, 0 replies; 193+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2023-01-17 17:11 UTC (permalink / raw)
  To: git
  Cc: René Scharfe, Junio C Hamano, Eric Sunshine,
	Ævar Arnfjörð Bjarmason

When "add_to_tip_table()" is called with a non-zero
"shorten_unambiguous" we always return an xstrdup()'d string, which
we'd then xstrdup() again, leaking memory. See [1] and [2] for how
this leak came about.

We could xstrdup() only if "shorten_unambiguous" wasn't true, but
let's instead inline this code, so that information on whether we need
to xstrdup() is contained within add_to_tip_table().

1. 98c5c4ad015 (name-rev: allow to specify a subpath for --refs
   option, 2013-06-18)
2. b23e0b9353e (name-rev: allow converting the exact object name at
   the tip of a ref, 2013-07-07)

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 builtin/name-rev.c | 23 ++++++++++-------------
 1 file changed, 10 insertions(+), 13 deletions(-)

diff --git a/builtin/name-rev.c b/builtin/name-rev.c
index 15535e914a6..49fae523694 100644
--- a/builtin/name-rev.c
+++ b/builtin/name-rev.c
@@ -273,17 +273,6 @@ static int subpath_matches(const char *path, const char *filter)
 	return -1;
 }
 
-static const char *name_ref_abbrev(const char *refname, int shorten_unambiguous)
-{
-	if (shorten_unambiguous)
-		refname = shorten_unambiguous_ref(refname, 0);
-	else if (skip_prefix(refname, "refs/heads/", &refname))
-		; /* refname already advanced */
-	else
-		skip_prefix(refname, "refs/", &refname);
-	return refname;
-}
-
 struct name_ref_data {
 	int tags_only;
 	int name_only;
@@ -309,11 +298,19 @@ static void add_to_tip_table(const struct object_id *oid, const char *refname,
 			     int shorten_unambiguous, struct commit *commit,
 			     timestamp_t taggerdate, int from_tag, int deref)
 {
-	refname = name_ref_abbrev(refname, shorten_unambiguous);
+	char *short_refname = NULL;
+
+	if (shorten_unambiguous)
+		short_refname = shorten_unambiguous_ref(refname, 0);
+	else if (skip_prefix(refname, "refs/heads/", &refname))
+		; /* refname already advanced */
+	else
+		skip_prefix(refname, "refs/", &refname);
 
 	ALLOC_GROW(tip_table.table, tip_table.nr + 1, tip_table.alloc);
 	oidcpy(&tip_table.table[tip_table.nr].oid, oid);
-	tip_table.table[tip_table.nr].refname = xstrdup(refname);
+	tip_table.table[tip_table.nr].refname = short_refname ?
+		short_refname : xstrdup(refname);
 	tip_table.table[tip_table.nr].commit = commit;
 	tip_table.table[tip_table.nr].taggerdate = taggerdate;
 	tip_table.table[tip_table.nr].from_tag = from_tag;
-- 
2.39.0.1225.g30a3d88132d


^ permalink raw reply related	[flat|nested] 193+ messages in thread

* [PATCH v4 07/19] repack: fix leaks on error with "goto cleanup"
  2023-01-17 17:11     ` [PATCH v4 00/19] leak fixes: various simple leak fixes Ævar Arnfjörð Bjarmason
                         ` (5 preceding siblings ...)
  2023-01-17 17:11       ` [PATCH v4 06/19] name-rev: don't xstrdup() an already dup'd string Ævar Arnfjörð Bjarmason
@ 2023-01-17 17:11       ` Ævar Arnfjörð Bjarmason
  2023-01-17 17:11       ` [PATCH v4 08/19] worktree: fix a trivial leak in prune_worktrees() Ævar Arnfjörð Bjarmason
                         ` (12 subsequent siblings)
  19 siblings, 0 replies; 193+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2023-01-17 17:11 UTC (permalink / raw)
  To: git
  Cc: René Scharfe, Junio C Hamano, Eric Sunshine,
	Ævar Arnfjörð Bjarmason

Change cmd_repack() to "goto cleanup" rather than "return ret" on
error, when we returned we'd potentially skip cleaning up the
string_lists and other data we'd allocated in this function.

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 builtin/repack.c                    | 13 +++++++------
 t/t6011-rev-list-with-bad-commit.sh |  1 +
 2 files changed, 8 insertions(+), 6 deletions(-)

diff --git a/builtin/repack.c b/builtin/repack.c
index c1402ad038f..f6493795318 100644
--- a/builtin/repack.c
+++ b/builtin/repack.c
@@ -948,7 +948,7 @@ int cmd_repack(int argc, const char **argv, const char *prefix)
 
 	ret = start_command(&cmd);
 	if (ret)
-		return ret;
+		goto cleanup;
 
 	if (geometry) {
 		FILE *in = xfdopen(cmd.in, "w");
@@ -977,7 +977,7 @@ int cmd_repack(int argc, const char **argv, const char *prefix)
 	fclose(out);
 	ret = finish_command(&cmd);
 	if (ret)
-		return ret;
+		goto cleanup;
 
 	if (!names.nr && !po_args.quiet)
 		printf_ln(_("Nothing new to pack."));
@@ -1007,7 +1007,7 @@ int cmd_repack(int argc, const char **argv, const char *prefix)
 				       &existing_nonkept_packs,
 				       &existing_kept_packs);
 		if (ret)
-			return ret;
+			goto cleanup;
 
 		if (delete_redundant && expire_to) {
 			/*
@@ -1039,7 +1039,7 @@ int cmd_repack(int argc, const char **argv, const char *prefix)
 					       &existing_nonkept_packs,
 					       &existing_kept_packs);
 			if (ret)
-				return ret;
+				goto cleanup;
 		}
 	}
 
@@ -1115,7 +1115,7 @@ int cmd_repack(int argc, const char **argv, const char *prefix)
 		string_list_clear(&include, 0);
 
 		if (ret)
-			return ret;
+			goto cleanup;
 	}
 
 	reprepare_packed_git(the_repository);
@@ -1172,10 +1172,11 @@ int cmd_repack(int argc, const char **argv, const char *prefix)
 		write_midx_file(get_object_directory(), NULL, NULL, flags);
 	}
 
+cleanup:
 	string_list_clear(&names, 1);
 	string_list_clear(&existing_nonkept_packs, 0);
 	string_list_clear(&existing_kept_packs, 0);
 	clear_pack_geometry(geometry);
 
-	return 0;
+	return ret;
 }
diff --git a/t/t6011-rev-list-with-bad-commit.sh b/t/t6011-rev-list-with-bad-commit.sh
index bad02cf5b83..b2e422cf0f7 100755
--- a/t/t6011-rev-list-with-bad-commit.sh
+++ b/t/t6011-rev-list-with-bad-commit.sh
@@ -2,6 +2,7 @@
 
 test_description='git rev-list should notice bad commits'
 
+TEST_PASSES_SANITIZE_LEAK=true
 . ./test-lib.sh
 
 # Note:
-- 
2.39.0.1225.g30a3d88132d


^ permalink raw reply related	[flat|nested] 193+ messages in thread

* [PATCH v4 08/19] worktree: fix a trivial leak in prune_worktrees()
  2023-01-17 17:11     ` [PATCH v4 00/19] leak fixes: various simple leak fixes Ævar Arnfjörð Bjarmason
                         ` (6 preceding siblings ...)
  2023-01-17 17:11       ` [PATCH v4 07/19] repack: fix leaks on error with "goto cleanup" Ævar Arnfjörð Bjarmason
@ 2023-01-17 17:11       ` Ævar Arnfjörð Bjarmason
  2023-01-18  6:28         ` Junio C Hamano
  2023-01-17 17:11       ` [PATCH v4 09/19] http-backend.c: fix "dir" and "cmd_arg" leaks in cmd_main() Ævar Arnfjörð Bjarmason
                         ` (11 subsequent siblings)
  19 siblings, 1 reply; 193+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2023-01-17 17:11 UTC (permalink / raw)
  To: git
  Cc: René Scharfe, Junio C Hamano, Eric Sunshine,
	Ævar Arnfjörð Bjarmason

We were leaking both the "struct strbuf" in prune_worktrees(), as well
as the "path" we got from should_prune_worktree(). Since these were
the only two uses of the "struct string_list" let's change it to a
"DUP" and push these to it with "string_list_append_nodup()".

For the string_list_append_nodup() we could also string_list_append()
the main_path.buf, and then strbuf_release(&main_path) right away. But
doing it this way avoids an allocation, as we already have the "struct
strbuf" prepared for appending to "kept".

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 builtin/worktree.c         | 6 +++---
 t/t2401-worktree-prune.sh  | 1 +
 t/t2406-worktree-repair.sh | 1 +
 t/t3203-branch-output.sh   | 2 ++
 4 files changed, 7 insertions(+), 3 deletions(-)

diff --git a/builtin/worktree.c b/builtin/worktree.c
index 591d659faea..865ce9be22b 100644
--- a/builtin/worktree.c
+++ b/builtin/worktree.c
@@ -173,7 +173,7 @@ static void prune_worktrees(void)
 {
 	struct strbuf reason = STRBUF_INIT;
 	struct strbuf main_path = STRBUF_INIT;
-	struct string_list kept = STRING_LIST_INIT_NODUP;
+	struct string_list kept = STRING_LIST_INIT_DUP;
 	DIR *dir = opendir(git_path("worktrees"));
 	struct dirent *d;
 	if (!dir)
@@ -184,14 +184,14 @@ static void prune_worktrees(void)
 		if (should_prune_worktree(d->d_name, &reason, &path, expire))
 			prune_worktree(d->d_name, reason.buf);
 		else if (path)
-			string_list_append(&kept, path)->util = xstrdup(d->d_name);
+			string_list_append_nodup(&kept, path)->util = xstrdup(d->d_name);
 	}
 	closedir(dir);
 
 	strbuf_add_absolute_path(&main_path, get_git_common_dir());
 	/* massage main worktree absolute path to match 'gitdir' content */
 	strbuf_strip_suffix(&main_path, "/.");
-	string_list_append(&kept, strbuf_detach(&main_path, NULL));
+	string_list_append_nodup(&kept, strbuf_detach(&main_path, NULL));
 	prune_dups(&kept);
 	string_list_clear(&kept, 1);
 
diff --git a/t/t2401-worktree-prune.sh b/t/t2401-worktree-prune.sh
index 3d28c7f06b2..568a47ec426 100755
--- a/t/t2401-worktree-prune.sh
+++ b/t/t2401-worktree-prune.sh
@@ -5,6 +5,7 @@ test_description='prune $GIT_DIR/worktrees'
 GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
 export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
 
+TEST_PASSES_SANITIZE_LEAK=true
 . ./test-lib.sh
 
 test_expect_success initialize '
diff --git a/t/t2406-worktree-repair.sh b/t/t2406-worktree-repair.sh
index 5c44453e1c1..8970780efcc 100755
--- a/t/t2406-worktree-repair.sh
+++ b/t/t2406-worktree-repair.sh
@@ -2,6 +2,7 @@
 
 test_description='test git worktree repair'
 
+TEST_PASSES_SANITIZE_LEAK=true
 . ./test-lib.sh
 
 test_expect_success setup '
diff --git a/t/t3203-branch-output.sh b/t/t3203-branch-output.sh
index d34d77f8934..ba8d929d189 100755
--- a/t/t3203-branch-output.sh
+++ b/t/t3203-branch-output.sh
@@ -1,6 +1,8 @@
 #!/bin/sh
 
 test_description='git branch display tests'
+
+TEST_PASSES_SANITIZE_LEAK=true
 . ./test-lib.sh
 . "$TEST_DIRECTORY"/lib-terminal.sh
 
-- 
2.39.0.1225.g30a3d88132d


^ permalink raw reply related	[flat|nested] 193+ messages in thread

* [PATCH v4 09/19] http-backend.c: fix "dir" and "cmd_arg" leaks in cmd_main()
  2023-01-17 17:11     ` [PATCH v4 00/19] leak fixes: various simple leak fixes Ævar Arnfjörð Bjarmason
                         ` (7 preceding siblings ...)
  2023-01-17 17:11       ` [PATCH v4 08/19] worktree: fix a trivial leak in prune_worktrees() Ævar Arnfjörð Bjarmason
@ 2023-01-17 17:11       ` Ævar Arnfjörð Bjarmason
  2023-01-17 17:11       ` [PATCH v4 10/19] http-backend.c: fix cmd_main() memory leak, refactor reg{exec,free}() Ævar Arnfjörð Bjarmason
                         ` (10 subsequent siblings)
  19 siblings, 0 replies; 193+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2023-01-17 17:11 UTC (permalink / raw)
  To: git
  Cc: René Scharfe, Junio C Hamano, Eric Sunshine,
	Ævar Arnfjörð Bjarmason

Free the "dir" variable after we're done with it. Before
917adc03608 (http-backend: add GIT_PROJECT_ROOT environment var,
2009-10-30) there was no leak here, as we'd get it via getenv(), but
since 917adc03608 we've xstrdup()'d it (or the equivalent), so we need
to free() it.

We also need to free the "cmd_arg" variable, which has been leaked
ever since it was added in 2f4038ab337 (Git-aware CGI to provide dumb
HTTP transport, 2009-10-30).

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 http-backend.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/http-backend.c b/http-backend.c
index 6eb3b2fe51c..67819d931ce 100644
--- a/http-backend.c
+++ b/http-backend.c
@@ -786,6 +786,7 @@ int cmd_main(int argc, const char **argv)
 	if (!getenv("GIT_HTTP_EXPORT_ALL") &&
 	    access("git-daemon-export-ok", F_OK) )
 		not_found(&hdr, "Repository not exported: '%s'", dir);
+	free(dir);
 
 	http_config();
 	max_request_buffer = git_env_ulong("GIT_HTTP_MAX_REQUEST_BUFFER",
@@ -795,5 +796,6 @@ int cmd_main(int argc, const char **argv)
 		setenv(GIT_PROTOCOL_ENVIRONMENT, proto_header, 0);
 
 	cmd->imp(&hdr, cmd_arg);
+	free(cmd_arg);
 	return 0;
 }
-- 
2.39.0.1225.g30a3d88132d


^ permalink raw reply related	[flat|nested] 193+ messages in thread

* [PATCH v4 10/19] http-backend.c: fix cmd_main() memory leak, refactor reg{exec,free}()
  2023-01-17 17:11     ` [PATCH v4 00/19] leak fixes: various simple leak fixes Ævar Arnfjörð Bjarmason
                         ` (8 preceding siblings ...)
  2023-01-17 17:11       ` [PATCH v4 09/19] http-backend.c: fix "dir" and "cmd_arg" leaks in cmd_main() Ævar Arnfjörð Bjarmason
@ 2023-01-17 17:11       ` Ævar Arnfjörð Bjarmason
  2023-01-17 17:11       ` [PATCH v4 11/19] commit-graph: fix a parse_options_concat() leak Ævar Arnfjörð Bjarmason
                         ` (9 subsequent siblings)
  19 siblings, 0 replies; 193+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2023-01-17 17:11 UTC (permalink / raw)
  To: git
  Cc: René Scharfe, Junio C Hamano, Eric Sunshine,
	Ævar Arnfjörð Bjarmason

Fix a memory leak that's been with us ever since
2f4038ab337 (Git-aware CGI to provide dumb HTTP transport,
2009-10-30). In this case we're not calling regerror() after a failed
regexec(), and don't otherwise use "re" afterwards.

We can therefore simplify this code by calling regfree() right after
the regexec(). An alternative fix would be to add a regfree() to both
the "return" and "break" path in this for-loop.

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 http-backend.c | 7 +++++--
 1 file changed, 5 insertions(+), 2 deletions(-)

diff --git a/http-backend.c b/http-backend.c
index 67819d931ce..8ab58e55f85 100644
--- a/http-backend.c
+++ b/http-backend.c
@@ -759,10 +759,14 @@ int cmd_main(int argc, const char **argv)
 		struct service_cmd *c = &services[i];
 		regex_t re;
 		regmatch_t out[1];
+		int ret;
 
 		if (regcomp(&re, c->pattern, REG_EXTENDED))
 			die("Bogus regex in service table: %s", c->pattern);
-		if (!regexec(&re, dir, 1, out, 0)) {
+		ret = regexec(&re, dir, 1, out, 0);
+		regfree(&re);
+
+		if (!ret) {
 			size_t n;
 
 			if (strcmp(method, c->method))
@@ -774,7 +778,6 @@ int cmd_main(int argc, const char **argv)
 			dir[out[0].rm_so] = 0;
 			break;
 		}
-		regfree(&re);
 	}
 
 	if (!cmd)
-- 
2.39.0.1225.g30a3d88132d


^ permalink raw reply related	[flat|nested] 193+ messages in thread

* [PATCH v4 11/19] commit-graph: fix a parse_options_concat() leak
  2023-01-17 17:11     ` [PATCH v4 00/19] leak fixes: various simple leak fixes Ævar Arnfjörð Bjarmason
                         ` (9 preceding siblings ...)
  2023-01-17 17:11       ` [PATCH v4 10/19] http-backend.c: fix cmd_main() memory leak, refactor reg{exec,free}() Ævar Arnfjörð Bjarmason
@ 2023-01-17 17:11       ` Ævar Arnfjörð Bjarmason
  2023-01-17 17:11       ` [PATCH v4 12/19] show-branch: free() allocated "head" before return Ævar Arnfjörð Bjarmason
                         ` (8 subsequent siblings)
  19 siblings, 0 replies; 193+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2023-01-17 17:11 UTC (permalink / raw)
  To: git
  Cc: René Scharfe, Junio C Hamano, Eric Sunshine,
	Ævar Arnfjörð Bjarmason

When the parse_options_concat() was added to this file in
84e4484f128 (commit-graph: use parse_options_concat(), 2021-08-23) we
wouldn't free() it if we returned early in these cases.

Since "result" is 0 by default we can "goto cleanup" in both cases,
and only need to set "result" if write_commit_graph_reachable() fails.

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 builtin/commit-graph.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/builtin/commit-graph.c b/builtin/commit-graph.c
index 0102ac8540e..93704f95a9d 100644
--- a/builtin/commit-graph.c
+++ b/builtin/commit-graph.c
@@ -269,8 +269,8 @@ static int graph_write(int argc, const char **argv, const char *prefix)
 
 	if (opts.reachable) {
 		if (write_commit_graph_reachable(odb, flags, &write_opts))
-			return 1;
-		return 0;
+			result = 1;
+		goto cleanup;
 	}
 
 	if (opts.stdin_packs) {
-- 
2.39.0.1225.g30a3d88132d


^ permalink raw reply related	[flat|nested] 193+ messages in thread

* [PATCH v4 12/19] show-branch: free() allocated "head" before return
  2023-01-17 17:11     ` [PATCH v4 00/19] leak fixes: various simple leak fixes Ævar Arnfjörð Bjarmason
                         ` (10 preceding siblings ...)
  2023-01-17 17:11       ` [PATCH v4 11/19] commit-graph: fix a parse_options_concat() leak Ævar Arnfjörð Bjarmason
@ 2023-01-17 17:11       ` Ævar Arnfjörð Bjarmason
  2023-01-17 17:11       ` [PATCH v4 13/19] builtin/merge.c: use fixed strings, not "strbuf", fix leak Ævar Arnfjörð Bjarmason
                         ` (7 subsequent siblings)
  19 siblings, 0 replies; 193+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2023-01-17 17:11 UTC (permalink / raw)
  To: git
  Cc: René Scharfe, Junio C Hamano, Eric Sunshine,
	Ævar Arnfjörð Bjarmason

Stop leaking the "head" variable, which we've been leaking since it
was originally added in [1], and in its current form since [2]

1. ed378ec7e85 (Make ref resolution saner, 2006-09-11)
2. d9e557a320b (show-branch: store resolved head in heap buffer,
   2017-02-14).

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 builtin/show-branch.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/builtin/show-branch.c b/builtin/show-branch.c
index c013abaf942..358ac3e519a 100644
--- a/builtin/show-branch.c
+++ b/builtin/show-branch.c
@@ -956,5 +956,6 @@ int cmd_show_branch(int ac, const char **av, const char *prefix)
 		if (shown_merge_point && --extra < 0)
 			break;
 	}
+	free(head);
 	return 0;
 }
-- 
2.39.0.1225.g30a3d88132d


^ permalink raw reply related	[flat|nested] 193+ messages in thread

* [PATCH v4 13/19] builtin/merge.c: use fixed strings, not "strbuf", fix leak
  2023-01-17 17:11     ` [PATCH v4 00/19] leak fixes: various simple leak fixes Ævar Arnfjörð Bjarmason
                         ` (11 preceding siblings ...)
  2023-01-17 17:11       ` [PATCH v4 12/19] show-branch: free() allocated "head" before return Ævar Arnfjörð Bjarmason
@ 2023-01-17 17:11       ` Ævar Arnfjörð Bjarmason
  2023-01-17 17:11       ` [PATCH v4 14/19] builtin/merge.c: free "&buf" on "Your local changes..." error Ævar Arnfjörð Bjarmason
                         ` (6 subsequent siblings)
  19 siblings, 0 replies; 193+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2023-01-17 17:11 UTC (permalink / raw)
  To: git
  Cc: René Scharfe, Junio C Hamano, Eric Sunshine,
	Ævar Arnfjörð Bjarmason

Follow-up 465028e0e25 (merge: add missing strbuf_release(),
2021-10-07) and address the "msg" memory leak in this block. We could
free "&msg" before the "goto done" here, but even better is to avoid
allocating it in the first place.

By repeating the "Fast-forward" string here we can avoid using a
"struct strbuf" altogether.

Suggested-by: René Scharfe <l.s.r@web.de>
Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 builtin/merge.c                | 11 ++++-------
 t/t6439-merge-co-error-msgs.sh |  1 +
 2 files changed, 5 insertions(+), 7 deletions(-)

diff --git a/builtin/merge.c b/builtin/merge.c
index 0f093f2a4f2..91dd5435c59 100644
--- a/builtin/merge.c
+++ b/builtin/merge.c
@@ -1560,7 +1560,9 @@ int cmd_merge(int argc, const char **argv, const char *prefix)
 			!common->next &&
 			oideq(&common->item->object.oid, &head_commit->object.oid)) {
 		/* Again the most common case of merging one remote. */
-		struct strbuf msg = STRBUF_INIT;
+		const char *msg = have_message ?
+			"Fast-forward (no commit created; -m option ignored)" :
+			"Fast-forward";
 		struct commit *commit;
 
 		if (verbosity >= 0) {
@@ -1570,10 +1572,6 @@ int cmd_merge(int argc, const char **argv, const char *prefix)
 			       find_unique_abbrev(&remoteheads->item->object.oid,
 						  DEFAULT_ABBREV));
 		}
-		strbuf_addstr(&msg, "Fast-forward");
-		if (have_message)
-			strbuf_addstr(&msg,
-				" (no commit created; -m option ignored)");
 		commit = remoteheads->item;
 		if (!commit) {
 			ret = 1;
@@ -1592,9 +1590,8 @@ int cmd_merge(int argc, const char **argv, const char *prefix)
 			goto done;
 		}
 
-		finish(head_commit, remoteheads, &commit->object.oid, msg.buf);
+		finish(head_commit, remoteheads, &commit->object.oid, msg);
 		remove_merge_branch_state(the_repository);
-		strbuf_release(&msg);
 		goto done;
 	} else if (!remoteheads->next && common->next)
 		;
diff --git a/t/t6439-merge-co-error-msgs.sh b/t/t6439-merge-co-error-msgs.sh
index 52cf0c87690..0cbec57cdab 100755
--- a/t/t6439-merge-co-error-msgs.sh
+++ b/t/t6439-merge-co-error-msgs.sh
@@ -5,6 +5,7 @@ test_description='unpack-trees error messages'
 GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
 export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
 
+TEST_PASSES_SANITIZE_LEAK=true
 . ./test-lib.sh
 
 
-- 
2.39.0.1225.g30a3d88132d


^ permalink raw reply related	[flat|nested] 193+ messages in thread

* [PATCH v4 14/19] builtin/merge.c: free "&buf" on "Your local changes..." error
  2023-01-17 17:11     ` [PATCH v4 00/19] leak fixes: various simple leak fixes Ævar Arnfjörð Bjarmason
                         ` (12 preceding siblings ...)
  2023-01-17 17:11       ` [PATCH v4 13/19] builtin/merge.c: use fixed strings, not "strbuf", fix leak Ævar Arnfjörð Bjarmason
@ 2023-01-17 17:11       ` Ævar Arnfjörð Bjarmason
  2023-01-17 17:11       ` [PATCH v4 15/19] object-file.c: release the "tag" in check_tag() Ævar Arnfjörð Bjarmason
                         ` (5 subsequent siblings)
  19 siblings, 0 replies; 193+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2023-01-17 17:11 UTC (permalink / raw)
  To: git
  Cc: René Scharfe, Junio C Hamano, Eric Sunshine,
	Ævar Arnfjörð Bjarmason

Plug a memory leak introduced in [1], since that change didn't follow
the "goto done" pattern introduced in [2] we'd leak the "&buf" memory.

1. e4cdfe84a0d (merge: abort if index does not match HEAD for trivial
   merges, 2022-07-23)
2. d5a35c114ab (Copy resolve_ref() return value for longer use,
   2011-11-13)

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 builtin/merge.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/builtin/merge.c b/builtin/merge.c
index 91dd5435c59..2b13124c497 100644
--- a/builtin/merge.c
+++ b/builtin/merge.c
@@ -1618,7 +1618,8 @@ int cmd_merge(int argc, const char **argv, const char *prefix)
 				error(_("Your local changes to the following files would be overwritten by merge:\n  %s"),
 				      sb.buf);
 				strbuf_release(&sb);
-				return 2;
+				ret = 2;
+				goto done;
 			}
 
 			/* See if it is really trivial. */
-- 
2.39.0.1225.g30a3d88132d


^ permalink raw reply related	[flat|nested] 193+ messages in thread

* [PATCH v4 15/19] object-file.c: release the "tag" in check_tag()
  2023-01-17 17:11     ` [PATCH v4 00/19] leak fixes: various simple leak fixes Ævar Arnfjörð Bjarmason
                         ` (13 preceding siblings ...)
  2023-01-17 17:11       ` [PATCH v4 14/19] builtin/merge.c: free "&buf" on "Your local changes..." error Ævar Arnfjörð Bjarmason
@ 2023-01-17 17:11       ` Ævar Arnfjörð Bjarmason
  2023-01-17 19:58         ` René Scharfe
  2023-01-17 17:11       ` [PATCH v4 16/19] grep.c: refactor free_grep_patterns() Ævar Arnfjörð Bjarmason
                         ` (4 subsequent siblings)
  19 siblings, 1 reply; 193+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2023-01-17 17:11 UTC (permalink / raw)
  To: git
  Cc: René Scharfe, Junio C Hamano, Eric Sunshine,
	Ævar Arnfjörð Bjarmason

Fix a memory leak that's been with us ever since c879daa2372 (Make
hash-object more robust against malformed objects, 2011-02-05). With
"HASH_FORMAT_CHECK" (used by "hash-object" and "replace") we'll parse
tags into a throwaway variable on the stack, but weren't freeing the
"item->tag" we might malloc() when doing so.

The clearing that release_tag_memory() does for us is redundant here,
but let's use it as-is anyway. It only has one other existing caller,
which does need the tag to be cleared.

Mark the tests that now pass in their entirety as passing under
"SANITIZE=leak", which means we'll test them as part of the
"linux-leaks" CI job.

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 object-file.c         | 1 +
 t/t3800-mktag.sh      | 1 +
 t/t5302-pack-index.sh | 2 ++
 3 files changed, 4 insertions(+)

diff --git a/object-file.c b/object-file.c
index 80a0cd3b351..b554266aff4 100644
--- a/object-file.c
+++ b/object-file.c
@@ -2324,6 +2324,7 @@ static void check_tag(const void *buf, size_t size)
 	memset(&t, 0, sizeof(t));
 	if (parse_tag_buffer(the_repository, &t, buf, size))
 		die(_("corrupt tag"));
+	release_tag_memory(&t);
 }
 
 static int index_mem(struct index_state *istate,
diff --git a/t/t3800-mktag.sh b/t/t3800-mktag.sh
index e3cf0ffbe59..d3e428ff46e 100755
--- a/t/t3800-mktag.sh
+++ b/t/t3800-mktag.sh
@@ -4,6 +4,7 @@
 
 test_description='git mktag: tag object verify test'
 
+TEST_PASSES_SANITIZE_LEAK=true
 . ./test-lib.sh
 
 ###########################################################
diff --git a/t/t5302-pack-index.sh b/t/t5302-pack-index.sh
index b0095ab41d3..54b11f81c63 100755
--- a/t/t5302-pack-index.sh
+++ b/t/t5302-pack-index.sh
@@ -4,6 +4,8 @@
 #
 
 test_description='pack index with 64-bit offsets and object CRC'
+
+TEST_PASSES_SANITIZE_LEAK=true
 . ./test-lib.sh
 
 test_expect_success 'setup' '
-- 
2.39.0.1225.g30a3d88132d


^ permalink raw reply related	[flat|nested] 193+ messages in thread

* [PATCH v4 16/19] grep.c: refactor free_grep_patterns()
  2023-01-17 17:11     ` [PATCH v4 00/19] leak fixes: various simple leak fixes Ævar Arnfjörð Bjarmason
                         ` (14 preceding siblings ...)
  2023-01-17 17:11       ` [PATCH v4 15/19] object-file.c: release the "tag" in check_tag() Ævar Arnfjörð Bjarmason
@ 2023-01-17 17:11       ` Ævar Arnfjörð Bjarmason
  2023-01-17 17:11       ` [PATCH v4 17/19] grep API: plug memory leaks by freeing "header_list" Ævar Arnfjörð Bjarmason
                         ` (3 subsequent siblings)
  19 siblings, 0 replies; 193+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2023-01-17 17:11 UTC (permalink / raw)
  To: git
  Cc: René Scharfe, Junio C Hamano, Eric Sunshine,
	Ævar Arnfjörð Bjarmason

Refactor the free_grep_patterns() function to split out the freeing of
the "struct grep_pat" it contains, right now we're only freeing the
"pattern_list", but we should be freeing another member of the same
type, which we'll do in the subsequent commit.

Let's also replace the "return" if we don't have an
"opt->pattern_expression" with a conditional call of
free_pattern_expr().

Before db84376f981 (grep.c: remove "extended" in favor of
"pattern_expression", fix segfault, 2022-10-11) the pattern here was:

	if (!x)
		return;
	free(y);

But after the cleanup in db84376f981 (which was a narrow segfault fix,
and thus avoided refactoring this) we ended up with:

	if (!x)
		return;
	free(x);

Let's instead do:

	if (x)
		free(x);

This doesn't matter for the subsequent change, but as we're
refactoring this function let's make it easier to reason about, and to
extend in the future, i.e. if we start to free free() members that
come after "pattern_expression" in the "struct grep_opt".

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 grep.c | 14 +++++++++-----
 1 file changed, 9 insertions(+), 5 deletions(-)

diff --git a/grep.c b/grep.c
index 06eed694936..a4450df4559 100644
--- a/grep.c
+++ b/grep.c
@@ -769,11 +769,11 @@ static void free_pattern_expr(struct grep_expr *x)
 	free(x);
 }
 
-void free_grep_patterns(struct grep_opt *opt)
+static void free_grep_pat(struct grep_pat *pattern)
 {
 	struct grep_pat *p, *n;
 
-	for (p = opt->pattern_list; p; p = n) {
+	for (p = pattern; p; p = n) {
 		n = p->next;
 		switch (p->token) {
 		case GREP_PATTERN: /* atom */
@@ -790,10 +790,14 @@ void free_grep_patterns(struct grep_opt *opt)
 		}
 		free(p);
 	}
+}
 
-	if (!opt->pattern_expression)
-		return;
-	free_pattern_expr(opt->pattern_expression);
+void free_grep_patterns(struct grep_opt *opt)
+{
+	free_grep_pat(opt->pattern_list);
+
+	if (opt->pattern_expression)
+		free_pattern_expr(opt->pattern_expression);
 }
 
 static const char *end_of_line(const char *cp, unsigned long *left)
-- 
2.39.0.1225.g30a3d88132d


^ permalink raw reply related	[flat|nested] 193+ messages in thread

* [PATCH v4 17/19] grep API: plug memory leaks by freeing "header_list"
  2023-01-17 17:11     ` [PATCH v4 00/19] leak fixes: various simple leak fixes Ævar Arnfjörð Bjarmason
                         ` (15 preceding siblings ...)
  2023-01-17 17:11       ` [PATCH v4 16/19] grep.c: refactor free_grep_patterns() Ævar Arnfjörð Bjarmason
@ 2023-01-17 17:11       ` Ævar Arnfjörð Bjarmason
  2023-01-17 17:11       ` [PATCH v4 18/19] receive-pack: free() the "ref_name" in "struct command" Ævar Arnfjörð Bjarmason
                         ` (2 subsequent siblings)
  19 siblings, 0 replies; 193+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2023-01-17 17:11 UTC (permalink / raw)
  To: git
  Cc: René Scharfe, Junio C Hamano, Eric Sunshine,
	Ævar Arnfjörð Bjarmason

When the "header_list" struct member was added in [1] it wasn't made
to free the list using loop added for the adjacent "pattern_list"
member, see [2] for when we started freeing it.

This makes e.g. this command leak-free when run on git.git:

	./git -P log -1 --color=always --author=A origin/master

1. 80235ba79ef ("log --author=me --grep=it" should find intersection,
   not union, 2010-01-17)
2. b48fb5b6a95 (grep: free expressions and patterns when done.,
   2006-09-27)

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 grep.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/grep.c b/grep.c
index a4450df4559..c908535e0d8 100644
--- a/grep.c
+++ b/grep.c
@@ -795,6 +795,7 @@ static void free_grep_pat(struct grep_pat *pattern)
 void free_grep_patterns(struct grep_opt *opt)
 {
 	free_grep_pat(opt->pattern_list);
+	free_grep_pat(opt->header_list);
 
 	if (opt->pattern_expression)
 		free_pattern_expr(opt->pattern_expression);
-- 
2.39.0.1225.g30a3d88132d


^ permalink raw reply related	[flat|nested] 193+ messages in thread

* [PATCH v4 18/19] receive-pack: free() the "ref_name" in "struct command"
  2023-01-17 17:11     ` [PATCH v4 00/19] leak fixes: various simple leak fixes Ævar Arnfjörð Bjarmason
                         ` (16 preceding siblings ...)
  2023-01-17 17:11       ` [PATCH v4 17/19] grep API: plug memory leaks by freeing "header_list" Ævar Arnfjörð Bjarmason
@ 2023-01-17 17:11       ` Ævar Arnfjörð Bjarmason
  2023-01-17 17:11       ` [PATCH v4 19/19] push: free_refs() the "local_refs" in set_refspecs() Ævar Arnfjörð Bjarmason
  2023-01-18 12:08       ` [PATCH v5 00/19] leak fixes: various simple leak fixes Ævar Arnfjörð Bjarmason
  19 siblings, 0 replies; 193+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2023-01-17 17:11 UTC (permalink / raw)
  To: git
  Cc: René Scharfe, Junio C Hamano, Eric Sunshine,
	Ævar Arnfjörð Bjarmason

Fix a memory leak that's been with us since this code was introduced
in 575f497456e (Add first cut at "git-receive-pack", 2005-06-29), see
eb1af2df0b1 (git-receive-pack: start parsing ref update commands,
2005-06-29) for the later change that refactored the code to add the
"ref_name" member.

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 builtin/receive-pack.c                 | 10 ++++++++++
 t/t5405-send-pack-rewind.sh            |  1 +
 t/t5406-remote-rejects.sh              |  1 +
 t/t5507-remote-environment.sh          |  2 ++
 t/t5522-pull-symlink.sh                |  1 +
 t/t5527-fetch-odd-refs.sh              |  1 +
 t/t5560-http-backend-noserver.sh       |  1 +
 t/t5561-http-backend.sh                |  1 +
 t/t5562-http-backend-content-length.sh |  2 ++
 t/t5705-session-id-in-capabilities.sh  |  1 +
 10 files changed, 21 insertions(+)

diff --git a/builtin/receive-pack.c b/builtin/receive-pack.c
index a90af303630..451bad776c6 100644
--- a/builtin/receive-pack.c
+++ b/builtin/receive-pack.c
@@ -2032,6 +2032,15 @@ static struct command **queue_command(struct command **tail,
 	return &cmd->next;
 }
 
+static void free_commands(struct command *commands)
+{
+	while (commands) {
+		struct command *next = commands->next;
+		free(commands);
+		commands = next;
+	}
+}
+
 static void queue_commands_from_cert(struct command **tail,
 				     struct strbuf *push_cert)
 {
@@ -2569,6 +2578,7 @@ int cmd_receive_pack(int argc, const char **argv, const char *prefix)
 		run_receive_hook(commands, "post-receive", 1,
 				 &push_options);
 		run_update_post_hook(commands);
+		free_commands(commands);
 		string_list_clear(&push_options, 0);
 		if (auto_gc) {
 			struct child_process proc = CHILD_PROCESS_INIT;
diff --git a/t/t5405-send-pack-rewind.sh b/t/t5405-send-pack-rewind.sh
index 11f03239a06..1686ac13aa6 100755
--- a/t/t5405-send-pack-rewind.sh
+++ b/t/t5405-send-pack-rewind.sh
@@ -5,6 +5,7 @@ test_description='forced push to replace commit we do not have'
 GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
 export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
 
+TEST_PASSES_SANITIZE_LEAK=true
 . ./test-lib.sh
 
 test_expect_success setup '
diff --git a/t/t5406-remote-rejects.sh b/t/t5406-remote-rejects.sh
index dcbeb420827..d6a99466338 100755
--- a/t/t5406-remote-rejects.sh
+++ b/t/t5406-remote-rejects.sh
@@ -2,6 +2,7 @@
 
 test_description='remote push rejects are reported by client'
 
+TEST_PASSES_SANITIZE_LEAK=true
 . ./test-lib.sh
 
 test_expect_success 'setup' '
diff --git a/t/t5507-remote-environment.sh b/t/t5507-remote-environment.sh
index e6149295b18..c6a6957c500 100755
--- a/t/t5507-remote-environment.sh
+++ b/t/t5507-remote-environment.sh
@@ -1,6 +1,8 @@
 #!/bin/sh
 
 test_description='check environment showed to remote side of transports'
+
+TEST_PASSES_SANITIZE_LEAK=true
 . ./test-lib.sh
 
 test_expect_success 'set up "remote" push situation' '
diff --git a/t/t5522-pull-symlink.sh b/t/t5522-pull-symlink.sh
index bcff460d0a2..394bc60cb8e 100755
--- a/t/t5522-pull-symlink.sh
+++ b/t/t5522-pull-symlink.sh
@@ -2,6 +2,7 @@
 
 test_description='pulling from symlinked subdir'
 
+TEST_PASSES_SANITIZE_LEAK=true
 . ./test-lib.sh
 
 # The scenario we are building:
diff --git a/t/t5527-fetch-odd-refs.sh b/t/t5527-fetch-odd-refs.sh
index e2770e4541f..98ece27c6a0 100755
--- a/t/t5527-fetch-odd-refs.sh
+++ b/t/t5527-fetch-odd-refs.sh
@@ -4,6 +4,7 @@ test_description='test fetching of oddly-named refs'
 GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
 export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
 
+TEST_PASSES_SANITIZE_LEAK=true
 . ./test-lib.sh
 
 # afterwards we will have:
diff --git a/t/t5560-http-backend-noserver.sh b/t/t5560-http-backend-noserver.sh
index d30cf4f5b83..f75068de648 100755
--- a/t/t5560-http-backend-noserver.sh
+++ b/t/t5560-http-backend-noserver.sh
@@ -4,6 +4,7 @@ test_description='test git-http-backend-noserver'
 GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
 export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
 
+TEST_PASSES_SANITIZE_LEAK=true
 . ./test-lib.sh
 
 HTTPD_DOCUMENT_ROOT_PATH="$TRASH_DIRECTORY"
diff --git a/t/t5561-http-backend.sh b/t/t5561-http-backend.sh
index 9c57d843152..e1d3b8caed0 100755
--- a/t/t5561-http-backend.sh
+++ b/t/t5561-http-backend.sh
@@ -4,6 +4,7 @@ test_description='test git-http-backend'
 GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
 export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
 
+TEST_PASSES_SANITIZE_LEAK=true
 . ./test-lib.sh
 . "$TEST_DIRECTORY"/lib-httpd.sh
 
diff --git a/t/t5562-http-backend-content-length.sh b/t/t5562-http-backend-content-length.sh
index b68ec22d3fd..7ee9858a78b 100755
--- a/t/t5562-http-backend-content-length.sh
+++ b/t/t5562-http-backend-content-length.sh
@@ -1,6 +1,8 @@
 #!/bin/sh
 
 test_description='test git-http-backend respects CONTENT_LENGTH'
+
+TEST_PASSES_SANITIZE_LEAK=true
 . ./test-lib.sh
 
 test_lazy_prereq GZIP 'gzip --version'
diff --git a/t/t5705-session-id-in-capabilities.sh b/t/t5705-session-id-in-capabilities.sh
index ed38c76c290..b8a722ec27e 100755
--- a/t/t5705-session-id-in-capabilities.sh
+++ b/t/t5705-session-id-in-capabilities.sh
@@ -2,6 +2,7 @@
 
 test_description='session ID in capabilities'
 
+TEST_PASSES_SANITIZE_LEAK=true
 . ./test-lib.sh
 
 REPO="$(pwd)/repo"
-- 
2.39.0.1225.g30a3d88132d


^ permalink raw reply related	[flat|nested] 193+ messages in thread

* [PATCH v4 19/19] push: free_refs() the "local_refs" in set_refspecs()
  2023-01-17 17:11     ` [PATCH v4 00/19] leak fixes: various simple leak fixes Ævar Arnfjörð Bjarmason
                         ` (17 preceding siblings ...)
  2023-01-17 17:11       ` [PATCH v4 18/19] receive-pack: free() the "ref_name" in "struct command" Ævar Arnfjörð Bjarmason
@ 2023-01-17 17:11       ` Ævar Arnfjörð Bjarmason
  2023-01-17 19:58         ` René Scharfe
  2023-01-18 12:08       ` [PATCH v5 00/19] leak fixes: various simple leak fixes Ævar Arnfjörð Bjarmason
  19 siblings, 1 reply; 193+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2023-01-17 17:11 UTC (permalink / raw)
  To: git
  Cc: René Scharfe, Junio C Hamano, Eric Sunshine,
	Ævar Arnfjörð Bjarmason

Fix a memory leak that's been with us since this code was added in
ca02465b413 (push: use remote.$name.push as a refmap, 2013-12-03).

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 builtin/push.c                          | 1 +
 t/t1416-ref-transaction-hooks.sh        | 1 +
 t/t2402-worktree-list.sh                | 1 +
 t/t5504-fetch-receive-strict.sh         | 1 +
 t/t5523-push-upstream.sh                | 1 +
 t/t5529-push-errors.sh                  | 2 ++
 t/t5546-receive-limits.sh               | 2 ++
 t/t5547-push-quarantine.sh              | 2 ++
 t/t5606-clone-options.sh                | 1 +
 t/t5810-proto-disable-local.sh          | 2 ++
 t/t5813-proto-disable-ssh.sh            | 2 ++
 t/t7409-submodule-detached-work-tree.sh | 1 +
 t/t7416-submodule-dash-url.sh           | 2 ++
 t/t7450-bad-git-dotfiles.sh             | 2 ++
 14 files changed, 21 insertions(+)

diff --git a/builtin/push.c b/builtin/push.c
index 60ac8017e52..f48e4c6a856 100644
--- a/builtin/push.c
+++ b/builtin/push.c
@@ -129,6 +129,7 @@ static void set_refspecs(const char **refs, int nr, const char *repo)
 		} else
 			refspec_append(&rs, ref);
 	}
+	free_refs(local_refs);
 }
 
 static int push_url_of_remote(struct remote *remote, const char ***url_p)
diff --git a/t/t1416-ref-transaction-hooks.sh b/t/t1416-ref-transaction-hooks.sh
index 27731722a5b..b32ca798f9f 100755
--- a/t/t1416-ref-transaction-hooks.sh
+++ b/t/t1416-ref-transaction-hooks.sh
@@ -5,6 +5,7 @@ test_description='reference transaction hooks'
 GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
 export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
 
+TEST_PASSES_SANITIZE_LEAK=true
 . ./test-lib.sh
 
 test_expect_success setup '
diff --git a/t/t2402-worktree-list.sh b/t/t2402-worktree-list.sh
index 79e0fce2d90..9ad9be0c208 100755
--- a/t/t2402-worktree-list.sh
+++ b/t/t2402-worktree-list.sh
@@ -5,6 +5,7 @@ test_description='test git worktree list'
 GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
 export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
 
+TEST_PASSES_SANITIZE_LEAK=true
 . ./test-lib.sh
 
 test_expect_success 'setup' '
diff --git a/t/t5504-fetch-receive-strict.sh b/t/t5504-fetch-receive-strict.sh
index ac4099ca893..14e8af1f3b7 100755
--- a/t/t5504-fetch-receive-strict.sh
+++ b/t/t5504-fetch-receive-strict.sh
@@ -4,6 +4,7 @@ test_description='fetch/receive strict mode'
 GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
 export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
 
+TEST_PASSES_SANITIZE_LEAK=true
 . ./test-lib.sh
 
 test_expect_success 'setup and inject "corrupt or missing" object' '
diff --git a/t/t5523-push-upstream.sh b/t/t5523-push-upstream.sh
index fdb42920564..c9acc076353 100755
--- a/t/t5523-push-upstream.sh
+++ b/t/t5523-push-upstream.sh
@@ -4,6 +4,7 @@ test_description='push with --set-upstream'
 GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
 export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
 
+TEST_PASSES_SANITIZE_LEAK=true
 . ./test-lib.sh
 . "$TEST_DIRECTORY"/lib-terminal.sh
 
diff --git a/t/t5529-push-errors.sh b/t/t5529-push-errors.sh
index ce85fd30ad1..0247137cb36 100755
--- a/t/t5529-push-errors.sh
+++ b/t/t5529-push-errors.sh
@@ -1,6 +1,8 @@
 #!/bin/sh
 
 test_description='detect some push errors early (before contacting remote)'
+
+TEST_PASSES_SANITIZE_LEAK=true
 . ./test-lib.sh
 
 test_expect_success 'setup commits' '
diff --git a/t/t5546-receive-limits.sh b/t/t5546-receive-limits.sh
index 0b0e987fdb7..eed3c9d81ab 100755
--- a/t/t5546-receive-limits.sh
+++ b/t/t5546-receive-limits.sh
@@ -1,6 +1,8 @@
 #!/bin/sh
 
 test_description='check receive input limits'
+
+TEST_PASSES_SANITIZE_LEAK=true
 . ./test-lib.sh
 
 # Let's run tests with different unpack limits: 1 and 10000
diff --git a/t/t5547-push-quarantine.sh b/t/t5547-push-quarantine.sh
index 1876fb34e51..9f899b8c7d7 100755
--- a/t/t5547-push-quarantine.sh
+++ b/t/t5547-push-quarantine.sh
@@ -1,6 +1,8 @@
 #!/bin/sh
 
 test_description='check quarantine of objects during push'
+
+TEST_PASSES_SANITIZE_LEAK=true
 . ./test-lib.sh
 
 test_expect_success 'create picky dest repo' '
diff --git a/t/t5606-clone-options.sh b/t/t5606-clone-options.sh
index cf221e92c4d..27f9f776389 100755
--- a/t/t5606-clone-options.sh
+++ b/t/t5606-clone-options.sh
@@ -4,6 +4,7 @@ test_description='basic clone options'
 GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
 export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
 
+TEST_PASSES_SANITIZE_LEAK=true
 . ./test-lib.sh
 
 test_expect_success 'setup' '
diff --git a/t/t5810-proto-disable-local.sh b/t/t5810-proto-disable-local.sh
index c1ef99b85c2..862610256fb 100755
--- a/t/t5810-proto-disable-local.sh
+++ b/t/t5810-proto-disable-local.sh
@@ -1,6 +1,8 @@
 #!/bin/sh
 
 test_description='test disabling of local paths in clone/fetch'
+
+TEST_PASSES_SANITIZE_LEAK=true
 . ./test-lib.sh
 . "$TEST_DIRECTORY/lib-proto-disable.sh"
 
diff --git a/t/t5813-proto-disable-ssh.sh b/t/t5813-proto-disable-ssh.sh
index 3f084ee3065..2e975dc70ec 100755
--- a/t/t5813-proto-disable-ssh.sh
+++ b/t/t5813-proto-disable-ssh.sh
@@ -1,6 +1,8 @@
 #!/bin/sh
 
 test_description='test disabling of git-over-ssh in clone/fetch'
+
+TEST_PASSES_SANITIZE_LEAK=true
 . ./test-lib.sh
 . "$TEST_DIRECTORY/lib-proto-disable.sh"
 
diff --git a/t/t7409-submodule-detached-work-tree.sh b/t/t7409-submodule-detached-work-tree.sh
index 374ed481e9c..574a6fc526e 100755
--- a/t/t7409-submodule-detached-work-tree.sh
+++ b/t/t7409-submodule-detached-work-tree.sh
@@ -13,6 +13,7 @@ TEST_NO_CREATE_REPO=1
 GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
 export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
 
+TEST_PASSES_SANITIZE_LEAK=true
 . ./test-lib.sh
 
 test_expect_success 'setup' '
diff --git a/t/t7416-submodule-dash-url.sh b/t/t7416-submodule-dash-url.sh
index 3ebd9859814..7cf72b9a076 100755
--- a/t/t7416-submodule-dash-url.sh
+++ b/t/t7416-submodule-dash-url.sh
@@ -1,6 +1,8 @@
 #!/bin/sh
 
 test_description='check handling of disallowed .gitmodule urls'
+
+TEST_PASSES_SANITIZE_LEAK=true
 . ./test-lib.sh
 
 test_expect_success 'setup' '
diff --git a/t/t7450-bad-git-dotfiles.sh b/t/t7450-bad-git-dotfiles.sh
index ba1f569bcbb..0d0c3f2c683 100755
--- a/t/t7450-bad-git-dotfiles.sh
+++ b/t/t7450-bad-git-dotfiles.sh
@@ -12,6 +12,8 @@ Such as:
 
   - symlinked .gitmodules, etc
 '
+
+TEST_PASSES_SANITIZE_LEAK=true
 . ./test-lib.sh
 . "$TEST_DIRECTORY"/lib-pack.sh
 
-- 
2.39.0.1225.g30a3d88132d


^ permalink raw reply related	[flat|nested] 193+ messages in thread

* Re: [PATCH v4 15/19] object-file.c: release the "tag" in check_tag()
  2023-01-17 17:11       ` [PATCH v4 15/19] object-file.c: release the "tag" in check_tag() Ævar Arnfjörð Bjarmason
@ 2023-01-17 19:58         ` René Scharfe
  2023-01-18 17:19           ` Jeff King
  0 siblings, 1 reply; 193+ messages in thread
From: René Scharfe @ 2023-01-17 19:58 UTC (permalink / raw)
  To: Ævar Arnfjörð Bjarmason, git; +Cc: Junio C Hamano, Eric Sunshine

Am 17.01.23 um 18:11 schrieb Ævar Arnfjörð Bjarmason:
> Fix a memory leak that's been with us ever since c879daa2372 (Make
> hash-object more robust against malformed objects, 2011-02-05). With
> "HASH_FORMAT_CHECK" (used by "hash-object" and "replace") we'll parse
> tags into a throwaway variable on the stack, but weren't freeing the
> "item->tag" we might malloc() when doing so.
>
> The clearing that release_tag_memory() does for us is redundant here,
> but let's use it as-is anyway. It only has one other existing caller,
> which does need the tag to be cleared.

Calling it is better than getting our hands dirty with tag internals
here.

There's similar leak in check_commit() in the same file, but plugging it
would require exporting unparse_commit().  Or perhaps using the heavy
hammer that is release_commit_memory()?  Anyway, it doesn't seem simple
to me, so that would be a patch for a separate series.

>
> Mark the tests that now pass in their entirety as passing under
> "SANITIZE=leak", which means we'll test them as part of the
> "linux-leaks" CI job.
>
> Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
> ---
>  object-file.c         | 1 +
>  t/t3800-mktag.sh      | 1 +
>  t/t5302-pack-index.sh | 2 ++
>  3 files changed, 4 insertions(+)
>
> diff --git a/object-file.c b/object-file.c
> index 80a0cd3b351..b554266aff4 100644
> --- a/object-file.c
> +++ b/object-file.c
> @@ -2324,6 +2324,7 @@ static void check_tag(const void *buf, size_t size)
>  	memset(&t, 0, sizeof(t));
>  	if (parse_tag_buffer(the_repository, &t, buf, size))
>  		die(_("corrupt tag"));
> +	release_tag_memory(&t);
>  }
>
>  static int index_mem(struct index_state *istate,
> diff --git a/t/t3800-mktag.sh b/t/t3800-mktag.sh
> index e3cf0ffbe59..d3e428ff46e 100755
> --- a/t/t3800-mktag.sh
> +++ b/t/t3800-mktag.sh
> @@ -4,6 +4,7 @@
>
>  test_description='git mktag: tag object verify test'
>
> +TEST_PASSES_SANITIZE_LEAK=true
>  . ./test-lib.sh
>
>  ###########################################################
> diff --git a/t/t5302-pack-index.sh b/t/t5302-pack-index.sh
> index b0095ab41d3..54b11f81c63 100755
> --- a/t/t5302-pack-index.sh
> +++ b/t/t5302-pack-index.sh
> @@ -4,6 +4,8 @@
>  #
>
>  test_description='pack index with 64-bit offsets and object CRC'
> +
> +TEST_PASSES_SANITIZE_LEAK=true
>  . ./test-lib.sh
>
>  test_expect_success 'setup' '

^ permalink raw reply	[flat|nested] 193+ messages in thread

* Re: [PATCH v4 19/19] push: free_refs() the "local_refs" in set_refspecs()
  2023-01-17 17:11       ` [PATCH v4 19/19] push: free_refs() the "local_refs" in set_refspecs() Ævar Arnfjörð Bjarmason
@ 2023-01-17 19:58         ` René Scharfe
  0 siblings, 0 replies; 193+ messages in thread
From: René Scharfe @ 2023-01-17 19:58 UTC (permalink / raw)
  To: Ævar Arnfjörð Bjarmason, git; +Cc: Junio C Hamano, Eric Sunshine

Am 17.01.23 um 18:11 schrieb Ævar Arnfjörð Bjarmason:
> Fix a memory leak that's been with us since this code was added in
> ca02465b413 (push: use remote.$name.push as a refmap, 2013-12-03).
>
> Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
> ---
>  builtin/push.c                          | 1 +
>  t/t1416-ref-transaction-hooks.sh        | 1 +
>  t/t2402-worktree-list.sh                | 1 +
>  t/t5504-fetch-receive-strict.sh         | 1 +
>  t/t5523-push-upstream.sh                | 1 +
>  t/t5529-push-errors.sh                  | 2 ++
>  t/t5546-receive-limits.sh               | 2 ++
>  t/t5547-push-quarantine.sh              | 2 ++
>  t/t5606-clone-options.sh                | 1 +
>  t/t5810-proto-disable-local.sh          | 2 ++
>  t/t5813-proto-disable-ssh.sh            | 2 ++
>  t/t7409-submodule-detached-work-tree.sh | 1 +
>  t/t7416-submodule-dash-url.sh           | 2 ++
>  t/t7450-bad-git-dotfiles.sh             | 2 ++
>  14 files changed, 21 insertions(+)
>
> diff --git a/builtin/push.c b/builtin/push.c
> index 60ac8017e52..f48e4c6a856 100644
> --- a/builtin/push.c
> +++ b/builtin/push.c
> @@ -129,6 +129,7 @@ static void set_refspecs(const char **refs, int nr, const char *repo)
>  		} else
>  			refspec_append(&rs, ref);
>  	}
> +	free_refs(local_refs);

OK.

This can still leak local_refs if remote_get() returns NULL and lazy-
loading is done over and over.  Unlikely to occur in the wild, I bet --
who pushes without a remote?  Does it make sense to also check
local_refs for NULL already in this patch or is it worth its own series?
Not sure.

remote is still leaked if it isn't NULL, though.  We'd need to export
remote_clear() to release it properly, no?  And shouldn't
remotes_remote_get_1() call remote_clear() itself before returning
NULL?  Not simple, separate series.

>  }
>
>  static int push_url_of_remote(struct remote *remote, const char ***url_p)
> diff --git a/t/t1416-ref-transaction-hooks.sh b/t/t1416-ref-transaction-hooks.sh
> index 27731722a5b..b32ca798f9f 100755
> --- a/t/t1416-ref-transaction-hooks.sh
> +++ b/t/t1416-ref-transaction-hooks.sh
> @@ -5,6 +5,7 @@ test_description='reference transaction hooks'
>  GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
>  export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
>
> +TEST_PASSES_SANITIZE_LEAK=true
>  . ./test-lib.sh
>
>  test_expect_success setup '
> diff --git a/t/t2402-worktree-list.sh b/t/t2402-worktree-list.sh
> index 79e0fce2d90..9ad9be0c208 100755
> --- a/t/t2402-worktree-list.sh
> +++ b/t/t2402-worktree-list.sh
> @@ -5,6 +5,7 @@ test_description='test git worktree list'
>  GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
>  export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
>
> +TEST_PASSES_SANITIZE_LEAK=true
>  . ./test-lib.sh
>
>  test_expect_success 'setup' '
> diff --git a/t/t5504-fetch-receive-strict.sh b/t/t5504-fetch-receive-strict.sh
> index ac4099ca893..14e8af1f3b7 100755
> --- a/t/t5504-fetch-receive-strict.sh
> +++ b/t/t5504-fetch-receive-strict.sh
> @@ -4,6 +4,7 @@ test_description='fetch/receive strict mode'
>  GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
>  export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
>
> +TEST_PASSES_SANITIZE_LEAK=true
>  . ./test-lib.sh
>
>  test_expect_success 'setup and inject "corrupt or missing" object' '
> diff --git a/t/t5523-push-upstream.sh b/t/t5523-push-upstream.sh
> index fdb42920564..c9acc076353 100755
> --- a/t/t5523-push-upstream.sh
> +++ b/t/t5523-push-upstream.sh
> @@ -4,6 +4,7 @@ test_description='push with --set-upstream'
>  GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
>  export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
>
> +TEST_PASSES_SANITIZE_LEAK=true
>  . ./test-lib.sh
>  . "$TEST_DIRECTORY"/lib-terminal.sh
>
> diff --git a/t/t5529-push-errors.sh b/t/t5529-push-errors.sh
> index ce85fd30ad1..0247137cb36 100755
> --- a/t/t5529-push-errors.sh
> +++ b/t/t5529-push-errors.sh
> @@ -1,6 +1,8 @@
>  #!/bin/sh
>
>  test_description='detect some push errors early (before contacting remote)'
> +
> +TEST_PASSES_SANITIZE_LEAK=true
>  . ./test-lib.sh
>
>  test_expect_success 'setup commits' '
> diff --git a/t/t5546-receive-limits.sh b/t/t5546-receive-limits.sh
> index 0b0e987fdb7..eed3c9d81ab 100755
> --- a/t/t5546-receive-limits.sh
> +++ b/t/t5546-receive-limits.sh
> @@ -1,6 +1,8 @@
>  #!/bin/sh
>
>  test_description='check receive input limits'
> +
> +TEST_PASSES_SANITIZE_LEAK=true
>  . ./test-lib.sh
>
>  # Let's run tests with different unpack limits: 1 and 10000
> diff --git a/t/t5547-push-quarantine.sh b/t/t5547-push-quarantine.sh
> index 1876fb34e51..9f899b8c7d7 100755
> --- a/t/t5547-push-quarantine.sh
> +++ b/t/t5547-push-quarantine.sh
> @@ -1,6 +1,8 @@
>  #!/bin/sh
>
>  test_description='check quarantine of objects during push'
> +
> +TEST_PASSES_SANITIZE_LEAK=true
>  . ./test-lib.sh
>
>  test_expect_success 'create picky dest repo' '
> diff --git a/t/t5606-clone-options.sh b/t/t5606-clone-options.sh
> index cf221e92c4d..27f9f776389 100755
> --- a/t/t5606-clone-options.sh
> +++ b/t/t5606-clone-options.sh
> @@ -4,6 +4,7 @@ test_description='basic clone options'
>  GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
>  export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
>
> +TEST_PASSES_SANITIZE_LEAK=true
>  . ./test-lib.sh
>
>  test_expect_success 'setup' '
> diff --git a/t/t5810-proto-disable-local.sh b/t/t5810-proto-disable-local.sh
> index c1ef99b85c2..862610256fb 100755
> --- a/t/t5810-proto-disable-local.sh
> +++ b/t/t5810-proto-disable-local.sh
> @@ -1,6 +1,8 @@
>  #!/bin/sh
>
>  test_description='test disabling of local paths in clone/fetch'
> +
> +TEST_PASSES_SANITIZE_LEAK=true
>  . ./test-lib.sh
>  . "$TEST_DIRECTORY/lib-proto-disable.sh"
>
> diff --git a/t/t5813-proto-disable-ssh.sh b/t/t5813-proto-disable-ssh.sh
> index 3f084ee3065..2e975dc70ec 100755
> --- a/t/t5813-proto-disable-ssh.sh
> +++ b/t/t5813-proto-disable-ssh.sh
> @@ -1,6 +1,8 @@
>  #!/bin/sh
>
>  test_description='test disabling of git-over-ssh in clone/fetch'
> +
> +TEST_PASSES_SANITIZE_LEAK=true
>  . ./test-lib.sh
>  . "$TEST_DIRECTORY/lib-proto-disable.sh"
>
> diff --git a/t/t7409-submodule-detached-work-tree.sh b/t/t7409-submodule-detached-work-tree.sh
> index 374ed481e9c..574a6fc526e 100755
> --- a/t/t7409-submodule-detached-work-tree.sh
> +++ b/t/t7409-submodule-detached-work-tree.sh
> @@ -13,6 +13,7 @@ TEST_NO_CREATE_REPO=1
>  GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
>  export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
>
> +TEST_PASSES_SANITIZE_LEAK=true
>  . ./test-lib.sh
>
>  test_expect_success 'setup' '
> diff --git a/t/t7416-submodule-dash-url.sh b/t/t7416-submodule-dash-url.sh
> index 3ebd9859814..7cf72b9a076 100755
> --- a/t/t7416-submodule-dash-url.sh
> +++ b/t/t7416-submodule-dash-url.sh
> @@ -1,6 +1,8 @@
>  #!/bin/sh
>
>  test_description='check handling of disallowed .gitmodule urls'
> +
> +TEST_PASSES_SANITIZE_LEAK=true
>  . ./test-lib.sh
>
>  test_expect_success 'setup' '
> diff --git a/t/t7450-bad-git-dotfiles.sh b/t/t7450-bad-git-dotfiles.sh
> index ba1f569bcbb..0d0c3f2c683 100755
> --- a/t/t7450-bad-git-dotfiles.sh
> +++ b/t/t7450-bad-git-dotfiles.sh
> @@ -12,6 +12,8 @@ Such as:
>
>    - symlinked .gitmodules, etc
>  '
> +
> +TEST_PASSES_SANITIZE_LEAK=true
>  . ./test-lib.sh
>  . "$TEST_DIRECTORY"/lib-pack.sh
>

^ permalink raw reply	[flat|nested] 193+ messages in thread

* Re: [PATCH v4 08/19] worktree: fix a trivial leak in prune_worktrees()
  2023-01-17 17:11       ` [PATCH v4 08/19] worktree: fix a trivial leak in prune_worktrees() Ævar Arnfjörð Bjarmason
@ 2023-01-18  6:28         ` Junio C Hamano
  2023-01-18  7:00           ` [PATCH v4 20/19] branch: the ref_filter is not cleaned Junio C Hamano
  2023-01-18 10:57           ` [PATCH v4 08/19] worktree: fix a trivial leak in prune_worktrees() Ævar Arnfjörð Bjarmason
  0 siblings, 2 replies; 193+ messages in thread
From: Junio C Hamano @ 2023-01-18  6:28 UTC (permalink / raw)
  To: Ævar Arnfjörð Bjarmason
  Cc: git, René Scharfe, Eric Sunshine

Ævar Arnfjörð Bjarmason  <avarab@gmail.com> writes:

> We were leaking both the "struct strbuf" in prune_worktrees(), as well
> as the "path" we got from should_prune_worktree(). Since these were
> the only two uses of the "struct string_list" let's change it to a
> "DUP" and push these to it with "string_list_append_nodup()".
> ...
> diff --git a/t/t3203-branch-output.sh b/t/t3203-branch-output.sh
> index d34d77f8934..ba8d929d189 100755
> --- a/t/t3203-branch-output.sh
> +++ b/t/t3203-branch-output.sh
> @@ -1,6 +1,8 @@
>  #!/bin/sh
>  
>  test_description='git branch display tests'
> +
> +TEST_PASSES_SANITIZE_LEAK=true
>  . ./test-lib.sh
>  . "$TEST_DIRECTORY"/lib-terminal.sh

This is wrong, isn't it?

t3203 uses --points-at, which populates filter.points_at by calling
parse_opt_object_name().  Various members of the ref-filter
structure is never freed (and there is no API helper function in
ref-filter subsystem).

Other tests that use --points-at (e.g. t6302 and t7004) are not
marked with "passes_sanitize_leak", and this one shouldn't be,
either.

With the following squashed in, the branch seems to pass, but I am
not sure which is lessor of the two evils.  From the point of view
of the code maintenance, UNLEAK() to mark this singleton variable is
far cleaner to deal with than selectively running the leak checks
with the "passes_sanitize_leak" mechanism (which always feels like a
losing whack-a-mole hack).

 builtin/branch.c | 1 +
 1 file changed, 1 insertion(+)

diff --git c/builtin/branch.c w/builtin/branch.c
index f63fd45edb..4fe7757670 100644
--- c/builtin/branch.c
+++ w/builtin/branch.c
@@ -742,6 +742,7 @@ int cmd_branch(int argc, const char **argv, const char *prefix)
 	if (filter.abbrev == -1)
 		filter.abbrev = DEFAULT_ABBREV;
 	filter.ignore_case = icase;
+	UNLEAK(filter);
 
 	finalize_colopts(&colopts, -1);
 	if (filter.verbose) {


^ permalink raw reply related	[flat|nested] 193+ messages in thread

* [PATCH v4 20/19] branch: the ref_filter is not cleaned
  2023-01-18  6:28         ` Junio C Hamano
@ 2023-01-18  7:00           ` Junio C Hamano
  2023-01-18 10:57           ` [PATCH v4 08/19] worktree: fix a trivial leak in prune_worktrees() Ævar Arnfjörð Bjarmason
  1 sibling, 0 replies; 193+ messages in thread
From: Junio C Hamano @ 2023-01-18  7:00 UTC (permalink / raw)
  To: Ævar Arnfjörð Bjarmason
  Cc: git, René Scharfe, Eric Sunshine

Recently, a test that uses "branch --point-at" was marked
(incorrectly) as passing the leak tests, but it was premature.

As there is no API support to release the resource held by the
ref_filter structure when we are done, let's mark the singleton
instance that does not grow unbounded as such with UNLEAK() to
squelch pointless leak checker errors.

Signed-off-by: Junio C Hamano <gitster@pobox.com>
---
 builtin/branch.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/builtin/branch.c b/builtin/branch.c
index f63fd45edb..4fe7757670 100644
--- a/builtin/branch.c
+++ b/builtin/branch.c
@@ -742,6 +742,7 @@ int cmd_branch(int argc, const char **argv, const char *prefix)
 	if (filter.abbrev == -1)
 		filter.abbrev = DEFAULT_ABBREV;
 	filter.ignore_case = icase;
+	UNLEAK(filter);
 
 	finalize_colopts(&colopts, -1);
 	if (filter.verbose) {
-- 
2.39.1-231-ga7caae2729


^ permalink raw reply related	[flat|nested] 193+ messages in thread

* Re: [PATCH v4 08/19] worktree: fix a trivial leak in prune_worktrees()
  2023-01-18  6:28         ` Junio C Hamano
  2023-01-18  7:00           ` [PATCH v4 20/19] branch: the ref_filter is not cleaned Junio C Hamano
@ 2023-01-18 10:57           ` Ævar Arnfjörð Bjarmason
  2023-01-18 16:16             ` Junio C Hamano
  1 sibling, 1 reply; 193+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2023-01-18 10:57 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: git, René Scharfe, Eric Sunshine


On Tue, Jan 17 2023, Junio C Hamano wrote:

> Ævar Arnfjörð Bjarmason  <avarab@gmail.com> writes:
>
>> We were leaking both the "struct strbuf" in prune_worktrees(), as well
>> as the "path" we got from should_prune_worktree(). Since these were
>> the only two uses of the "struct string_list" let's change it to a
>> "DUP" and push these to it with "string_list_append_nodup()".
>> ...
>> diff --git a/t/t3203-branch-output.sh b/t/t3203-branch-output.sh
>> index d34d77f8934..ba8d929d189 100755
>> --- a/t/t3203-branch-output.sh
>> +++ b/t/t3203-branch-output.sh
>> @@ -1,6 +1,8 @@
>>  #!/bin/sh
>>  
>>  test_description='git branch display tests'
>> +
>> +TEST_PASSES_SANITIZE_LEAK=true
>>  . ./test-lib.sh
>>  . "$TEST_DIRECTORY"/lib-terminal.sh
>
> This is wrong, isn't it?
>
> t3203 uses --points-at, which populates filter.points_at by calling
> parse_opt_object_name().  Various members of the ref-filter
> structure is never freed (and there is no API helper function in
> ref-filter subsystem).
>
> Other tests that use --points-at (e.g. t6302 and t7004) are not
> marked with "passes_sanitize_leak", and this one shouldn't be,
> either.
>
> With the following squashed in, the branch seems to pass, but I am
> not sure which is lessor of the two evils.  From the point of view
> of the code maintenance, UNLEAK() to mark this singleton variable is
> far cleaner to deal with than selectively running the leak checks
> with the "passes_sanitize_leak" mechanism (which always feels like a
> losing whack-a-mole hack).
>
>  builtin/branch.c | 1 +
>  1 file changed, 1 insertion(+)
>
> diff --git c/builtin/branch.c w/builtin/branch.c
> index f63fd45edb..4fe7757670 100644
> --- c/builtin/branch.c
> +++ w/builtin/branch.c
> @@ -742,6 +742,7 @@ int cmd_branch(int argc, const char **argv, const char *prefix)
>  	if (filter.abbrev == -1)
>  		filter.abbrev = DEFAULT_ABBREV;
>  	filter.ignore_case = icase;
> +	UNLEAK(filter);
>  
>  	finalize_colopts(&colopts, -1);
>  	if (filter.verbose) {

I'll send a v5 re-roll without this change, sorry.

This is a case where the version of GCC I was testing with doesn't
report the leak, but clang does (and probably other versions of GCC),
sorry.

^ permalink raw reply	[flat|nested] 193+ messages in thread

* [PATCH v5 00/19] leak fixes: various simple leak fixes
  2023-01-17 17:11     ` [PATCH v4 00/19] leak fixes: various simple leak fixes Ævar Arnfjörð Bjarmason
                         ` (18 preceding siblings ...)
  2023-01-17 17:11       ` [PATCH v4 19/19] push: free_refs() the "local_refs" in set_refspecs() Ævar Arnfjörð Bjarmason
@ 2023-01-18 12:08       ` Ævar Arnfjörð Bjarmason
  2023-01-18 12:08         ` [PATCH v5 01/19] tests: mark tests as passing with SANITIZE=leak Ævar Arnfjörð Bjarmason
                           ` (19 more replies)
  19 siblings, 20 replies; 193+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2023-01-18 12:08 UTC (permalink / raw)
  To: git
  Cc: René Scharfe, Junio C Hamano, Eric Sunshine,
	Ævar Arnfjörð Bjarmason

See
https://lore.kernel.org/git/cover-v4-00.19-00000000000-20230117T151201Z-avarab@gmail.com/
for the v4. Change since then:

* Don't mark t/t3203-branch-output.sh as passing, which was new in
  v4. As noted in
  https://lore.kernel.org/git/xmqq1qns8gz4.fsf_-_@gitster.g/ it still
  leaked.

  As I noted in
  https://lore.kernel.org/git/230118.86o7qwxg4e.gmgdl@evledraar.gmail.com/
  this was a gcc v.s. clang difference.

  I a fix for that "filter" leak as a follow-up, let's just fix it for
  real at some point, rather than using the UNLEAK(), sorry about the
  churn.

* The couple of things René pointed out on v4 I both took (and he
  seems to think so) as suggestions for eventual follow-ups.

  In general I agree that some of the fixes here have deeper
  root-cause fixes that are worth doing at some point, but in the
  meantime having some simple leak fixes (and CI regression testing
  for them) is an improvement.

Ævar Arnfjörð Bjarmason (19):
  tests: mark tests as passing with SANITIZE=leak
  bundle.c: don't leak the "args" in the "struct child_process"
  commit-graph: use free_commit_graph() instead of UNLEAK()
  clone: use free() instead of UNLEAK()
  various: add missing clear_pathspec(), fix leaks
  name-rev: don't xstrdup() an already dup'd string
  repack: fix leaks on error with "goto cleanup"
  worktree: fix a trivial leak in prune_worktrees()
  http-backend.c: fix "dir" and "cmd_arg" leaks in cmd_main()
  http-backend.c: fix cmd_main() memory leak, refactor reg{exec,free}()
  commit-graph: fix a parse_options_concat() leak
  show-branch: free() allocated "head" before return
  builtin/merge.c: use fixed strings, not "strbuf", fix leak
  builtin/merge.c: free "&buf" on "Your local changes..." error
  object-file.c: release the "tag" in check_tag()
  grep.c: refactor free_grep_patterns()
  grep API: plug memory leaks by freeing "header_list"
  receive-pack: free() the "ref_name" in "struct command"
  push: free_refs() the "local_refs" in set_refspecs()

 archive.c                                  |  1 +
 builtin/clean.c                            |  1 +
 builtin/clone.c                            |  5 +++--
 builtin/commit-graph.c                     | 10 ++++++----
 builtin/merge.c                            | 14 ++++++-------
 builtin/name-rev.c                         | 23 ++++++++++------------
 builtin/push.c                             |  1 +
 builtin/receive-pack.c                     | 10 ++++++++++
 builtin/repack.c                           | 13 ++++++------
 builtin/reset.c                            | 11 ++++++++---
 builtin/show-branch.c                      |  1 +
 builtin/stash.c                            |  7 +++++--
 builtin/worktree.c                         |  6 +++---
 bundle.c                                   |  6 ++++--
 grep.c                                     | 15 +++++++++-----
 http-backend.c                             |  9 +++++++--
 object-file.c                              |  1 +
 t/t0023-crlf-am.sh                         |  1 +
 t/t1301-shared-repo.sh                     |  1 +
 t/t1302-repo-version.sh                    |  1 +
 t/t1304-default-acl.sh                     |  1 +
 t/t1408-packed-refs.sh                     |  1 +
 t/t1410-reflog.sh                          |  1 +
 t/t1416-ref-transaction-hooks.sh           |  1 +
 t/t2401-worktree-prune.sh                  |  1 +
 t/t2402-worktree-list.sh                   |  1 +
 t/t2406-worktree-repair.sh                 |  1 +
 t/t3210-pack-refs.sh                       |  1 +
 t/t3800-mktag.sh                           |  1 +
 t/t4152-am-subjects.sh                     |  2 ++
 t/t4254-am-corrupt.sh                      |  2 ++
 t/t4256-am-format-flowed.sh                |  1 +
 t/t4257-am-interactive.sh                  |  2 ++
 t/t5001-archive-attr.sh                    |  1 +
 t/t5004-archive-corner-cases.sh            |  2 ++
 t/t5302-pack-index.sh                      |  2 ++
 t/t5317-pack-objects-filter-objects.sh     |  1 +
 t/t5330-no-lazy-fetch-with-commit-graph.sh |  1 +
 t/t5403-post-checkout-hook.sh              |  1 +
 t/t5405-send-pack-rewind.sh                |  1 +
 t/t5406-remote-rejects.sh                  |  1 +
 t/t5502-quickfetch.sh                      |  1 +
 t/t5504-fetch-receive-strict.sh            |  1 +
 t/t5507-remote-environment.sh              |  2 ++
 t/t5522-pull-symlink.sh                    |  1 +
 t/t5523-push-upstream.sh                   |  1 +
 t/t5527-fetch-odd-refs.sh                  |  1 +
 t/t5529-push-errors.sh                     |  2 ++
 t/t5546-receive-limits.sh                  |  2 ++
 t/t5547-push-quarantine.sh                 |  2 ++
 t/t5560-http-backend-noserver.sh           |  1 +
 t/t5561-http-backend.sh                    |  1 +
 t/t5562-http-backend-content-length.sh     |  2 ++
 t/t5604-clone-reference.sh                 |  1 +
 t/t5606-clone-options.sh                   |  1 +
 t/t5613-info-alternate.sh                  |  2 ++
 t/t5705-session-id-in-capabilities.sh      |  1 +
 t/t5810-proto-disable-local.sh             |  2 ++
 t/t5813-proto-disable-ssh.sh               |  2 ++
 t/t6011-rev-list-with-bad-commit.sh        |  1 +
 t/t6014-rev-list-all.sh                    |  1 +
 t/t6021-rev-list-exclude-hidden.sh         |  1 +
 t/t6439-merge-co-error-msgs.sh             |  1 +
 t/t7105-reset-patch.sh                     |  2 ++
 t/t7106-reset-unborn-branch.sh             |  2 ++
 t/t7107-reset-pathspec-file.sh             |  1 +
 t/t7301-clean-interactive.sh               |  1 +
 t/t7403-submodule-sync.sh                  |  1 +
 t/t7409-submodule-detached-work-tree.sh    |  1 +
 t/t7416-submodule-dash-url.sh              |  2 ++
 t/t7450-bad-git-dotfiles.sh                |  2 ++
 t/t7701-repack-unpack-unreachable.sh       |  1 +
 72 files changed, 156 insertions(+), 50 deletions(-)

Range-diff against v4:
 1:  2ed69e3cda3 =  1:  c47fc0fb637 tests: mark tests as passing with SANITIZE=leak
 2:  9993786ba0d =  2:  9eb758117dc bundle.c: don't leak the "args" in the "struct child_process"
 3:  8e98d7c4ebf =  3:  01b6229f18a commit-graph: use free_commit_graph() instead of UNLEAK()
 4:  966d7657d54 =  4:  f4f3aef2861 clone: use free() instead of UNLEAK()
 5:  93a8f8fa1b9 =  5:  8d10fbe0b8f various: add missing clear_pathspec(), fix leaks
 6:  bd15d991ac7 =  6:  eb5dc3ac192 name-rev: don't xstrdup() an already dup'd string
 7:  fd890121ebe =  7:  1fac90c306a repack: fix leaks on error with "goto cleanup"
 8:  1fe25bc6981 !  8:  02248aca3eb worktree: fix a trivial leak in prune_worktrees()
    @@ t/t2406-worktree-repair.sh
      . ./test-lib.sh
      
      test_expect_success setup '
    -
    - ## t/t3203-branch-output.sh ##
    -@@
    - #!/bin/sh
    - 
    - test_description='git branch display tests'
    -+
    -+TEST_PASSES_SANITIZE_LEAK=true
    - . ./test-lib.sh
    - . "$TEST_DIRECTORY"/lib-terminal.sh
    - 
 9:  6b3dd9b15f0 =  9:  b39d6d29dd5 http-backend.c: fix "dir" and "cmd_arg" leaks in cmd_main()
10:  246f71bb447 = 10:  928dea2d4ee http-backend.c: fix cmd_main() memory leak, refactor reg{exec,free}()
11:  ab31d8d10da = 11:  5770b9eb764 commit-graph: fix a parse_options_concat() leak
12:  9054b353220 = 12:  3ff86cb808c show-branch: free() allocated "head" before return
13:  05836b08e0f = 13:  1f3e3524580 builtin/merge.c: use fixed strings, not "strbuf", fix leak
14:  e8ea18b08c2 = 14:  15e4b8db805 builtin/merge.c: free "&buf" on "Your local changes..." error
15:  66c24afb893 = 15:  d36ad1f818a object-file.c: release the "tag" in check_tag()
16:  52744d9690f = 16:  10959760dfc grep.c: refactor free_grep_patterns()
17:  8ff63d9095c = 17:  6a8f4a567aa grep API: plug memory leaks by freeing "header_list"
18:  0ad7d59b881 = 18:  3c3d48df04b receive-pack: free() the "ref_name" in "struct command"
19:  b3aee41d0b4 = 19:  f29500a4abc push: free_refs() the "local_refs" in set_refspecs()
-- 
2.39.0.1225.g30a3d88132d


^ permalink raw reply	[flat|nested] 193+ messages in thread

* [PATCH v5 01/19] tests: mark tests as passing with SANITIZE=leak
  2023-01-18 12:08       ` [PATCH v5 00/19] leak fixes: various simple leak fixes Ævar Arnfjörð Bjarmason
@ 2023-01-18 12:08         ` Ævar Arnfjörð Bjarmason
  2023-01-18 12:08         ` [PATCH v5 02/19] bundle.c: don't leak the "args" in the "struct child_process" Ævar Arnfjörð Bjarmason
                           ` (18 subsequent siblings)
  19 siblings, 0 replies; 193+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2023-01-18 12:08 UTC (permalink / raw)
  To: git
  Cc: René Scharfe, Junio C Hamano, Eric Sunshine,
	Ævar Arnfjörð Bjarmason

When the "ab/various-leak-fixes" topic was merged in [1] only t6021
would fail if the tests were run in the
"GIT_TEST_PASSING_SANITIZE_LEAK=check" mode, i.e. to check whether we
marked all leak-free tests with "TEST_PASSES_SANITIZE_LEAK=true".

Since then we've had various tests starting to pass under
SANITIZE=leak. Let's mark those as passing, this is when they started
to pass, narrowed down with "git bisect":

- t5317-pack-objects-filter-objects.sh: In
  faebba436e6 (list-objects-filter: plug pattern_list leak, 2022-12-01).

- t3210-pack-refs.sh, t5613-info-alternate.sh,
  t7403-submodule-sync.sh: In 189e97bc4ba (diff: remove parseopts member
  from struct diff_options, 2022-12-01).

- t1408-packed-refs.sh: In ab91f6b7c42 (Merge branch
  'rs/diff-parseopts', 2022-12-19).

- t0023-crlf-am.sh, t4152-am-subjects.sh, t4254-am-corrupt.sh,
  t4256-am-format-flowed.sh, t4257-am-interactive.sh,
  t5403-post-checkout-hook.sh: In a658e881c13 (am: don't pass strvec to
  apply_parse_options(), 2022-12-13)

- t1301-shared-repo.sh, t1302-repo-version.sh: In b07a819c05f (reflog:
  clear leftovers in reflog_expiry_cleanup(), 2022-12-13).

- t1304-default-acl.sh, t1410-reflog.sh,
  t5330-no-lazy-fetch-with-commit-graph.sh, t5502-quickfetch.sh,
  t5604-clone-reference.sh, t6014-rev-list-all.sh,
  t7701-repack-unpack-unreachable.sh: In b0c61be3209 (Merge branch
  'rs/reflog-expiry-cleanup', 2022-12-26)

1. 9ea1378d046 (Merge branch 'ab/various-leak-fixes', 2022-12-14)

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 t/t0023-crlf-am.sh                         | 1 +
 t/t1301-shared-repo.sh                     | 1 +
 t/t1302-repo-version.sh                    | 1 +
 t/t1304-default-acl.sh                     | 1 +
 t/t1408-packed-refs.sh                     | 1 +
 t/t1410-reflog.sh                          | 1 +
 t/t3210-pack-refs.sh                       | 1 +
 t/t4152-am-subjects.sh                     | 2 ++
 t/t4254-am-corrupt.sh                      | 2 ++
 t/t4256-am-format-flowed.sh                | 1 +
 t/t4257-am-interactive.sh                  | 2 ++
 t/t5317-pack-objects-filter-objects.sh     | 1 +
 t/t5330-no-lazy-fetch-with-commit-graph.sh | 1 +
 t/t5403-post-checkout-hook.sh              | 1 +
 t/t5502-quickfetch.sh                      | 1 +
 t/t5604-clone-reference.sh                 | 1 +
 t/t5613-info-alternate.sh                  | 2 ++
 t/t6014-rev-list-all.sh                    | 1 +
 t/t6021-rev-list-exclude-hidden.sh         | 1 +
 t/t7403-submodule-sync.sh                  | 1 +
 t/t7701-repack-unpack-unreachable.sh       | 1 +
 21 files changed, 25 insertions(+)

diff --git a/t/t0023-crlf-am.sh b/t/t0023-crlf-am.sh
index f9bbb91f64e..575805513a3 100755
--- a/t/t0023-crlf-am.sh
+++ b/t/t0023-crlf-am.sh
@@ -2,6 +2,7 @@
 
 test_description='Test am with auto.crlf'
 
+TEST_PASSES_SANITIZE_LEAK=true
 . ./test-lib.sh
 
 cat >patchfile <<\EOF
diff --git a/t/t1301-shared-repo.sh b/t/t1301-shared-repo.sh
index 93a2f91f8a5..a1251f65100 100755
--- a/t/t1301-shared-repo.sh
+++ b/t/t1301-shared-repo.sh
@@ -8,6 +8,7 @@ test_description='Test shared repository initialization'
 GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
 export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
 
+TEST_PASSES_SANITIZE_LEAK=true
 . ./test-lib.sh
 
 # Remove a default ACL from the test dir if possible.
diff --git a/t/t1302-repo-version.sh b/t/t1302-repo-version.sh
index 7cf80bf66a6..70389fa2ebb 100755
--- a/t/t1302-repo-version.sh
+++ b/t/t1302-repo-version.sh
@@ -5,6 +5,7 @@
 
 test_description='Test repository version check'
 
+TEST_PASSES_SANITIZE_LEAK=true
 . ./test-lib.sh
 
 test_expect_success 'setup' '
diff --git a/t/t1304-default-acl.sh b/t/t1304-default-acl.sh
index c69ae41306c..31b89dd9693 100755
--- a/t/t1304-default-acl.sh
+++ b/t/t1304-default-acl.sh
@@ -9,6 +9,7 @@ test_description='Test repository with default ACL'
 # => this must come before . ./test-lib.sh
 umask 077
 
+TEST_PASSES_SANITIZE_LEAK=true
 . ./test-lib.sh
 
 # We need an arbitrary other user give permission to using ACLs. root
diff --git a/t/t1408-packed-refs.sh b/t/t1408-packed-refs.sh
index 41ba1f1d7fc..9469c79a585 100755
--- a/t/t1408-packed-refs.sh
+++ b/t/t1408-packed-refs.sh
@@ -5,6 +5,7 @@ test_description='packed-refs entries are covered by loose refs'
 GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
 export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
 
+TEST_PASSES_SANITIZE_LEAK=true
 . ./test-lib.sh
 
 test_expect_success setup '
diff --git a/t/t1410-reflog.sh b/t/t1410-reflog.sh
index aa59954f6c5..6c45965b1e4 100755
--- a/t/t1410-reflog.sh
+++ b/t/t1410-reflog.sh
@@ -7,6 +7,7 @@ test_description='Test prune and reflog expiration'
 GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
 export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
 
+TEST_PASSES_SANITIZE_LEAK=true
 . ./test-lib.sh
 
 check_have () {
diff --git a/t/t3210-pack-refs.sh b/t/t3210-pack-refs.sh
index 577f32dc71f..07a0ff93def 100755
--- a/t/t3210-pack-refs.sh
+++ b/t/t3210-pack-refs.sh
@@ -12,6 +12,7 @@ semantic is still the same.
 GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
 export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
 
+TEST_PASSES_SANITIZE_LEAK=true
 . ./test-lib.sh
 
 test_expect_success 'enable reflogs' '
diff --git a/t/t4152-am-subjects.sh b/t/t4152-am-subjects.sh
index 4c68245acad..9f2edba1f83 100755
--- a/t/t4152-am-subjects.sh
+++ b/t/t4152-am-subjects.sh
@@ -1,6 +1,8 @@
 #!/bin/sh
 
 test_description='test subject preservation with format-patch | am'
+
+TEST_PASSES_SANITIZE_LEAK=true
 . ./test-lib.sh
 
 make_patches() {
diff --git a/t/t4254-am-corrupt.sh b/t/t4254-am-corrupt.sh
index 54be7da1611..45f1d4f95e5 100755
--- a/t/t4254-am-corrupt.sh
+++ b/t/t4254-am-corrupt.sh
@@ -1,6 +1,8 @@
 #!/bin/sh
 
 test_description='git am with corrupt input'
+
+TEST_PASSES_SANITIZE_LEAK=true
 . ./test-lib.sh
 
 make_mbox_with_nul () {
diff --git a/t/t4256-am-format-flowed.sh b/t/t4256-am-format-flowed.sh
index 2369c4e17ad..1015273bc82 100755
--- a/t/t4256-am-format-flowed.sh
+++ b/t/t4256-am-format-flowed.sh
@@ -2,6 +2,7 @@
 
 test_description='test format=flowed support of git am'
 
+TEST_PASSES_SANITIZE_LEAK=true
 . ./test-lib.sh
 
 test_expect_success 'setup' '
diff --git a/t/t4257-am-interactive.sh b/t/t4257-am-interactive.sh
index aed8f4de3d6..f26d7fd2dbd 100755
--- a/t/t4257-am-interactive.sh
+++ b/t/t4257-am-interactive.sh
@@ -1,6 +1,8 @@
 #!/bin/sh
 
 test_description='am --interactive tests'
+
+TEST_PASSES_SANITIZE_LEAK=true
 . ./test-lib.sh
 
 test_expect_success 'set up patches to apply' '
diff --git a/t/t5317-pack-objects-filter-objects.sh b/t/t5317-pack-objects-filter-objects.sh
index 5b707d911b5..b26d476c646 100755
--- a/t/t5317-pack-objects-filter-objects.sh
+++ b/t/t5317-pack-objects-filter-objects.sh
@@ -5,6 +5,7 @@ test_description='git pack-objects using object filtering'
 GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
 export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
 
+TEST_PASSES_SANITIZE_LEAK=true
 . ./test-lib.sh
 
 # Test blob:none filter.
diff --git a/t/t5330-no-lazy-fetch-with-commit-graph.sh b/t/t5330-no-lazy-fetch-with-commit-graph.sh
index 2cc7fd7a476..5eb28f0512d 100755
--- a/t/t5330-no-lazy-fetch-with-commit-graph.sh
+++ b/t/t5330-no-lazy-fetch-with-commit-graph.sh
@@ -2,6 +2,7 @@
 
 test_description='test for no lazy fetch with the commit-graph'
 
+TEST_PASSES_SANITIZE_LEAK=true
 . ./test-lib.sh
 
 test_expect_success 'setup: prepare a repository with a commit' '
diff --git a/t/t5403-post-checkout-hook.sh b/t/t5403-post-checkout-hook.sh
index 978f240cdac..cfaae547398 100755
--- a/t/t5403-post-checkout-hook.sh
+++ b/t/t5403-post-checkout-hook.sh
@@ -7,6 +7,7 @@ test_description='Test the post-checkout hook.'
 GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
 export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
 
+TEST_PASSES_SANITIZE_LEAK=true
 . ./test-lib.sh
 
 test_expect_success setup '
diff --git a/t/t5502-quickfetch.sh b/t/t5502-quickfetch.sh
index b160f8b7fb7..7b3ff21b984 100755
--- a/t/t5502-quickfetch.sh
+++ b/t/t5502-quickfetch.sh
@@ -5,6 +5,7 @@ test_description='test quickfetch from local'
 GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
 export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
 
+TEST_PASSES_SANITIZE_LEAK=true
 . ./test-lib.sh
 
 test_expect_success setup '
diff --git a/t/t5604-clone-reference.sh b/t/t5604-clone-reference.sh
index 2734e37e880..dc86dea1333 100755
--- a/t/t5604-clone-reference.sh
+++ b/t/t5604-clone-reference.sh
@@ -7,6 +7,7 @@ test_description='test clone --reference'
 GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
 export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
 
+TEST_PASSES_SANITIZE_LEAK=true
 . ./test-lib.sh
 
 base_dir=$(pwd)
diff --git a/t/t5613-info-alternate.sh b/t/t5613-info-alternate.sh
index 895f46bb911..7708cbafa98 100755
--- a/t/t5613-info-alternate.sh
+++ b/t/t5613-info-alternate.sh
@@ -4,6 +4,8 @@
 #
 
 test_description='test transitive info/alternate entries'
+
+TEST_PASSES_SANITIZE_LEAK=true
 . ./test-lib.sh
 
 test_expect_success 'preparing first repository' '
diff --git a/t/t6014-rev-list-all.sh b/t/t6014-rev-list-all.sh
index c9bedd29cba..16b8bd1d090 100755
--- a/t/t6014-rev-list-all.sh
+++ b/t/t6014-rev-list-all.sh
@@ -2,6 +2,7 @@
 
 test_description='--all includes detached HEADs'
 
+TEST_PASSES_SANITIZE_LEAK=true
 . ./test-lib.sh
 
 
diff --git a/t/t6021-rev-list-exclude-hidden.sh b/t/t6021-rev-list-exclude-hidden.sh
index 32b2b094138..11c50b7c0dd 100755
--- a/t/t6021-rev-list-exclude-hidden.sh
+++ b/t/t6021-rev-list-exclude-hidden.sh
@@ -2,6 +2,7 @@
 
 test_description='git rev-list --exclude-hidden test'
 
+TEST_PASSES_SANITIZE_LEAK=true
 . ./test-lib.sh
 
 test_expect_success 'setup' '
diff --git a/t/t7403-submodule-sync.sh b/t/t7403-submodule-sync.sh
index ea92ef52a5e..ff09443a0a4 100755
--- a/t/t7403-submodule-sync.sh
+++ b/t/t7403-submodule-sync.sh
@@ -11,6 +11,7 @@ These tests exercise the "git submodule sync" subcommand.
 GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
 export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
 
+TEST_PASSES_SANITIZE_LEAK=true
 . ./test-lib.sh
 
 test_expect_success setup '
diff --git a/t/t7701-repack-unpack-unreachable.sh b/t/t7701-repack-unpack-unreachable.sh
index b7ac4f598a8..ebb267855fe 100755
--- a/t/t7701-repack-unpack-unreachable.sh
+++ b/t/t7701-repack-unpack-unreachable.sh
@@ -5,6 +5,7 @@ test_description='git repack works correctly'
 GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
 export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
 
+TEST_PASSES_SANITIZE_LEAK=true
 . ./test-lib.sh
 
 fsha1=
-- 
2.39.0.1225.g30a3d88132d


^ permalink raw reply related	[flat|nested] 193+ messages in thread

* [PATCH v5 02/19] bundle.c: don't leak the "args" in the "struct child_process"
  2023-01-18 12:08       ` [PATCH v5 00/19] leak fixes: various simple leak fixes Ævar Arnfjörð Bjarmason
  2023-01-18 12:08         ` [PATCH v5 01/19] tests: mark tests as passing with SANITIZE=leak Ævar Arnfjörð Bjarmason
@ 2023-01-18 12:08         ` Ævar Arnfjörð Bjarmason
  2023-01-26  1:38           ` Elijah Newren
  2023-01-18 12:08         ` [PATCH v5 03/19] commit-graph: use free_commit_graph() instead of UNLEAK() Ævar Arnfjörð Bjarmason
                           ` (17 subsequent siblings)
  19 siblings, 1 reply; 193+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2023-01-18 12:08 UTC (permalink / raw)
  To: git
  Cc: René Scharfe, Junio C Hamano, Eric Sunshine,
	Ævar Arnfjörð Bjarmason

Fix a leak that's been here since 7366096de9d (bundle API: change
"flags" to be "extra_index_pack_args", 2021-09-05), if can't verify
the bundle we didn't call child_process_clear() to clear the "args".

But rather than doing that let's verify the bundle before we start
preparing the process we're going to spawn, if we get an error we
don't need to push anything to the "args".

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 bundle.c | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/bundle.c b/bundle.c
index 4ef7256aa11..9ebb10a8f72 100644
--- a/bundle.c
+++ b/bundle.c
@@ -627,6 +627,10 @@ int unbundle(struct repository *r, struct bundle_header *header,
 	     enum verify_bundle_flags flags)
 {
 	struct child_process ip = CHILD_PROCESS_INIT;
+
+	if (verify_bundle(r, header, flags))
+		return -1;
+
 	strvec_pushl(&ip.args, "index-pack", "--fix-thin", "--stdin", NULL);
 
 	/* If there is a filter, then we need to create the promisor pack. */
@@ -638,8 +642,6 @@ int unbundle(struct repository *r, struct bundle_header *header,
 		strvec_clear(extra_index_pack_args);
 	}
 
-	if (verify_bundle(r, header, flags))
-		return -1;
 	ip.in = bundle_fd;
 	ip.no_stdout = 1;
 	ip.git_cmd = 1;
-- 
2.39.0.1225.g30a3d88132d


^ permalink raw reply related	[flat|nested] 193+ messages in thread

* [PATCH v5 03/19] commit-graph: use free_commit_graph() instead of UNLEAK()
  2023-01-18 12:08       ` [PATCH v5 00/19] leak fixes: various simple leak fixes Ævar Arnfjörð Bjarmason
  2023-01-18 12:08         ` [PATCH v5 01/19] tests: mark tests as passing with SANITIZE=leak Ævar Arnfjörð Bjarmason
  2023-01-18 12:08         ` [PATCH v5 02/19] bundle.c: don't leak the "args" in the "struct child_process" Ævar Arnfjörð Bjarmason
@ 2023-01-18 12:08         ` Ævar Arnfjörð Bjarmason
  2023-01-18 12:08         ` [PATCH v5 04/19] clone: use free() " Ævar Arnfjörð Bjarmason
                           ` (16 subsequent siblings)
  19 siblings, 0 replies; 193+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2023-01-18 12:08 UTC (permalink / raw)
  To: git
  Cc: René Scharfe, Junio C Hamano, Eric Sunshine,
	Ævar Arnfjörð Bjarmason

In 0bfb48e6723 (builtin/commit-graph.c: UNLEAK variables, 2018-10-03)
this was made to UNLEAK(), but we can just as easily invoke the
free_commit_graph() function added in c3756d5b7fc (commit-graph: add
free_commit_graph, 2018-07-11) instead.

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 builtin/commit-graph.c | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/builtin/commit-graph.c b/builtin/commit-graph.c
index e8f77f535f3..0102ac8540e 100644
--- a/builtin/commit-graph.c
+++ b/builtin/commit-graph.c
@@ -67,6 +67,7 @@ static int graph_verify(int argc, const char **argv, const char *prefix)
 	int fd;
 	struct stat st;
 	int flags = 0;
+	int ret;
 
 	static struct option builtin_commit_graph_verify_options[] = {
 		OPT_BOOL(0, "shallow", &opts.shallow,
@@ -111,8 +112,9 @@ static int graph_verify(int argc, const char **argv, const char *prefix)
 	if (!graph)
 		return !!open_ok;
 
-	UNLEAK(graph);
-	return verify_commit_graph(the_repository, graph, flags);
+	ret = verify_commit_graph(the_repository, graph, flags);
+	free_commit_graph(graph);
+	return ret;
 }
 
 extern int read_replace_refs;
-- 
2.39.0.1225.g30a3d88132d


^ permalink raw reply related	[flat|nested] 193+ messages in thread

* [PATCH v5 04/19] clone: use free() instead of UNLEAK()
  2023-01-18 12:08       ` [PATCH v5 00/19] leak fixes: various simple leak fixes Ævar Arnfjörð Bjarmason
                           ` (2 preceding siblings ...)
  2023-01-18 12:08         ` [PATCH v5 03/19] commit-graph: use free_commit_graph() instead of UNLEAK() Ævar Arnfjörð Bjarmason
@ 2023-01-18 12:08         ` Ævar Arnfjörð Bjarmason
  2023-01-18 12:08         ` [PATCH v5 05/19] various: add missing clear_pathspec(), fix leaks Ævar Arnfjörð Bjarmason
                           ` (15 subsequent siblings)
  19 siblings, 0 replies; 193+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2023-01-18 12:08 UTC (permalink / raw)
  To: git
  Cc: René Scharfe, Junio C Hamano, Eric Sunshine,
	Ævar Arnfjörð Bjarmason

Change an UNLEAK() added in 0c4542738e6 (clone: free or UNLEAK further
pointers when finished, 2021-03-14) to use a "to_free" pattern
instead. In this case the "repo" can be either this absolute_pathdup()
value, or in the "else if" branch seen in the context the the
"argv[0]" argument to "main()".

We can only free() the value in the former case, hence the "to_free"
pattern.

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 builtin/clone.c | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/builtin/clone.c b/builtin/clone.c
index 5453ba5277f..ba82f5e4108 100644
--- a/builtin/clone.c
+++ b/builtin/clone.c
@@ -892,6 +892,7 @@ int cmd_clone(int argc, const char **argv, const char *prefix)
 	int is_bundle = 0, is_local;
 	int reject_shallow = 0;
 	const char *repo_name, *repo, *work_tree, *git_dir;
+	char *repo_to_free = NULL;
 	char *path = NULL, *dir, *display_repo = NULL;
 	int dest_exists, real_dest_exists = 0;
 	const struct ref *refs, *remote_head;
@@ -949,7 +950,7 @@ int cmd_clone(int argc, const char **argv, const char *prefix)
 	path = get_repo_path(repo_name, &is_bundle);
 	if (path) {
 		FREE_AND_NULL(path);
-		repo = absolute_pathdup(repo_name);
+		repo = repo_to_free = absolute_pathdup(repo_name);
 	} else if (strchr(repo_name, ':')) {
 		repo = repo_name;
 		display_repo = transport_anonymize_url(repo);
@@ -1413,7 +1414,7 @@ int cmd_clone(int argc, const char **argv, const char *prefix)
 	free(unborn_head);
 	free(dir);
 	free(path);
-	UNLEAK(repo);
+	free(repo_to_free);
 	junk_mode = JUNK_LEAVE_ALL;
 
 	transport_ls_refs_options_release(&transport_ls_refs_options);
-- 
2.39.0.1225.g30a3d88132d


^ permalink raw reply related	[flat|nested] 193+ messages in thread

* [PATCH v5 05/19] various: add missing clear_pathspec(), fix leaks
  2023-01-18 12:08       ` [PATCH v5 00/19] leak fixes: various simple leak fixes Ævar Arnfjörð Bjarmason
                           ` (3 preceding siblings ...)
  2023-01-18 12:08         ` [PATCH v5 04/19] clone: use free() " Ævar Arnfjörð Bjarmason
@ 2023-01-18 12:08         ` Ævar Arnfjörð Bjarmason
  2023-01-18 12:08         ` [PATCH v5 06/19] name-rev: don't xstrdup() an already dup'd string Ævar Arnfjörð Bjarmason
                           ` (14 subsequent siblings)
  19 siblings, 0 replies; 193+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2023-01-18 12:08 UTC (permalink / raw)
  To: git
  Cc: René Scharfe, Junio C Hamano, Eric Sunshine,
	Ævar Arnfjörð Bjarmason

Fix memory leaks resulting from a missing clear_pathspec().

- archive.c: Plug a leak in the "struct archiver_args", and
  clear_pathspec() the "pathspec" member that the "parse_pathspec_arg()"
  call in this function populates.

- builtin/clean.c: Fix a memory leak that's been with us since
  893d839970c (clean: convert to use parse_pathspec, 2013-07-14).

- builtin/reset.c: Add clear_pathspec() calls to cmd_reset(),
  including to the codepaths where we'd return early.

- builtin/stash.c: Call clear_pathspec() on the pathspec initialized
  in push_stash().

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 archive.c                       |  1 +
 builtin/clean.c                 |  1 +
 builtin/reset.c                 | 11 ++++++++---
 builtin/stash.c                 |  7 +++++--
 t/t5001-archive-attr.sh         |  1 +
 t/t5004-archive-corner-cases.sh |  2 ++
 t/t7105-reset-patch.sh          |  2 ++
 t/t7106-reset-unborn-branch.sh  |  2 ++
 t/t7107-reset-pathspec-file.sh  |  1 +
 t/t7301-clean-interactive.sh    |  1 +
 10 files changed, 24 insertions(+), 5 deletions(-)

diff --git a/archive.c b/archive.c
index 941495f5d78..a2d813e50db 100644
--- a/archive.c
+++ b/archive.c
@@ -710,6 +710,7 @@ int write_archive(int argc, const char **argv, const char *prefix,
 
 	string_list_clear_func(&args.extra_files, extra_file_info_clear);
 	free(args.refname);
+	clear_pathspec(&args.pathspec);
 
 	return rc;
 }
diff --git a/builtin/clean.c b/builtin/clean.c
index b2701a28158..b15eab328b7 100644
--- a/builtin/clean.c
+++ b/builtin/clean.c
@@ -1092,5 +1092,6 @@ int cmd_clean(int argc, const char **argv, const char *prefix)
 	strbuf_release(&buf);
 	string_list_clear(&del_list, 0);
 	string_list_clear(&exclude_list, 0);
+	clear_pathspec(&pathspec);
 	return (errors != 0);
 }
diff --git a/builtin/reset.c b/builtin/reset.c
index fea20a9ba0b..e9c10618cd3 100644
--- a/builtin/reset.c
+++ b/builtin/reset.c
@@ -390,7 +390,8 @@ int cmd_reset(int argc, const char **argv, const char *prefix)
 		if (reset_type != NONE)
 			die(_("options '%s' and '%s' cannot be used together"), "--patch", "--{hard,mixed,soft}");
 		trace2_cmd_mode("patch-interactive");
-		return run_add_interactive(rev, "--patch=reset", &pathspec);
+		update_ref_status = run_add_interactive(rev, "--patch=reset", &pathspec);
+		goto cleanup;
 	}
 
 	/* git reset tree [--] paths... can be used to
@@ -439,8 +440,10 @@ int cmd_reset(int argc, const char **argv, const char *prefix)
 				       LOCK_DIE_ON_ERROR);
 		if (reset_type == MIXED) {
 			int flags = quiet ? REFRESH_QUIET : REFRESH_IN_PORCELAIN;
-			if (read_from_tree(&pathspec, &oid, intent_to_add))
-				return 1;
+			if (read_from_tree(&pathspec, &oid, intent_to_add)) {
+				update_ref_status = 1;
+				goto cleanup;
+			}
 			the_index.updated_skipworktree = 1;
 			if (!no_refresh && get_git_work_tree()) {
 				uint64_t t_begin, t_delta_in_ms;
@@ -488,5 +491,7 @@ int cmd_reset(int argc, const char **argv, const char *prefix)
 
 	discard_index(&the_index);
 
+cleanup:
+	clear_pathspec(&pathspec);
 	return update_ref_status;
 }
diff --git a/builtin/stash.c b/builtin/stash.c
index bb0fd861434..45bffdf54bb 100644
--- a/builtin/stash.c
+++ b/builtin/stash.c
@@ -1727,6 +1727,7 @@ static int push_stash(int argc, const char **argv, const char *prefix,
 		OPT_PATHSPEC_FILE_NUL(&pathspec_file_nul),
 		OPT_END()
 	};
+	int ret;
 
 	if (argc) {
 		force_assume = !strcmp(argv[0], "-p");
@@ -1766,8 +1767,10 @@ static int push_stash(int argc, const char **argv, const char *prefix,
 		die(_("the option '%s' requires '%s'"), "--pathspec-file-nul", "--pathspec-from-file");
 	}
 
-	return do_push_stash(&ps, stash_msg, quiet, keep_index, patch_mode,
-			     include_untracked, only_staged);
+	ret = do_push_stash(&ps, stash_msg, quiet, keep_index, patch_mode,
+			    include_untracked, only_staged);
+	clear_pathspec(&ps);
+	return ret;
 }
 
 static int push_stash_unassumed(int argc, const char **argv, const char *prefix)
diff --git a/t/t5001-archive-attr.sh b/t/t5001-archive-attr.sh
index 2f6eef5e372..04d300eeda7 100755
--- a/t/t5001-archive-attr.sh
+++ b/t/t5001-archive-attr.sh
@@ -3,6 +3,7 @@
 test_description='git archive attribute tests'
 
 TEST_CREATE_REPO_NO_TEMPLATE=1
+TEST_PASSES_SANITIZE_LEAK=true
 . ./test-lib.sh
 
 SUBSTFORMAT='%H (%h)%n'
diff --git a/t/t5004-archive-corner-cases.sh b/t/t5004-archive-corner-cases.sh
index ae508e21623..9f2c6da80e8 100755
--- a/t/t5004-archive-corner-cases.sh
+++ b/t/t5004-archive-corner-cases.sh
@@ -1,6 +1,8 @@
 #!/bin/sh
 
 test_description='test corner cases of git-archive'
+
+TEST_PASSES_SANITIZE_LEAK=true
 . ./test-lib.sh
 
 # the 10knuls.tar file is used to test for an empty git generated tar
diff --git a/t/t7105-reset-patch.sh b/t/t7105-reset-patch.sh
index fc2a6cf5c7a..9b46da7aaa7 100755
--- a/t/t7105-reset-patch.sh
+++ b/t/t7105-reset-patch.sh
@@ -1,6 +1,8 @@
 #!/bin/sh
 
 test_description='git reset --patch'
+
+TEST_PASSES_SANITIZE_LEAK=true
 . ./lib-patch-mode.sh
 
 test_expect_success PERL 'setup' '
diff --git a/t/t7106-reset-unborn-branch.sh b/t/t7106-reset-unborn-branch.sh
index ecb85c3b823..a0b67a0b843 100755
--- a/t/t7106-reset-unborn-branch.sh
+++ b/t/t7106-reset-unborn-branch.sh
@@ -1,6 +1,8 @@
 #!/bin/sh
 
 test_description='git reset should work on unborn branch'
+
+TEST_PASSES_SANITIZE_LEAK=true
 . ./test-lib.sh
 
 test_expect_success 'setup' '
diff --git a/t/t7107-reset-pathspec-file.sh b/t/t7107-reset-pathspec-file.sh
index 523efbecde1..af5ea406db3 100755
--- a/t/t7107-reset-pathspec-file.sh
+++ b/t/t7107-reset-pathspec-file.sh
@@ -2,6 +2,7 @@
 
 test_description='reset --pathspec-from-file'
 
+TEST_PASSES_SANITIZE_LEAK=true
 . ./test-lib.sh
 
 test_tick
diff --git a/t/t7301-clean-interactive.sh b/t/t7301-clean-interactive.sh
index a07e8b86de2..d82a3210a1d 100755
--- a/t/t7301-clean-interactive.sh
+++ b/t/t7301-clean-interactive.sh
@@ -2,6 +2,7 @@
 
 test_description='git clean -i basic tests'
 
+TEST_PASSES_SANITIZE_LEAK=true
 . ./test-lib.sh
 . "$TEST_DIRECTORY"/lib-terminal.sh
 
-- 
2.39.0.1225.g30a3d88132d


^ permalink raw reply related	[flat|nested] 193+ messages in thread

* [PATCH v5 06/19] name-rev: don't xstrdup() an already dup'd string
  2023-01-18 12:08       ` [PATCH v5 00/19] leak fixes: various simple leak fixes Ævar Arnfjörð Bjarmason
                           ` (4 preceding siblings ...)
  2023-01-18 12:08         ` [PATCH v5 05/19] various: add missing clear_pathspec(), fix leaks Ævar Arnfjörð Bjarmason
@ 2023-01-18 12:08         ` Ævar Arnfjörð Bjarmason
  2023-01-18 12:08         ` [PATCH v5 07/19] repack: fix leaks on error with "goto cleanup" Ævar Arnfjörð Bjarmason
                           ` (13 subsequent siblings)
  19 siblings, 0 replies; 193+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2023-01-18 12:08 UTC (permalink / raw)
  To: git
  Cc: René Scharfe, Junio C Hamano, Eric Sunshine,
	Ævar Arnfjörð Bjarmason

When "add_to_tip_table()" is called with a non-zero
"shorten_unambiguous" we always return an xstrdup()'d string, which
we'd then xstrdup() again, leaking memory. See [1] and [2] for how
this leak came about.

We could xstrdup() only if "shorten_unambiguous" wasn't true, but
let's instead inline this code, so that information on whether we need
to xstrdup() is contained within add_to_tip_table().

1. 98c5c4ad015 (name-rev: allow to specify a subpath for --refs
   option, 2013-06-18)
2. b23e0b9353e (name-rev: allow converting the exact object name at
   the tip of a ref, 2013-07-07)

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 builtin/name-rev.c | 23 ++++++++++-------------
 1 file changed, 10 insertions(+), 13 deletions(-)

diff --git a/builtin/name-rev.c b/builtin/name-rev.c
index 15535e914a6..49fae523694 100644
--- a/builtin/name-rev.c
+++ b/builtin/name-rev.c
@@ -273,17 +273,6 @@ static int subpath_matches(const char *path, const char *filter)
 	return -1;
 }
 
-static const char *name_ref_abbrev(const char *refname, int shorten_unambiguous)
-{
-	if (shorten_unambiguous)
-		refname = shorten_unambiguous_ref(refname, 0);
-	else if (skip_prefix(refname, "refs/heads/", &refname))
-		; /* refname already advanced */
-	else
-		skip_prefix(refname, "refs/", &refname);
-	return refname;
-}
-
 struct name_ref_data {
 	int tags_only;
 	int name_only;
@@ -309,11 +298,19 @@ static void add_to_tip_table(const struct object_id *oid, const char *refname,
 			     int shorten_unambiguous, struct commit *commit,
 			     timestamp_t taggerdate, int from_tag, int deref)
 {
-	refname = name_ref_abbrev(refname, shorten_unambiguous);
+	char *short_refname = NULL;
+
+	if (shorten_unambiguous)
+		short_refname = shorten_unambiguous_ref(refname, 0);
+	else if (skip_prefix(refname, "refs/heads/", &refname))
+		; /* refname already advanced */
+	else
+		skip_prefix(refname, "refs/", &refname);
 
 	ALLOC_GROW(tip_table.table, tip_table.nr + 1, tip_table.alloc);
 	oidcpy(&tip_table.table[tip_table.nr].oid, oid);
-	tip_table.table[tip_table.nr].refname = xstrdup(refname);
+	tip_table.table[tip_table.nr].refname = short_refname ?
+		short_refname : xstrdup(refname);
 	tip_table.table[tip_table.nr].commit = commit;
 	tip_table.table[tip_table.nr].taggerdate = taggerdate;
 	tip_table.table[tip_table.nr].from_tag = from_tag;
-- 
2.39.0.1225.g30a3d88132d


^ permalink raw reply related	[flat|nested] 193+ messages in thread

* [PATCH v5 07/19] repack: fix leaks on error with "goto cleanup"
  2023-01-18 12:08       ` [PATCH v5 00/19] leak fixes: various simple leak fixes Ævar Arnfjörð Bjarmason
                           ` (5 preceding siblings ...)
  2023-01-18 12:08         ` [PATCH v5 06/19] name-rev: don't xstrdup() an already dup'd string Ævar Arnfjörð Bjarmason
@ 2023-01-18 12:08         ` Ævar Arnfjörð Bjarmason
  2023-01-26  1:36           ` Elijah Newren
  2023-01-18 12:08         ` [PATCH v5 08/19] worktree: fix a trivial leak in prune_worktrees() Ævar Arnfjörð Bjarmason
                           ` (12 subsequent siblings)
  19 siblings, 1 reply; 193+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2023-01-18 12:08 UTC (permalink / raw)
  To: git
  Cc: René Scharfe, Junio C Hamano, Eric Sunshine,
	Ævar Arnfjörð Bjarmason

Change cmd_repack() to "goto cleanup" rather than "return ret" on
error, when we returned we'd potentially skip cleaning up the
string_lists and other data we'd allocated in this function.

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 builtin/repack.c                    | 13 +++++++------
 t/t6011-rev-list-with-bad-commit.sh |  1 +
 2 files changed, 8 insertions(+), 6 deletions(-)

diff --git a/builtin/repack.c b/builtin/repack.c
index c1402ad038f..f6493795318 100644
--- a/builtin/repack.c
+++ b/builtin/repack.c
@@ -948,7 +948,7 @@ int cmd_repack(int argc, const char **argv, const char *prefix)
 
 	ret = start_command(&cmd);
 	if (ret)
-		return ret;
+		goto cleanup;
 
 	if (geometry) {
 		FILE *in = xfdopen(cmd.in, "w");
@@ -977,7 +977,7 @@ int cmd_repack(int argc, const char **argv, const char *prefix)
 	fclose(out);
 	ret = finish_command(&cmd);
 	if (ret)
-		return ret;
+		goto cleanup;
 
 	if (!names.nr && !po_args.quiet)
 		printf_ln(_("Nothing new to pack."));
@@ -1007,7 +1007,7 @@ int cmd_repack(int argc, const char **argv, const char *prefix)
 				       &existing_nonkept_packs,
 				       &existing_kept_packs);
 		if (ret)
-			return ret;
+			goto cleanup;
 
 		if (delete_redundant && expire_to) {
 			/*
@@ -1039,7 +1039,7 @@ int cmd_repack(int argc, const char **argv, const char *prefix)
 					       &existing_nonkept_packs,
 					       &existing_kept_packs);
 			if (ret)
-				return ret;
+				goto cleanup;
 		}
 	}
 
@@ -1115,7 +1115,7 @@ int cmd_repack(int argc, const char **argv, const char *prefix)
 		string_list_clear(&include, 0);
 
 		if (ret)
-			return ret;
+			goto cleanup;
 	}
 
 	reprepare_packed_git(the_repository);
@@ -1172,10 +1172,11 @@ int cmd_repack(int argc, const char **argv, const char *prefix)
 		write_midx_file(get_object_directory(), NULL, NULL, flags);
 	}
 
+cleanup:
 	string_list_clear(&names, 1);
 	string_list_clear(&existing_nonkept_packs, 0);
 	string_list_clear(&existing_kept_packs, 0);
 	clear_pack_geometry(geometry);
 
-	return 0;
+	return ret;
 }
diff --git a/t/t6011-rev-list-with-bad-commit.sh b/t/t6011-rev-list-with-bad-commit.sh
index bad02cf5b83..b2e422cf0f7 100755
--- a/t/t6011-rev-list-with-bad-commit.sh
+++ b/t/t6011-rev-list-with-bad-commit.sh
@@ -2,6 +2,7 @@
 
 test_description='git rev-list should notice bad commits'
 
+TEST_PASSES_SANITIZE_LEAK=true
 . ./test-lib.sh
 
 # Note:
-- 
2.39.0.1225.g30a3d88132d


^ permalink raw reply related	[flat|nested] 193+ messages in thread

* [PATCH v5 08/19] worktree: fix a trivial leak in prune_worktrees()
  2023-01-18 12:08       ` [PATCH v5 00/19] leak fixes: various simple leak fixes Ævar Arnfjörð Bjarmason
                           ` (6 preceding siblings ...)
  2023-01-18 12:08         ` [PATCH v5 07/19] repack: fix leaks on error with "goto cleanup" Ævar Arnfjörð Bjarmason
@ 2023-01-18 12:08         ` Ævar Arnfjörð Bjarmason
  2023-01-18 12:08         ` [PATCH v5 09/19] http-backend.c: fix "dir" and "cmd_arg" leaks in cmd_main() Ævar Arnfjörð Bjarmason
                           ` (11 subsequent siblings)
  19 siblings, 0 replies; 193+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2023-01-18 12:08 UTC (permalink / raw)
  To: git
  Cc: René Scharfe, Junio C Hamano, Eric Sunshine,
	Ævar Arnfjörð Bjarmason

We were leaking both the "struct strbuf" in prune_worktrees(), as well
as the "path" we got from should_prune_worktree(). Since these were
the only two uses of the "struct string_list" let's change it to a
"DUP" and push these to it with "string_list_append_nodup()".

For the string_list_append_nodup() we could also string_list_append()
the main_path.buf, and then strbuf_release(&main_path) right away. But
doing it this way avoids an allocation, as we already have the "struct
strbuf" prepared for appending to "kept".

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 builtin/worktree.c         | 6 +++---
 t/t2401-worktree-prune.sh  | 1 +
 t/t2406-worktree-repair.sh | 1 +
 3 files changed, 5 insertions(+), 3 deletions(-)

diff --git a/builtin/worktree.c b/builtin/worktree.c
index 591d659faea..865ce9be22b 100644
--- a/builtin/worktree.c
+++ b/builtin/worktree.c
@@ -173,7 +173,7 @@ static void prune_worktrees(void)
 {
 	struct strbuf reason = STRBUF_INIT;
 	struct strbuf main_path = STRBUF_INIT;
-	struct string_list kept = STRING_LIST_INIT_NODUP;
+	struct string_list kept = STRING_LIST_INIT_DUP;
 	DIR *dir = opendir(git_path("worktrees"));
 	struct dirent *d;
 	if (!dir)
@@ -184,14 +184,14 @@ static void prune_worktrees(void)
 		if (should_prune_worktree(d->d_name, &reason, &path, expire))
 			prune_worktree(d->d_name, reason.buf);
 		else if (path)
-			string_list_append(&kept, path)->util = xstrdup(d->d_name);
+			string_list_append_nodup(&kept, path)->util = xstrdup(d->d_name);
 	}
 	closedir(dir);
 
 	strbuf_add_absolute_path(&main_path, get_git_common_dir());
 	/* massage main worktree absolute path to match 'gitdir' content */
 	strbuf_strip_suffix(&main_path, "/.");
-	string_list_append(&kept, strbuf_detach(&main_path, NULL));
+	string_list_append_nodup(&kept, strbuf_detach(&main_path, NULL));
 	prune_dups(&kept);
 	string_list_clear(&kept, 1);
 
diff --git a/t/t2401-worktree-prune.sh b/t/t2401-worktree-prune.sh
index 3d28c7f06b2..568a47ec426 100755
--- a/t/t2401-worktree-prune.sh
+++ b/t/t2401-worktree-prune.sh
@@ -5,6 +5,7 @@ test_description='prune $GIT_DIR/worktrees'
 GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
 export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
 
+TEST_PASSES_SANITIZE_LEAK=true
 . ./test-lib.sh
 
 test_expect_success initialize '
diff --git a/t/t2406-worktree-repair.sh b/t/t2406-worktree-repair.sh
index 5c44453e1c1..8970780efcc 100755
--- a/t/t2406-worktree-repair.sh
+++ b/t/t2406-worktree-repair.sh
@@ -2,6 +2,7 @@
 
 test_description='test git worktree repair'
 
+TEST_PASSES_SANITIZE_LEAK=true
 . ./test-lib.sh
 
 test_expect_success setup '
-- 
2.39.0.1225.g30a3d88132d


^ permalink raw reply related	[flat|nested] 193+ messages in thread

* [PATCH v5 09/19] http-backend.c: fix "dir" and "cmd_arg" leaks in cmd_main()
  2023-01-18 12:08       ` [PATCH v5 00/19] leak fixes: various simple leak fixes Ævar Arnfjörð Bjarmason
                           ` (7 preceding siblings ...)
  2023-01-18 12:08         ` [PATCH v5 08/19] worktree: fix a trivial leak in prune_worktrees() Ævar Arnfjörð Bjarmason
@ 2023-01-18 12:08         ` Ævar Arnfjörð Bjarmason
  2023-01-18 12:08         ` [PATCH v5 10/19] http-backend.c: fix cmd_main() memory leak, refactor reg{exec,free}() Ævar Arnfjörð Bjarmason
                           ` (10 subsequent siblings)
  19 siblings, 0 replies; 193+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2023-01-18 12:08 UTC (permalink / raw)
  To: git
  Cc: René Scharfe, Junio C Hamano, Eric Sunshine,
	Ævar Arnfjörð Bjarmason

Free the "dir" variable after we're done with it. Before
917adc03608 (http-backend: add GIT_PROJECT_ROOT environment var,
2009-10-30) there was no leak here, as we'd get it via getenv(), but
since 917adc03608 we've xstrdup()'d it (or the equivalent), so we need
to free() it.

We also need to free the "cmd_arg" variable, which has been leaked
ever since it was added in 2f4038ab337 (Git-aware CGI to provide dumb
HTTP transport, 2009-10-30).

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 http-backend.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/http-backend.c b/http-backend.c
index 6eb3b2fe51c..67819d931ce 100644
--- a/http-backend.c
+++ b/http-backend.c
@@ -786,6 +786,7 @@ int cmd_main(int argc, const char **argv)
 	if (!getenv("GIT_HTTP_EXPORT_ALL") &&
 	    access("git-daemon-export-ok", F_OK) )
 		not_found(&hdr, "Repository not exported: '%s'", dir);
+	free(dir);
 
 	http_config();
 	max_request_buffer = git_env_ulong("GIT_HTTP_MAX_REQUEST_BUFFER",
@@ -795,5 +796,6 @@ int cmd_main(int argc, const char **argv)
 		setenv(GIT_PROTOCOL_ENVIRONMENT, proto_header, 0);
 
 	cmd->imp(&hdr, cmd_arg);
+	free(cmd_arg);
 	return 0;
 }
-- 
2.39.0.1225.g30a3d88132d


^ permalink raw reply related	[flat|nested] 193+ messages in thread

* [PATCH v5 10/19] http-backend.c: fix cmd_main() memory leak, refactor reg{exec,free}()
  2023-01-18 12:08       ` [PATCH v5 00/19] leak fixes: various simple leak fixes Ævar Arnfjörð Bjarmason
                           ` (8 preceding siblings ...)
  2023-01-18 12:08         ` [PATCH v5 09/19] http-backend.c: fix "dir" and "cmd_arg" leaks in cmd_main() Ævar Arnfjörð Bjarmason
@ 2023-01-18 12:08         ` Ævar Arnfjörð Bjarmason
  2023-01-18 12:08         ` [PATCH v5 11/19] commit-graph: fix a parse_options_concat() leak Ævar Arnfjörð Bjarmason
                           ` (9 subsequent siblings)
  19 siblings, 0 replies; 193+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2023-01-18 12:08 UTC (permalink / raw)
  To: git
  Cc: René Scharfe, Junio C Hamano, Eric Sunshine,
	Ævar Arnfjörð Bjarmason

Fix a memory leak that's been with us ever since
2f4038ab337 (Git-aware CGI to provide dumb HTTP transport,
2009-10-30). In this case we're not calling regerror() after a failed
regexec(), and don't otherwise use "re" afterwards.

We can therefore simplify this code by calling regfree() right after
the regexec(). An alternative fix would be to add a regfree() to both
the "return" and "break" path in this for-loop.

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 http-backend.c | 7 +++++--
 1 file changed, 5 insertions(+), 2 deletions(-)

diff --git a/http-backend.c b/http-backend.c
index 67819d931ce..8ab58e55f85 100644
--- a/http-backend.c
+++ b/http-backend.c
@@ -759,10 +759,14 @@ int cmd_main(int argc, const char **argv)
 		struct service_cmd *c = &services[i];
 		regex_t re;
 		regmatch_t out[1];
+		int ret;
 
 		if (regcomp(&re, c->pattern, REG_EXTENDED))
 			die("Bogus regex in service table: %s", c->pattern);
-		if (!regexec(&re, dir, 1, out, 0)) {
+		ret = regexec(&re, dir, 1, out, 0);
+		regfree(&re);
+
+		if (!ret) {
 			size_t n;
 
 			if (strcmp(method, c->method))
@@ -774,7 +778,6 @@ int cmd_main(int argc, const char **argv)
 			dir[out[0].rm_so] = 0;
 			break;
 		}
-		regfree(&re);
 	}
 
 	if (!cmd)
-- 
2.39.0.1225.g30a3d88132d


^ permalink raw reply related	[flat|nested] 193+ messages in thread

* [PATCH v5 11/19] commit-graph: fix a parse_options_concat() leak
  2023-01-18 12:08       ` [PATCH v5 00/19] leak fixes: various simple leak fixes Ævar Arnfjörð Bjarmason
                           ` (9 preceding siblings ...)
  2023-01-18 12:08         ` [PATCH v5 10/19] http-backend.c: fix cmd_main() memory leak, refactor reg{exec,free}() Ævar Arnfjörð Bjarmason
@ 2023-01-18 12:08         ` Ævar Arnfjörð Bjarmason
  2023-01-18 12:08         ` [PATCH v5 12/19] show-branch: free() allocated "head" before return Ævar Arnfjörð Bjarmason
                           ` (8 subsequent siblings)
  19 siblings, 0 replies; 193+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2023-01-18 12:08 UTC (permalink / raw)
  To: git
  Cc: René Scharfe, Junio C Hamano, Eric Sunshine,
	Ævar Arnfjörð Bjarmason

When the parse_options_concat() was added to this file in
84e4484f128 (commit-graph: use parse_options_concat(), 2021-08-23) we
wouldn't free() it if we returned early in these cases.

Since "result" is 0 by default we can "goto cleanup" in both cases,
and only need to set "result" if write_commit_graph_reachable() fails.

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 builtin/commit-graph.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/builtin/commit-graph.c b/builtin/commit-graph.c
index 0102ac8540e..93704f95a9d 100644
--- a/builtin/commit-graph.c
+++ b/builtin/commit-graph.c
@@ -269,8 +269,8 @@ static int graph_write(int argc, const char **argv, const char *prefix)
 
 	if (opts.reachable) {
 		if (write_commit_graph_reachable(odb, flags, &write_opts))
-			return 1;
-		return 0;
+			result = 1;
+		goto cleanup;
 	}
 
 	if (opts.stdin_packs) {
-- 
2.39.0.1225.g30a3d88132d


^ permalink raw reply related	[flat|nested] 193+ messages in thread

* [PATCH v5 12/19] show-branch: free() allocated "head" before return
  2023-01-18 12:08       ` [PATCH v5 00/19] leak fixes: various simple leak fixes Ævar Arnfjörð Bjarmason
                           ` (10 preceding siblings ...)
  2023-01-18 12:08         ` [PATCH v5 11/19] commit-graph: fix a parse_options_concat() leak Ævar Arnfjörð Bjarmason
@ 2023-01-18 12:08         ` Ævar Arnfjörð Bjarmason
  2023-01-18 12:08         ` [PATCH v5 13/19] builtin/merge.c: use fixed strings, not "strbuf", fix leak Ævar Arnfjörð Bjarmason
                           ` (7 subsequent siblings)
  19 siblings, 0 replies; 193+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2023-01-18 12:08 UTC (permalink / raw)
  To: git
  Cc: René Scharfe, Junio C Hamano, Eric Sunshine,
	Ævar Arnfjörð Bjarmason

Stop leaking the "head" variable, which we've been leaking since it
was originally added in [1], and in its current form since [2]

1. ed378ec7e85 (Make ref resolution saner, 2006-09-11)
2. d9e557a320b (show-branch: store resolved head in heap buffer,
   2017-02-14).

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 builtin/show-branch.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/builtin/show-branch.c b/builtin/show-branch.c
index c013abaf942..358ac3e519a 100644
--- a/builtin/show-branch.c
+++ b/builtin/show-branch.c
@@ -956,5 +956,6 @@ int cmd_show_branch(int ac, const char **av, const char *prefix)
 		if (shown_merge_point && --extra < 0)
 			break;
 	}
+	free(head);
 	return 0;
 }
-- 
2.39.0.1225.g30a3d88132d


^ permalink raw reply related	[flat|nested] 193+ messages in thread

* [PATCH v5 13/19] builtin/merge.c: use fixed strings, not "strbuf", fix leak
  2023-01-18 12:08       ` [PATCH v5 00/19] leak fixes: various simple leak fixes Ævar Arnfjörð Bjarmason
                           ` (11 preceding siblings ...)
  2023-01-18 12:08         ` [PATCH v5 12/19] show-branch: free() allocated "head" before return Ævar Arnfjörð Bjarmason
@ 2023-01-18 12:08         ` Ævar Arnfjörð Bjarmason
  2023-01-18 12:08         ` [PATCH v5 14/19] builtin/merge.c: free "&buf" on "Your local changes..." error Ævar Arnfjörð Bjarmason
                           ` (6 subsequent siblings)
  19 siblings, 0 replies; 193+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2023-01-18 12:08 UTC (permalink / raw)
  To: git
  Cc: René Scharfe, Junio C Hamano, Eric Sunshine,
	Ævar Arnfjörð Bjarmason

Follow-up 465028e0e25 (merge: add missing strbuf_release(),
2021-10-07) and address the "msg" memory leak in this block. We could
free "&msg" before the "goto done" here, but even better is to avoid
allocating it in the first place.

By repeating the "Fast-forward" string here we can avoid using a
"struct strbuf" altogether.

Suggested-by: René Scharfe <l.s.r@web.de>
Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 builtin/merge.c                | 11 ++++-------
 t/t6439-merge-co-error-msgs.sh |  1 +
 2 files changed, 5 insertions(+), 7 deletions(-)

diff --git a/builtin/merge.c b/builtin/merge.c
index 0f093f2a4f2..91dd5435c59 100644
--- a/builtin/merge.c
+++ b/builtin/merge.c
@@ -1560,7 +1560,9 @@ int cmd_merge(int argc, const char **argv, const char *prefix)
 			!common->next &&
 			oideq(&common->item->object.oid, &head_commit->object.oid)) {
 		/* Again the most common case of merging one remote. */
-		struct strbuf msg = STRBUF_INIT;
+		const char *msg = have_message ?
+			"Fast-forward (no commit created; -m option ignored)" :
+			"Fast-forward";
 		struct commit *commit;
 
 		if (verbosity >= 0) {
@@ -1570,10 +1572,6 @@ int cmd_merge(int argc, const char **argv, const char *prefix)
 			       find_unique_abbrev(&remoteheads->item->object.oid,
 						  DEFAULT_ABBREV));
 		}
-		strbuf_addstr(&msg, "Fast-forward");
-		if (have_message)
-			strbuf_addstr(&msg,
-				" (no commit created; -m option ignored)");
 		commit = remoteheads->item;
 		if (!commit) {
 			ret = 1;
@@ -1592,9 +1590,8 @@ int cmd_merge(int argc, const char **argv, const char *prefix)
 			goto done;
 		}
 
-		finish(head_commit, remoteheads, &commit->object.oid, msg.buf);
+		finish(head_commit, remoteheads, &commit->object.oid, msg);
 		remove_merge_branch_state(the_repository);
-		strbuf_release(&msg);
 		goto done;
 	} else if (!remoteheads->next && common->next)
 		;
diff --git a/t/t6439-merge-co-error-msgs.sh b/t/t6439-merge-co-error-msgs.sh
index 52cf0c87690..0cbec57cdab 100755
--- a/t/t6439-merge-co-error-msgs.sh
+++ b/t/t6439-merge-co-error-msgs.sh
@@ -5,6 +5,7 @@ test_description='unpack-trees error messages'
 GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
 export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
 
+TEST_PASSES_SANITIZE_LEAK=true
 . ./test-lib.sh
 
 
-- 
2.39.0.1225.g30a3d88132d


^ permalink raw reply related	[flat|nested] 193+ messages in thread

* [PATCH v5 14/19] builtin/merge.c: free "&buf" on "Your local changes..." error
  2023-01-18 12:08       ` [PATCH v5 00/19] leak fixes: various simple leak fixes Ævar Arnfjörð Bjarmason
                           ` (12 preceding siblings ...)
  2023-01-18 12:08         ` [PATCH v5 13/19] builtin/merge.c: use fixed strings, not "strbuf", fix leak Ævar Arnfjörð Bjarmason
@ 2023-01-18 12:08         ` Ævar Arnfjörð Bjarmason
  2023-01-26  1:54           ` Elijah Newren
  2023-01-18 12:08         ` [PATCH v5 15/19] object-file.c: release the "tag" in check_tag() Ævar Arnfjörð Bjarmason
                           ` (5 subsequent siblings)
  19 siblings, 1 reply; 193+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2023-01-18 12:08 UTC (permalink / raw)
  To: git
  Cc: René Scharfe, Junio C Hamano, Eric Sunshine,
	Ævar Arnfjörð Bjarmason

Plug a memory leak introduced in [1], since that change didn't follow
the "goto done" pattern introduced in [2] we'd leak the "&buf" memory.

1. e4cdfe84a0d (merge: abort if index does not match HEAD for trivial
   merges, 2022-07-23)
2. d5a35c114ab (Copy resolve_ref() return value for longer use,
   2011-11-13)

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 builtin/merge.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/builtin/merge.c b/builtin/merge.c
index 91dd5435c59..2b13124c497 100644
--- a/builtin/merge.c
+++ b/builtin/merge.c
@@ -1618,7 +1618,8 @@ int cmd_merge(int argc, const char **argv, const char *prefix)
 				error(_("Your local changes to the following files would be overwritten by merge:\n  %s"),
 				      sb.buf);
 				strbuf_release(&sb);
-				return 2;
+				ret = 2;
+				goto done;
 			}
 
 			/* See if it is really trivial. */
-- 
2.39.0.1225.g30a3d88132d


^ permalink raw reply related	[flat|nested] 193+ messages in thread

* [PATCH v5 15/19] object-file.c: release the "tag" in check_tag()
  2023-01-18 12:08       ` [PATCH v5 00/19] leak fixes: various simple leak fixes Ævar Arnfjörð Bjarmason
                           ` (13 preceding siblings ...)
  2023-01-18 12:08         ` [PATCH v5 14/19] builtin/merge.c: free "&buf" on "Your local changes..." error Ævar Arnfjörð Bjarmason
@ 2023-01-18 12:08         ` Ævar Arnfjörð Bjarmason
  2023-01-18 12:08         ` [PATCH v5 16/19] grep.c: refactor free_grep_patterns() Ævar Arnfjörð Bjarmason
                           ` (4 subsequent siblings)
  19 siblings, 0 replies; 193+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2023-01-18 12:08 UTC (permalink / raw)
  To: git
  Cc: René Scharfe, Junio C Hamano, Eric Sunshine,
	Ævar Arnfjörð Bjarmason

Fix a memory leak that's been with us ever since c879daa2372 (Make
hash-object more robust against malformed objects, 2011-02-05). With
"HASH_FORMAT_CHECK" (used by "hash-object" and "replace") we'll parse
tags into a throwaway variable on the stack, but weren't freeing the
"item->tag" we might malloc() when doing so.

The clearing that release_tag_memory() does for us is redundant here,
but let's use it as-is anyway. It only has one other existing caller,
which does need the tag to be cleared.

Mark the tests that now pass in their entirety as passing under
"SANITIZE=leak", which means we'll test them as part of the
"linux-leaks" CI job.

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 object-file.c         | 1 +
 t/t3800-mktag.sh      | 1 +
 t/t5302-pack-index.sh | 2 ++
 3 files changed, 4 insertions(+)

diff --git a/object-file.c b/object-file.c
index 80a0cd3b351..b554266aff4 100644
--- a/object-file.c
+++ b/object-file.c
@@ -2324,6 +2324,7 @@ static void check_tag(const void *buf, size_t size)
 	memset(&t, 0, sizeof(t));
 	if (parse_tag_buffer(the_repository, &t, buf, size))
 		die(_("corrupt tag"));
+	release_tag_memory(&t);
 }
 
 static int index_mem(struct index_state *istate,
diff --git a/t/t3800-mktag.sh b/t/t3800-mktag.sh
index e3cf0ffbe59..d3e428ff46e 100755
--- a/t/t3800-mktag.sh
+++ b/t/t3800-mktag.sh
@@ -4,6 +4,7 @@
 
 test_description='git mktag: tag object verify test'
 
+TEST_PASSES_SANITIZE_LEAK=true
 . ./test-lib.sh
 
 ###########################################################
diff --git a/t/t5302-pack-index.sh b/t/t5302-pack-index.sh
index b0095ab41d3..54b11f81c63 100755
--- a/t/t5302-pack-index.sh
+++ b/t/t5302-pack-index.sh
@@ -4,6 +4,8 @@
 #
 
 test_description='pack index with 64-bit offsets and object CRC'
+
+TEST_PASSES_SANITIZE_LEAK=true
 . ./test-lib.sh
 
 test_expect_success 'setup' '
-- 
2.39.0.1225.g30a3d88132d


^ permalink raw reply related	[flat|nested] 193+ messages in thread

* [PATCH v5 16/19] grep.c: refactor free_grep_patterns()
  2023-01-18 12:08       ` [PATCH v5 00/19] leak fixes: various simple leak fixes Ævar Arnfjörð Bjarmason
                           ` (14 preceding siblings ...)
  2023-01-18 12:08         ` [PATCH v5 15/19] object-file.c: release the "tag" in check_tag() Ævar Arnfjörð Bjarmason
@ 2023-01-18 12:08         ` Ævar Arnfjörð Bjarmason
  2023-01-26  2:26           ` Elijah Newren
  2023-01-18 12:08         ` [PATCH v5 17/19] grep API: plug memory leaks by freeing "header_list" Ævar Arnfjörð Bjarmason
                           ` (3 subsequent siblings)
  19 siblings, 1 reply; 193+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2023-01-18 12:08 UTC (permalink / raw)
  To: git
  Cc: René Scharfe, Junio C Hamano, Eric Sunshine,
	Ævar Arnfjörð Bjarmason

Refactor the free_grep_patterns() function to split out the freeing of
the "struct grep_pat" it contains, right now we're only freeing the
"pattern_list", but we should be freeing another member of the same
type, which we'll do in the subsequent commit.

Let's also replace the "return" if we don't have an
"opt->pattern_expression" with a conditional call of
free_pattern_expr().

Before db84376f981 (grep.c: remove "extended" in favor of
"pattern_expression", fix segfault, 2022-10-11) the pattern here was:

	if (!x)
		return;
	free(y);

But after the cleanup in db84376f981 (which was a narrow segfault fix,
and thus avoided refactoring this) we ended up with:

	if (!x)
		return;
	free(x);

Let's instead do:

	if (x)
		free(x);

This doesn't matter for the subsequent change, but as we're
refactoring this function let's make it easier to reason about, and to
extend in the future, i.e. if we start to free free() members that
come after "pattern_expression" in the "struct grep_opt".

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 grep.c | 14 +++++++++-----
 1 file changed, 9 insertions(+), 5 deletions(-)

diff --git a/grep.c b/grep.c
index 06eed694936..a4450df4559 100644
--- a/grep.c
+++ b/grep.c
@@ -769,11 +769,11 @@ static void free_pattern_expr(struct grep_expr *x)
 	free(x);
 }
 
-void free_grep_patterns(struct grep_opt *opt)
+static void free_grep_pat(struct grep_pat *pattern)
 {
 	struct grep_pat *p, *n;
 
-	for (p = opt->pattern_list; p; p = n) {
+	for (p = pattern; p; p = n) {
 		n = p->next;
 		switch (p->token) {
 		case GREP_PATTERN: /* atom */
@@ -790,10 +790,14 @@ void free_grep_patterns(struct grep_opt *opt)
 		}
 		free(p);
 	}
+}
 
-	if (!opt->pattern_expression)
-		return;
-	free_pattern_expr(opt->pattern_expression);
+void free_grep_patterns(struct grep_opt *opt)
+{
+	free_grep_pat(opt->pattern_list);
+
+	if (opt->pattern_expression)
+		free_pattern_expr(opt->pattern_expression);
 }
 
 static const char *end_of_line(const char *cp, unsigned long *left)
-- 
2.39.0.1225.g30a3d88132d


^ permalink raw reply related	[flat|nested] 193+ messages in thread

* [PATCH v5 17/19] grep API: plug memory leaks by freeing "header_list"
  2023-01-18 12:08       ` [PATCH v5 00/19] leak fixes: various simple leak fixes Ævar Arnfjörð Bjarmason
                           ` (15 preceding siblings ...)
  2023-01-18 12:08         ` [PATCH v5 16/19] grep.c: refactor free_grep_patterns() Ævar Arnfjörð Bjarmason
@ 2023-01-18 12:08         ` Ævar Arnfjörð Bjarmason
  2023-01-26  2:33           ` Elijah Newren
  2023-01-18 12:08         ` [PATCH v5 18/19] receive-pack: free() the "ref_name" in "struct command" Ævar Arnfjörð Bjarmason
                           ` (2 subsequent siblings)
  19 siblings, 1 reply; 193+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2023-01-18 12:08 UTC (permalink / raw)
  To: git
  Cc: René Scharfe, Junio C Hamano, Eric Sunshine,
	Ævar Arnfjörð Bjarmason

When the "header_list" struct member was added in [1] it wasn't made
to free the list using loop added for the adjacent "pattern_list"
member, see [2] for when we started freeing it.

This makes e.g. this command leak-free when run on git.git:

	./git -P log -1 --color=always --author=A origin/master

1. 80235ba79ef ("log --author=me --grep=it" should find intersection,
   not union, 2010-01-17)
2. b48fb5b6a95 (grep: free expressions and patterns when done.,
   2006-09-27)

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 grep.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/grep.c b/grep.c
index a4450df4559..c908535e0d8 100644
--- a/grep.c
+++ b/grep.c
@@ -795,6 +795,7 @@ static void free_grep_pat(struct grep_pat *pattern)
 void free_grep_patterns(struct grep_opt *opt)
 {
 	free_grep_pat(opt->pattern_list);
+	free_grep_pat(opt->header_list);
 
 	if (opt->pattern_expression)
 		free_pattern_expr(opt->pattern_expression);
-- 
2.39.0.1225.g30a3d88132d


^ permalink raw reply related	[flat|nested] 193+ messages in thread

* [PATCH v5 18/19] receive-pack: free() the "ref_name" in "struct command"
  2023-01-18 12:08       ` [PATCH v5 00/19] leak fixes: various simple leak fixes Ævar Arnfjörð Bjarmason
                           ` (16 preceding siblings ...)
  2023-01-18 12:08         ` [PATCH v5 17/19] grep API: plug memory leaks by freeing "header_list" Ævar Arnfjörð Bjarmason
@ 2023-01-18 12:08         ` Ævar Arnfjörð Bjarmason
  2023-01-26  2:37           ` Elijah Newren
  2023-01-18 12:08         ` [PATCH v5 19/19] push: free_refs() the "local_refs" in set_refspecs() Ævar Arnfjörð Bjarmason
  2023-02-02  9:52         ` [PATCH v6 00/19] leak fixes: various simple leak fixes Ævar Arnfjörð Bjarmason
  19 siblings, 1 reply; 193+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2023-01-18 12:08 UTC (permalink / raw)
  To: git
  Cc: René Scharfe, Junio C Hamano, Eric Sunshine,
	Ævar Arnfjörð Bjarmason

Fix a memory leak that's been with us since this code was introduced
in 575f497456e (Add first cut at "git-receive-pack", 2005-06-29), see
eb1af2df0b1 (git-receive-pack: start parsing ref update commands,
2005-06-29) for the later change that refactored the code to add the
"ref_name" member.

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 builtin/receive-pack.c                 | 10 ++++++++++
 t/t5405-send-pack-rewind.sh            |  1 +
 t/t5406-remote-rejects.sh              |  1 +
 t/t5507-remote-environment.sh          |  2 ++
 t/t5522-pull-symlink.sh                |  1 +
 t/t5527-fetch-odd-refs.sh              |  1 +
 t/t5560-http-backend-noserver.sh       |  1 +
 t/t5561-http-backend.sh                |  1 +
 t/t5562-http-backend-content-length.sh |  2 ++
 t/t5705-session-id-in-capabilities.sh  |  1 +
 10 files changed, 21 insertions(+)

diff --git a/builtin/receive-pack.c b/builtin/receive-pack.c
index a90af303630..451bad776c6 100644
--- a/builtin/receive-pack.c
+++ b/builtin/receive-pack.c
@@ -2032,6 +2032,15 @@ static struct command **queue_command(struct command **tail,
 	return &cmd->next;
 }
 
+static void free_commands(struct command *commands)
+{
+	while (commands) {
+		struct command *next = commands->next;
+		free(commands);
+		commands = next;
+	}
+}
+
 static void queue_commands_from_cert(struct command **tail,
 				     struct strbuf *push_cert)
 {
@@ -2569,6 +2578,7 @@ int cmd_receive_pack(int argc, const char **argv, const char *prefix)
 		run_receive_hook(commands, "post-receive", 1,
 				 &push_options);
 		run_update_post_hook(commands);
+		free_commands(commands);
 		string_list_clear(&push_options, 0);
 		if (auto_gc) {
 			struct child_process proc = CHILD_PROCESS_INIT;
diff --git a/t/t5405-send-pack-rewind.sh b/t/t5405-send-pack-rewind.sh
index 11f03239a06..1686ac13aa6 100755
--- a/t/t5405-send-pack-rewind.sh
+++ b/t/t5405-send-pack-rewind.sh
@@ -5,6 +5,7 @@ test_description='forced push to replace commit we do not have'
 GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
 export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
 
+TEST_PASSES_SANITIZE_LEAK=true
 . ./test-lib.sh
 
 test_expect_success setup '
diff --git a/t/t5406-remote-rejects.sh b/t/t5406-remote-rejects.sh
index dcbeb420827..d6a99466338 100755
--- a/t/t5406-remote-rejects.sh
+++ b/t/t5406-remote-rejects.sh
@@ -2,6 +2,7 @@
 
 test_description='remote push rejects are reported by client'
 
+TEST_PASSES_SANITIZE_LEAK=true
 . ./test-lib.sh
 
 test_expect_success 'setup' '
diff --git a/t/t5507-remote-environment.sh b/t/t5507-remote-environment.sh
index e6149295b18..c6a6957c500 100755
--- a/t/t5507-remote-environment.sh
+++ b/t/t5507-remote-environment.sh
@@ -1,6 +1,8 @@
 #!/bin/sh
 
 test_description='check environment showed to remote side of transports'
+
+TEST_PASSES_SANITIZE_LEAK=true
 . ./test-lib.sh
 
 test_expect_success 'set up "remote" push situation' '
diff --git a/t/t5522-pull-symlink.sh b/t/t5522-pull-symlink.sh
index bcff460d0a2..394bc60cb8e 100755
--- a/t/t5522-pull-symlink.sh
+++ b/t/t5522-pull-symlink.sh
@@ -2,6 +2,7 @@
 
 test_description='pulling from symlinked subdir'
 
+TEST_PASSES_SANITIZE_LEAK=true
 . ./test-lib.sh
 
 # The scenario we are building:
diff --git a/t/t5527-fetch-odd-refs.sh b/t/t5527-fetch-odd-refs.sh
index e2770e4541f..98ece27c6a0 100755
--- a/t/t5527-fetch-odd-refs.sh
+++ b/t/t5527-fetch-odd-refs.sh
@@ -4,6 +4,7 @@ test_description='test fetching of oddly-named refs'
 GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
 export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
 
+TEST_PASSES_SANITIZE_LEAK=true
 . ./test-lib.sh
 
 # afterwards we will have:
diff --git a/t/t5560-http-backend-noserver.sh b/t/t5560-http-backend-noserver.sh
index d30cf4f5b83..f75068de648 100755
--- a/t/t5560-http-backend-noserver.sh
+++ b/t/t5560-http-backend-noserver.sh
@@ -4,6 +4,7 @@ test_description='test git-http-backend-noserver'
 GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
 export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
 
+TEST_PASSES_SANITIZE_LEAK=true
 . ./test-lib.sh
 
 HTTPD_DOCUMENT_ROOT_PATH="$TRASH_DIRECTORY"
diff --git a/t/t5561-http-backend.sh b/t/t5561-http-backend.sh
index 9c57d843152..e1d3b8caed0 100755
--- a/t/t5561-http-backend.sh
+++ b/t/t5561-http-backend.sh
@@ -4,6 +4,7 @@ test_description='test git-http-backend'
 GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
 export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
 
+TEST_PASSES_SANITIZE_LEAK=true
 . ./test-lib.sh
 . "$TEST_DIRECTORY"/lib-httpd.sh
 
diff --git a/t/t5562-http-backend-content-length.sh b/t/t5562-http-backend-content-length.sh
index b68ec22d3fd..7ee9858a78b 100755
--- a/t/t5562-http-backend-content-length.sh
+++ b/t/t5562-http-backend-content-length.sh
@@ -1,6 +1,8 @@
 #!/bin/sh
 
 test_description='test git-http-backend respects CONTENT_LENGTH'
+
+TEST_PASSES_SANITIZE_LEAK=true
 . ./test-lib.sh
 
 test_lazy_prereq GZIP 'gzip --version'
diff --git a/t/t5705-session-id-in-capabilities.sh b/t/t5705-session-id-in-capabilities.sh
index ed38c76c290..b8a722ec27e 100755
--- a/t/t5705-session-id-in-capabilities.sh
+++ b/t/t5705-session-id-in-capabilities.sh
@@ -2,6 +2,7 @@
 
 test_description='session ID in capabilities'
 
+TEST_PASSES_SANITIZE_LEAK=true
 . ./test-lib.sh
 
 REPO="$(pwd)/repo"
-- 
2.39.0.1225.g30a3d88132d


^ permalink raw reply related	[flat|nested] 193+ messages in thread

* [PATCH v5 19/19] push: free_refs() the "local_refs" in set_refspecs()
  2023-01-18 12:08       ` [PATCH v5 00/19] leak fixes: various simple leak fixes Ævar Arnfjörð Bjarmason
                           ` (17 preceding siblings ...)
  2023-01-18 12:08         ` [PATCH v5 18/19] receive-pack: free() the "ref_name" in "struct command" Ævar Arnfjörð Bjarmason
@ 2023-01-18 12:08         ` Ævar Arnfjörð Bjarmason
  2023-01-26  2:44           ` Elijah Newren
  2023-02-02  9:52         ` [PATCH v6 00/19] leak fixes: various simple leak fixes Ævar Arnfjörð Bjarmason
  19 siblings, 1 reply; 193+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2023-01-18 12:08 UTC (permalink / raw)
  To: git
  Cc: René Scharfe, Junio C Hamano, Eric Sunshine,
	Ævar Arnfjörð Bjarmason

Fix a memory leak that's been with us since this code was added in
ca02465b413 (push: use remote.$name.push as a refmap, 2013-12-03).

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 builtin/push.c                          | 1 +
 t/t1416-ref-transaction-hooks.sh        | 1 +
 t/t2402-worktree-list.sh                | 1 +
 t/t5504-fetch-receive-strict.sh         | 1 +
 t/t5523-push-upstream.sh                | 1 +
 t/t5529-push-errors.sh                  | 2 ++
 t/t5546-receive-limits.sh               | 2 ++
 t/t5547-push-quarantine.sh              | 2 ++
 t/t5606-clone-options.sh                | 1 +
 t/t5810-proto-disable-local.sh          | 2 ++
 t/t5813-proto-disable-ssh.sh            | 2 ++
 t/t7409-submodule-detached-work-tree.sh | 1 +
 t/t7416-submodule-dash-url.sh           | 2 ++
 t/t7450-bad-git-dotfiles.sh             | 2 ++
 14 files changed, 21 insertions(+)

diff --git a/builtin/push.c b/builtin/push.c
index 60ac8017e52..f48e4c6a856 100644
--- a/builtin/push.c
+++ b/builtin/push.c
@@ -129,6 +129,7 @@ static void set_refspecs(const char **refs, int nr, const char *repo)
 		} else
 			refspec_append(&rs, ref);
 	}
+	free_refs(local_refs);
 }
 
 static int push_url_of_remote(struct remote *remote, const char ***url_p)
diff --git a/t/t1416-ref-transaction-hooks.sh b/t/t1416-ref-transaction-hooks.sh
index 27731722a5b..b32ca798f9f 100755
--- a/t/t1416-ref-transaction-hooks.sh
+++ b/t/t1416-ref-transaction-hooks.sh
@@ -5,6 +5,7 @@ test_description='reference transaction hooks'
 GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
 export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
 
+TEST_PASSES_SANITIZE_LEAK=true
 . ./test-lib.sh
 
 test_expect_success setup '
diff --git a/t/t2402-worktree-list.sh b/t/t2402-worktree-list.sh
index 79e0fce2d90..9ad9be0c208 100755
--- a/t/t2402-worktree-list.sh
+++ b/t/t2402-worktree-list.sh
@@ -5,6 +5,7 @@ test_description='test git worktree list'
 GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
 export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
 
+TEST_PASSES_SANITIZE_LEAK=true
 . ./test-lib.sh
 
 test_expect_success 'setup' '
diff --git a/t/t5504-fetch-receive-strict.sh b/t/t5504-fetch-receive-strict.sh
index ac4099ca893..14e8af1f3b7 100755
--- a/t/t5504-fetch-receive-strict.sh
+++ b/t/t5504-fetch-receive-strict.sh
@@ -4,6 +4,7 @@ test_description='fetch/receive strict mode'
 GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
 export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
 
+TEST_PASSES_SANITIZE_LEAK=true
 . ./test-lib.sh
 
 test_expect_success 'setup and inject "corrupt or missing" object' '
diff --git a/t/t5523-push-upstream.sh b/t/t5523-push-upstream.sh
index fdb42920564..c9acc076353 100755
--- a/t/t5523-push-upstream.sh
+++ b/t/t5523-push-upstream.sh
@@ -4,6 +4,7 @@ test_description='push with --set-upstream'
 GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
 export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
 
+TEST_PASSES_SANITIZE_LEAK=true
 . ./test-lib.sh
 . "$TEST_DIRECTORY"/lib-terminal.sh
 
diff --git a/t/t5529-push-errors.sh b/t/t5529-push-errors.sh
index ce85fd30ad1..0247137cb36 100755
--- a/t/t5529-push-errors.sh
+++ b/t/t5529-push-errors.sh
@@ -1,6 +1,8 @@
 #!/bin/sh
 
 test_description='detect some push errors early (before contacting remote)'
+
+TEST_PASSES_SANITIZE_LEAK=true
 . ./test-lib.sh
 
 test_expect_success 'setup commits' '
diff --git a/t/t5546-receive-limits.sh b/t/t5546-receive-limits.sh
index 0b0e987fdb7..eed3c9d81ab 100755
--- a/t/t5546-receive-limits.sh
+++ b/t/t5546-receive-limits.sh
@@ -1,6 +1,8 @@
 #!/bin/sh
 
 test_description='check receive input limits'
+
+TEST_PASSES_SANITIZE_LEAK=true
 . ./test-lib.sh
 
 # Let's run tests with different unpack limits: 1 and 10000
diff --git a/t/t5547-push-quarantine.sh b/t/t5547-push-quarantine.sh
index 1876fb34e51..9f899b8c7d7 100755
--- a/t/t5547-push-quarantine.sh
+++ b/t/t5547-push-quarantine.sh
@@ -1,6 +1,8 @@
 #!/bin/sh
 
 test_description='check quarantine of objects during push'
+
+TEST_PASSES_SANITIZE_LEAK=true
 . ./test-lib.sh
 
 test_expect_success 'create picky dest repo' '
diff --git a/t/t5606-clone-options.sh b/t/t5606-clone-options.sh
index cf221e92c4d..27f9f776389 100755
--- a/t/t5606-clone-options.sh
+++ b/t/t5606-clone-options.sh
@@ -4,6 +4,7 @@ test_description='basic clone options'
 GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
 export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
 
+TEST_PASSES_SANITIZE_LEAK=true
 . ./test-lib.sh
 
 test_expect_success 'setup' '
diff --git a/t/t5810-proto-disable-local.sh b/t/t5810-proto-disable-local.sh
index c1ef99b85c2..862610256fb 100755
--- a/t/t5810-proto-disable-local.sh
+++ b/t/t5810-proto-disable-local.sh
@@ -1,6 +1,8 @@
 #!/bin/sh
 
 test_description='test disabling of local paths in clone/fetch'
+
+TEST_PASSES_SANITIZE_LEAK=true
 . ./test-lib.sh
 . "$TEST_DIRECTORY/lib-proto-disable.sh"
 
diff --git a/t/t5813-proto-disable-ssh.sh b/t/t5813-proto-disable-ssh.sh
index 3f084ee3065..2e975dc70ec 100755
--- a/t/t5813-proto-disable-ssh.sh
+++ b/t/t5813-proto-disable-ssh.sh
@@ -1,6 +1,8 @@
 #!/bin/sh
 
 test_description='test disabling of git-over-ssh in clone/fetch'
+
+TEST_PASSES_SANITIZE_LEAK=true
 . ./test-lib.sh
 . "$TEST_DIRECTORY/lib-proto-disable.sh"
 
diff --git a/t/t7409-submodule-detached-work-tree.sh b/t/t7409-submodule-detached-work-tree.sh
index 374ed481e9c..574a6fc526e 100755
--- a/t/t7409-submodule-detached-work-tree.sh
+++ b/t/t7409-submodule-detached-work-tree.sh
@@ -13,6 +13,7 @@ TEST_NO_CREATE_REPO=1
 GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
 export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
 
+TEST_PASSES_SANITIZE_LEAK=true
 . ./test-lib.sh
 
 test_expect_success 'setup' '
diff --git a/t/t7416-submodule-dash-url.sh b/t/t7416-submodule-dash-url.sh
index 3ebd9859814..7cf72b9a076 100755
--- a/t/t7416-submodule-dash-url.sh
+++ b/t/t7416-submodule-dash-url.sh
@@ -1,6 +1,8 @@
 #!/bin/sh
 
 test_description='check handling of disallowed .gitmodule urls'
+
+TEST_PASSES_SANITIZE_LEAK=true
 . ./test-lib.sh
 
 test_expect_success 'setup' '
diff --git a/t/t7450-bad-git-dotfiles.sh b/t/t7450-bad-git-dotfiles.sh
index ba1f569bcbb..0d0c3f2c683 100755
--- a/t/t7450-bad-git-dotfiles.sh
+++ b/t/t7450-bad-git-dotfiles.sh
@@ -12,6 +12,8 @@ Such as:
 
   - symlinked .gitmodules, etc
 '
+
+TEST_PASSES_SANITIZE_LEAK=true
 . ./test-lib.sh
 . "$TEST_DIRECTORY"/lib-pack.sh
 
-- 
2.39.0.1225.g30a3d88132d


^ permalink raw reply related	[flat|nested] 193+ messages in thread

* Re: [PATCH v4 08/19] worktree: fix a trivial leak in prune_worktrees()
  2023-01-18 10:57           ` [PATCH v4 08/19] worktree: fix a trivial leak in prune_worktrees() Ævar Arnfjörð Bjarmason
@ 2023-01-18 16:16             ` Junio C Hamano
  2023-01-18 23:03               ` Ævar Arnfjörð Bjarmason
  0 siblings, 1 reply; 193+ messages in thread
From: Junio C Hamano @ 2023-01-18 16:16 UTC (permalink / raw)
  To: Ævar Arnfjörð Bjarmason
  Cc: git, René Scharfe, Eric Sunshine

Ævar Arnfjörð Bjarmason <avarab@gmail.com> writes:

>> diff --git c/builtin/branch.c w/builtin/branch.c
>> index f63fd45edb..4fe7757670 100644
>> --- c/builtin/branch.c
>> +++ w/builtin/branch.c
>> @@ -742,6 +742,7 @@ int cmd_branch(int argc, const char **argv, const char *prefix)
>>  	if (filter.abbrev == -1)
>>  		filter.abbrev = DEFAULT_ABBREV;
>>  	filter.ignore_case = icase;
>> +	UNLEAK(filter);
>>  
>>  	finalize_colopts(&colopts, -1);
>>  	if (filter.verbose) {
>
> I'll send a v5 re-roll without this change, sorry.

I'd rather see your reroll with the above addition of UNLEAK() than
without it, to fix the breakage.

^ permalink raw reply	[flat|nested] 193+ messages in thread

* Re: [PATCH v4 15/19] object-file.c: release the "tag" in check_tag()
  2023-01-17 19:58         ` René Scharfe
@ 2023-01-18 17:19           ` Jeff King
  2023-01-18 18:05             ` René Scharfe
  0 siblings, 1 reply; 193+ messages in thread
From: Jeff King @ 2023-01-18 17:19 UTC (permalink / raw)
  To: René Scharfe
  Cc: Ævar Arnfjörð Bjarmason, git, Junio C Hamano,
	Eric Sunshine

On Tue, Jan 17, 2023 at 08:58:24PM +0100, René Scharfe wrote:

> Am 17.01.23 um 18:11 schrieb Ævar Arnfjörð Bjarmason:
> > Fix a memory leak that's been with us ever since c879daa2372 (Make
> > hash-object more robust against malformed objects, 2011-02-05). With
> > "HASH_FORMAT_CHECK" (used by "hash-object" and "replace") we'll parse
> > tags into a throwaway variable on the stack, but weren't freeing the
> > "item->tag" we might malloc() when doing so.
> >
> > The clearing that release_tag_memory() does for us is redundant here,
> > but let's use it as-is anyway. It only has one other existing caller,
> > which does need the tag to be cleared.
> 
> Calling it is better than getting our hands dirty with tag internals
> here.
> 
> There's similar leak in check_commit() in the same file, but plugging it
> would require exporting unparse_commit().  Or perhaps using the heavy
> hammer that is release_commit_memory()?  Anyway, it doesn't seem simple
> to me, so that would be a patch for a separate series.

I think both of these cases are a bit sketchy, because they create an
object struct on the stack, and not via alloc_*_node(), which may
violate assumptions elsewhere. In the case of the tag, it's probably OK.
For the commit, though, the "index" field is going to be 0, which may
confuse release_commit_memory(). It calls free_commit_buffer(), which is
going to use that index to try to free from the buffer slab.

So I'd be wary of calling that. I'm also slightly skeptical of the
existing code that calls parse_commit_buffer(), but I think it works. We
do not attach the buffer to the commit object there (good), and we pass
"0" for check_graph, so the graph code (which IIRC also uses the index
for some slab lookups) isn't run.

I think this code would be better off either:

  1. Just allocating an object struct in the usual way. I understand the
     desire not to spend extra memory, but parse_commit_buffer() is
     going to allocate structs under the hood for the tree and parent
     commits anyway.

  2. The point of this code is to find malformed input to hash-object.
     We're probably better off feeding the buffer to fsck_commit(), etc.
     It does more thorough checks, and these days it does not need an
     object struct at all.

Either of which would naturally fix the leak for tags. I'm not sure
there actually is a leak for commits, as commit structs don't store any
strings themselves.

I don't think any of that needs to hold up Ævar's current series,
though. Fixing the leak this way in the meantime is OK, and then if we
switch to one of the other techniques, the problem just goes away.

-Peff

^ permalink raw reply	[flat|nested] 193+ messages in thread

* Re: [PATCH v4 15/19] object-file.c: release the "tag" in check_tag()
  2023-01-18 17:19           ` Jeff King
@ 2023-01-18 18:05             ` René Scharfe
  2023-01-18 18:39               ` Jeff King
  0 siblings, 1 reply; 193+ messages in thread
From: René Scharfe @ 2023-01-18 18:05 UTC (permalink / raw)
  To: Jeff King
  Cc: Ævar Arnfjörð Bjarmason, git, Junio C Hamano,
	Eric Sunshine

Am 18.01.23 um 18:19 schrieb Jeff King:
> On Tue, Jan 17, 2023 at 08:58:24PM +0100, René Scharfe wrote:
>
>> Am 17.01.23 um 18:11 schrieb Ævar Arnfjörð Bjarmason:
>>> Fix a memory leak that's been with us ever since c879daa2372 (Make
>>> hash-object more robust against malformed objects, 2011-02-05). With
>>> "HASH_FORMAT_CHECK" (used by "hash-object" and "replace") we'll parse
>>> tags into a throwaway variable on the stack, but weren't freeing the
>>> "item->tag" we might malloc() when doing so.
>>>
>>> The clearing that release_tag_memory() does for us is redundant here,
>>> but let's use it as-is anyway. It only has one other existing caller,
>>> which does need the tag to be cleared.
>>
>> Calling it is better than getting our hands dirty with tag internals
>> here.
>>
>> There's similar leak in check_commit() in the same file, but plugging it
>> would require exporting unparse_commit().  Or perhaps using the heavy
>> hammer that is release_commit_memory()?  Anyway, it doesn't seem simple
>> to me, so that would be a patch for a separate series.
>
> I think both of these cases are a bit sketchy, because they create an
> object struct on the stack, and not via alloc_*_node(), which may
> violate assumptions elsewhere. In the case of the tag, it's probably OK.
> For the commit, though, the "index" field is going to be 0, which may
> confuse release_commit_memory(). It calls free_commit_buffer(), which is
> going to use that index to try to free from the buffer slab.
>
> So I'd be wary of calling that. I'm also slightly skeptical of the
> existing code that calls parse_commit_buffer(), but I think it works. We
> do not attach the buffer to the commit object there (good), and we pass
> "0" for check_graph, so the graph code (which IIRC also uses the index
> for some slab lookups) isn't run.
>
> I think this code would be better off either:
>
>   1. Just allocating an object struct in the usual way. I understand the
>      desire not to spend extra memory, but parse_commit_buffer() is
>      going to allocate structs under the hood for the tree and parent
>      commits anyway.
>
>   2. The point of this code is to find malformed input to hash-object.
>      We're probably better off feeding the buffer to fsck_commit(), etc.
>      It does more thorough checks, and these days it does not need an
>      object struct at all.

I like the second one, as long as it won't check too much.  c879daa237
(Make hash-object more robust against malformed objects, 2011-02-05) added
the checks that are now in object-file.c and intended to only validate the
internal structure of objects, not relations between.  It gave the example
to allow adding a commit before its tree, which should be allowed.  And
IIUC fsck_object() fits that bill.

> Either of which would naturally fix the leak for tags. I'm not sure
> there actually is a leak for commits, as commit structs don't store any
> strings themselves.

parse_commit_buffer() allocates the list of parents.

Hmm, and it looks them up.  Doesn't this violate the goal to allow
dangling references?

> I don't think any of that needs to hold up Ævar's current series,
> though. Fixing the leak this way in the meantime is OK, and then if we
> switch to one of the other techniques, the problem just goes away.

Right.

René

^ permalink raw reply	[flat|nested] 193+ messages in thread

* Re: [PATCH v4 15/19] object-file.c: release the "tag" in check_tag()
  2023-01-18 18:05             ` René Scharfe
@ 2023-01-18 18:39               ` Jeff King
  2023-01-18 18:54                 ` René Scharfe
  0 siblings, 1 reply; 193+ messages in thread
From: Jeff King @ 2023-01-18 18:39 UTC (permalink / raw)
  To: René Scharfe
  Cc: Ævar Arnfjörð Bjarmason, git, Junio C Hamano,
	Eric Sunshine

On Wed, Jan 18, 2023 at 07:05:32PM +0100, René Scharfe wrote:

> >   2. The point of this code is to find malformed input to hash-object.
> >      We're probably better off feeding the buffer to fsck_commit(), etc.
> >      It does more thorough checks, and these days it does not need an
> >      object struct at all.
> 
> I like the second one, as long as it won't check too much.  c879daa237
> (Make hash-object more robust against malformed objects, 2011-02-05) added
> the checks that are now in object-file.c and intended to only validate the
> internal structure of objects, not relations between.  It gave the example
> to allow adding a commit before its tree, which should be allowed.  And
> IIUC fsck_object() fits that bill.

Yes, I think it will do what the right thing here. And having just
written up a quick series, the only tests which needed changes were ones
with syntactic problems. :)

I'll send it out in a few minutes.

> > Either of which would naturally fix the leak for tags. I'm not sure
> > there actually is a leak for commits, as commit structs don't store any
> > strings themselves.
> 
> parse_commit_buffer() allocates the list of parents.

Yes, but it does so with lookup_commit(), so the resulting commit
objects are themselves reachable from the usual obj_hash, and thus not
leaked.

> Hmm, and it looks them up.  Doesn't this violate the goal to allow
> dangling references?

No, because lookup_commit() is just about creating an in-process struct.
It doesn't look at the object database at all (though it would complain
if we had seen the same oid in-process as another type).

-Peff

^ permalink raw reply	[flat|nested] 193+ messages in thread

* Re: [PATCH v4 15/19] object-file.c: release the "tag" in check_tag()
  2023-01-18 18:39               ` Jeff King
@ 2023-01-18 18:54                 ` René Scharfe
  2023-01-18 19:17                   ` Jeff King
  0 siblings, 1 reply; 193+ messages in thread
From: René Scharfe @ 2023-01-18 18:54 UTC (permalink / raw)
  To: Jeff King
  Cc: Ævar Arnfjörð Bjarmason, git, Junio C Hamano,
	Eric Sunshine

Am 18.01.23 um 19:39 schrieb Jeff King:
> On Wed, Jan 18, 2023 at 07:05:32PM +0100, René Scharfe wrote:
>
>>>   2. The point of this code is to find malformed input to hash-object.
>>>      We're probably better off feeding the buffer to fsck_commit(), etc.
>>>      It does more thorough checks, and these days it does not need an
>>>      object struct at all.
>>
>> I like the second one, as long as it won't check too much.  c879daa237
>> (Make hash-object more robust against malformed objects, 2011-02-05) added
>> the checks that are now in object-file.c and intended to only validate the
>> internal structure of objects, not relations between.  It gave the example
>> to allow adding a commit before its tree, which should be allowed.  And
>> IIUC fsck_object() fits that bill.
>
> Yes, I think it will do what the right thing here. And having just
> written up a quick series, the only tests which needed changes were ones
> with syntactic problems. :)
>
> I'll send it out in a few minutes.

Great! :)

>>> Either of which would naturally fix the leak for tags. I'm not sure
>>> there actually is a leak for commits, as commit structs don't store any
>>> strings themselves.
>>
>> parse_commit_buffer() allocates the list of parents.
>
> Yes, but it does so with lookup_commit(), so the resulting commit
> objects are themselves reachable from the usual obj_hash, and thus not
> leaked.

The commit_list structures are leaked, no?

>
>> Hmm, and it looks them up.  Doesn't this violate the goal to allow
>> dangling references?
>
> No, because lookup_commit() is just about creating an in-process struct.
> It doesn't look at the object database at all (though it would complain
> if we had seen the same oid in-process as another type).

Ah, good.

René

^ permalink raw reply	[flat|nested] 193+ messages in thread

* Re: [PATCH v4 15/19] object-file.c: release the "tag" in check_tag()
  2023-01-18 18:54                 ` René Scharfe
@ 2023-01-18 19:17                   ` Jeff King
  0 siblings, 0 replies; 193+ messages in thread
From: Jeff King @ 2023-01-18 19:17 UTC (permalink / raw)
  To: René Scharfe
  Cc: Ævar Arnfjörð Bjarmason, git, Junio C Hamano,
	Eric Sunshine

On Wed, Jan 18, 2023 at 07:54:41PM +0100, René Scharfe wrote:

> > Yes, but it does so with lookup_commit(), so the resulting commit
> > objects are themselves reachable from the usual obj_hash, and thus not
> > leaked.
> 
> The commit_list structures are leaked, no?

Ah, yeah, you're right.

-Peff

^ permalink raw reply	[flat|nested] 193+ messages in thread

* Re: [PATCH v4 08/19] worktree: fix a trivial leak in prune_worktrees()
  2023-01-18 16:16             ` Junio C Hamano
@ 2023-01-18 23:03               ` Ævar Arnfjörð Bjarmason
  2023-01-18 23:20                 ` Junio C Hamano
  0 siblings, 1 reply; 193+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2023-01-18 23:03 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: git, René Scharfe, Eric Sunshine


On Wed, Jan 18 2023, Junio C Hamano wrote:

> Ævar Arnfjörð Bjarmason <avarab@gmail.com> writes:
>
>>> diff --git c/builtin/branch.c w/builtin/branch.c
>>> index f63fd45edb..4fe7757670 100644
>>> --- c/builtin/branch.c
>>> +++ w/builtin/branch.c
>>> @@ -742,6 +742,7 @@ int cmd_branch(int argc, const char **argv, const char *prefix)
>>>  	if (filter.abbrev == -1)
>>>  		filter.abbrev = DEFAULT_ABBREV;
>>>  	filter.ignore_case = icase;
>>> +	UNLEAK(filter);
>>>  
>>>  	finalize_colopts(&colopts, -1);
>>>  	if (filter.verbose) {
>>
>> I'll send a v5 re-roll without this change, sorry.
>
> I'd rather see your reroll with the above addition of UNLEAK() than
> without it, to fix the breakage.

I don't mind that UNLEAK() being in-tree until a better fix for that
leak, but doesn't the v5 I sent also address this?

The issue was that I mis-marked a test as passing, when it only passed
depending on my local compiler (-fsanitize=leak is fickle
sometimes). Now that we're not marking that test as leak-free there's no
need for the UNLEAK() for now, no?

Or is there some edge case I didn't spot/notice?

1. https://lore.kernel.org/git/cover-v5-00.19-00000000000-20230118T120334Z-avarab@gmail.com/

^ permalink raw reply	[flat|nested] 193+ messages in thread

* Re: [PATCH v4 08/19] worktree: fix a trivial leak in prune_worktrees()
  2023-01-18 23:03               ` Ævar Arnfjörð Bjarmason
@ 2023-01-18 23:20                 ` Junio C Hamano
  0 siblings, 0 replies; 193+ messages in thread
From: Junio C Hamano @ 2023-01-18 23:20 UTC (permalink / raw)
  To: Ævar Arnfjörð Bjarmason
  Cc: git, René Scharfe, Eric Sunshine

Ævar Arnfjörð Bjarmason <avarab@gmail.com> writes:

>> I'd rather see your reroll with the above addition of UNLEAK() than
>> without it, to fix the breakage.
>
> I don't mind that UNLEAK() being in-tree until a better fix for that
> leak, but doesn't the v5 I sent also address this?
>
> The issue was that I mis-marked a test as passing, when it only passed
> depending on my local compiler (-fsanitize=leak is fickle
> sometimes). Now that we're not marking that test as leak-free there's no
> need for the UNLEAK() for now, no?
>
> Or is there some edge case I didn't spot/notice?

The top-level singleton instance of "filter" that is used once and
never grows unbounded is a perfect use case for UNLEAK().  And with
it, the test DOES get leak-free, so it would be appropriate to keep
the PASSES variable added to the script (until it gets broken
again).

Or did you have any other uses of tools with leaks in the script,
other than the one that is fixed with the UNLEAK()?

^ permalink raw reply	[flat|nested] 193+ messages in thread

* Re: [PATCH v5 07/19] repack: fix leaks on error with "goto cleanup"
  2023-01-18 12:08         ` [PATCH v5 07/19] repack: fix leaks on error with "goto cleanup" Ævar Arnfjörð Bjarmason
@ 2023-01-26  1:36           ` Elijah Newren
  0 siblings, 0 replies; 193+ messages in thread
From: Elijah Newren @ 2023-01-26  1:36 UTC (permalink / raw)
  To: Ævar Arnfjörð Bjarmason
  Cc: git, René Scharfe, Junio C Hamano, Eric Sunshine

On Wed, Jan 18, 2023 at 5:10 AM Ævar Arnfjörð Bjarmason
<avarab@gmail.com> wrote:
>
> Change cmd_repack() to "goto cleanup" rather than "return ret" on
> error, when we returned we'd potentially skip cleaning up the
> string_lists and other data we'd allocated in this function.

This is hard to parse; the comma followed by "when" suggests you are
only changing things under a certain set of conditions rather than
explaining why you are making an unconditional change.  Perhaps:

In cmd_repack() when we hit an error, replace "return ret" with "goto
cleanup" to ensure we free the necessary data structures.


> Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
> ---
>  builtin/repack.c                    | 13 +++++++------
>  t/t6011-rev-list-with-bad-commit.sh |  1 +
>  2 files changed, 8 insertions(+), 6 deletions(-)
>
> diff --git a/builtin/repack.c b/builtin/repack.c
> index c1402ad038f..f6493795318 100644
> --- a/builtin/repack.c
> +++ b/builtin/repack.c
> @@ -948,7 +948,7 @@ int cmd_repack(int argc, const char **argv, const char *prefix)
>
>         ret = start_command(&cmd);
>         if (ret)
> -               return ret;
> +               goto cleanup;
>
>         if (geometry) {
>                 FILE *in = xfdopen(cmd.in, "w");
> @@ -977,7 +977,7 @@ int cmd_repack(int argc, const char **argv, const char *prefix)
>         fclose(out);
>         ret = finish_command(&cmd);
>         if (ret)
> -               return ret;
> +               goto cleanup;
>
>         if (!names.nr && !po_args.quiet)
>                 printf_ln(_("Nothing new to pack."));
> @@ -1007,7 +1007,7 @@ int cmd_repack(int argc, const char **argv, const char *prefix)
>                                        &existing_nonkept_packs,
>                                        &existing_kept_packs);
>                 if (ret)
> -                       return ret;
> +                       goto cleanup;
>
>                 if (delete_redundant && expire_to) {
>                         /*
> @@ -1039,7 +1039,7 @@ int cmd_repack(int argc, const char **argv, const char *prefix)
>                                                &existing_nonkept_packs,
>                                                &existing_kept_packs);
>                         if (ret)
> -                               return ret;
> +                               goto cleanup;
>                 }
>         }
>
> @@ -1115,7 +1115,7 @@ int cmd_repack(int argc, const char **argv, const char *prefix)
>                 string_list_clear(&include, 0);
>
>                 if (ret)
> -                       return ret;
> +                       goto cleanup;
>         }
>
>         reprepare_packed_git(the_repository);
> @@ -1172,10 +1172,11 @@ int cmd_repack(int argc, const char **argv, const char *prefix)
>                 write_midx_file(get_object_directory(), NULL, NULL, flags);
>         }
>
> +cleanup:
>         string_list_clear(&names, 1);
>         string_list_clear(&existing_nonkept_packs, 0);
>         string_list_clear(&existing_kept_packs, 0);
>         clear_pack_geometry(geometry);
>
> -       return 0;
> +       return ret;
>  }
> diff --git a/t/t6011-rev-list-with-bad-commit.sh b/t/t6011-rev-list-with-bad-commit.sh
> index bad02cf5b83..b2e422cf0f7 100755
> --- a/t/t6011-rev-list-with-bad-commit.sh
> +++ b/t/t6011-rev-list-with-bad-commit.sh
> @@ -2,6 +2,7 @@
>
>  test_description='git rev-list should notice bad commits'
>
> +TEST_PASSES_SANITIZE_LEAK=true
>  . ./test-lib.sh
>
>  # Note:
> --
> 2.39.0.1225.g30a3d88132d

Code changes look fine.

^ permalink raw reply	[flat|nested] 193+ messages in thread

* Re: [PATCH v5 02/19] bundle.c: don't leak the "args" in the "struct child_process"
  2023-01-18 12:08         ` [PATCH v5 02/19] bundle.c: don't leak the "args" in the "struct child_process" Ævar Arnfjörð Bjarmason
@ 2023-01-26  1:38           ` Elijah Newren
  0 siblings, 0 replies; 193+ messages in thread
From: Elijah Newren @ 2023-01-26  1:38 UTC (permalink / raw)
  To: Ævar Arnfjörð Bjarmason
  Cc: git, René Scharfe, Junio C Hamano, Eric Sunshine

On Wed, Jan 18, 2023 at 5:16 AM Ævar Arnfjörð Bjarmason
<avarab@gmail.com> wrote:
>
> Fix a leak that's been here since 7366096de9d (bundle API: change
> "flags" to be "extra_index_pack_args", 2021-09-05), if can't verify
> the bundle we didn't call child_process_clear() to clear the "args".

That's really hard to parse.  Perhaps:

Fix a leak that's been here since 7366096de9d (bundle API: change
"flags" to be "extra_index_pack_args", 2021-09-05).  If we can't verify
the bundle, we didn't call child_process_clear() to clear the "args".

> But rather than doing that let's verify the bundle before we start
> preparing the process we're going to spawn, if we get an error we
> don't need to push anything to the "args".

Also hard to parse.  Perhaps:

But rather than adding an additional child_process_clear() call, let's
verify the bundle before we start
preparing the process we're going to spawn.  If we fail to verify, we
don't need to push anything to the child_process "args".


> Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
> ---
>  bundle.c | 6 ++++--
>  1 file changed, 4 insertions(+), 2 deletions(-)
>
> diff --git a/bundle.c b/bundle.c
> index 4ef7256aa11..9ebb10a8f72 100644
> --- a/bundle.c
> +++ b/bundle.c
> @@ -627,6 +627,10 @@ int unbundle(struct repository *r, struct bundle_header *header,
>              enum verify_bundle_flags flags)
>  {
>         struct child_process ip = CHILD_PROCESS_INIT;
> +
> +       if (verify_bundle(r, header, flags))
> +               return -1;
> +
>         strvec_pushl(&ip.args, "index-pack", "--fix-thin", "--stdin", NULL);
>
>         /* If there is a filter, then we need to create the promisor pack. */
> @@ -638,8 +642,6 @@ int unbundle(struct repository *r, struct bundle_header *header,
>                 strvec_clear(extra_index_pack_args);
>         }
>
> -       if (verify_bundle(r, header, flags))
> -               return -1;
>         ip.in = bundle_fd;
>         ip.no_stdout = 1;
>         ip.git_cmd = 1;
> --
> 2.39.0.1225.g30a3d88132d

^ permalink raw reply	[flat|nested] 193+ messages in thread

* Re: [PATCH v5 14/19] builtin/merge.c: free "&buf" on "Your local changes..." error
  2023-01-18 12:08         ` [PATCH v5 14/19] builtin/merge.c: free "&buf" on "Your local changes..." error Ævar Arnfjörð Bjarmason
@ 2023-01-26  1:54           ` Elijah Newren
  0 siblings, 0 replies; 193+ messages in thread
From: Elijah Newren @ 2023-01-26  1:54 UTC (permalink / raw)
  To: Ævar Arnfjörð Bjarmason
  Cc: git, René Scharfe, Junio C Hamano, Eric Sunshine

On Wed, Jan 18, 2023 at 5:14 AM Ævar Arnfjörð Bjarmason
<avarab@gmail.com> wrote:
>
> Plug a memory leak introduced in [1], since that change didn't follow
> the "goto done" pattern introduced in [2] we'd leak the "&buf" memory.
>
> 1. e4cdfe84a0d (merge: abort if index does not match HEAD for trivial
>    merges, 2022-07-23)
> 2. d5a35c114ab (Copy resolve_ref() return value for longer use,
>    2011-11-13)
>
> Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
> ---
>  builtin/merge.c | 3 ++-
>  1 file changed, 2 insertions(+), 1 deletion(-)
>
> diff --git a/builtin/merge.c b/builtin/merge.c
> index 91dd5435c59..2b13124c497 100644
> --- a/builtin/merge.c
> +++ b/builtin/merge.c
> @@ -1618,7 +1618,8 @@ int cmd_merge(int argc, const char **argv, const char *prefix)
>                                 error(_("Your local changes to the following files would be overwritten by merge:\n  %s"),
>                                       sb.buf);
>                                 strbuf_release(&sb);
> -                               return 2;
> +                               ret = 2;
> +                               goto done;
>                         }
>
>                         /* See if it is really trivial. */
> --
> 2.39.0.1225.g30a3d88132d

Thanks for fixing my bug!

^ permalink raw reply	[flat|nested] 193+ messages in thread

* Re: [PATCH v5 16/19] grep.c: refactor free_grep_patterns()
  2023-01-18 12:08         ` [PATCH v5 16/19] grep.c: refactor free_grep_patterns() Ævar Arnfjörð Bjarmason
@ 2023-01-26  2:26           ` Elijah Newren
  0 siblings, 0 replies; 193+ messages in thread
From: Elijah Newren @ 2023-01-26  2:26 UTC (permalink / raw)
  To: Ævar Arnfjörð Bjarmason
  Cc: git, René Scharfe, Junio C Hamano, Eric Sunshine

On Wed, Jan 18, 2023 at 5:35 AM Ævar Arnfjörð Bjarmason
<avarab@gmail.com> wrote:
>
> Refactor the free_grep_patterns() function to split out the freeing of
> the "struct grep_pat" it contains, right now we're only freeing the
> "pattern_list", but we should be freeing another member of the same
> type, which we'll do in the subsequent commit.

s/contains, right/contains. Right/

> Let's also replace the "return" if we don't have an
> "opt->pattern_expression" with a conditional call of
> free_pattern_expr().
>
> Before db84376f981 (grep.c: remove "extended" in favor of
> "pattern_expression", fix segfault, 2022-10-11) the pattern here was:
>
>         if (!x)
>                 return;
>         free(y);
>
> But after the cleanup in db84376f981 (which was a narrow segfault fix,
> and thus avoided refactoring this) we ended up with:

For most of your commits, I like the extended history, but in this
case I think it's just a distraction.  I think I'd replace the above
block with just five words:

    While at it, instead of:

>         if (!x)
>                 return;
>         free(x);
>
> Let's instead do:
>
>         if (x)
>                 free(x);

This is slightly confusing, because "if(x) free(x)" can be compressed
to "free(x)".  I think you meant "free_pattern_expr" rather than
"free", which cannot (currently) be similarly compressed.

> This doesn't matter for the subsequent change, but as we're
> refactoring this function let's make it easier to reason about, and to
> extend in the future, i.e. if we start to free free() members that
> come after "pattern_expression" in the "struct grep_opt".

Perhaps just simplify this paragraph to:

This will make it easier to free additional members from
free_grep_patterns() in the future.


>
> Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
> ---
>  grep.c | 14 +++++++++-----
>  1 file changed, 9 insertions(+), 5 deletions(-)
>
> diff --git a/grep.c b/grep.c
> index 06eed694936..a4450df4559 100644
> --- a/grep.c
> +++ b/grep.c
> @@ -769,11 +769,11 @@ static void free_pattern_expr(struct grep_expr *x)
>         free(x);
>  }
>
> -void free_grep_patterns(struct grep_opt *opt)
> +static void free_grep_pat(struct grep_pat *pattern)
>  {
>         struct grep_pat *p, *n;
>
> -       for (p = opt->pattern_list; p; p = n) {
> +       for (p = pattern; p; p = n) {
>                 n = p->next;
>                 switch (p->token) {
>                 case GREP_PATTERN: /* atom */
> @@ -790,10 +790,14 @@ void free_grep_patterns(struct grep_opt *opt)
>                 }
>                 free(p);
>         }
> +}
>
> -       if (!opt->pattern_expression)
> -               return;
> -       free_pattern_expr(opt->pattern_expression);
> +void free_grep_patterns(struct grep_opt *opt)
> +{
> +       free_grep_pat(opt->pattern_list);
> +
> +       if (opt->pattern_expression)
> +               free_pattern_expr(opt->pattern_expression);
>  }

I think this last function would read even better as:

+void free_grep_patterns(struct grep_opt *opt)
+{
+       free_grep_pat(opt->pattern_list);
+       free_pattern_expr(opt->pattern_expression);
 }

after modifying free_pattern_expr() to return early if passed a NULL argument.

^ permalink raw reply	[flat|nested] 193+ messages in thread

* Re: [PATCH v5 17/19] grep API: plug memory leaks by freeing "header_list"
  2023-01-18 12:08         ` [PATCH v5 17/19] grep API: plug memory leaks by freeing "header_list" Ævar Arnfjörð Bjarmason
@ 2023-01-26  2:33           ` Elijah Newren
  0 siblings, 0 replies; 193+ messages in thread
From: Elijah Newren @ 2023-01-26  2:33 UTC (permalink / raw)
  To: Ævar Arnfjörð Bjarmason
  Cc: git, René Scharfe, Junio C Hamano, Eric Sunshine

I had the same reaction to this patch that Rene did on v1.  The commit
message of the previous patch should probably be reworked so as to not
mislead.

On Wed, Jan 18, 2023 at 5:15 AM Ævar Arnfjörð Bjarmason
<avarab@gmail.com> wrote:
>
> When the "header_list" struct member was added in [1] it wasn't made
> to free the list using loop added for the adjacent "pattern_list"
> member, see [2] for when we started freeing it.
>
> This makes e.g. this command leak-free when run on git.git:
>
>         ./git -P log -1 --color=always --author=A origin/master
>
> 1. 80235ba79ef ("log --author=me --grep=it" should find intersection,
>    not union, 2010-01-17)
> 2. b48fb5b6a95 (grep: free expressions and patterns when done.,
>    2006-09-27)

That paragraph is really hard to parse for me.  Maybe change the above
to something like

"""
When the "header_list" struct member was added in [1], freeing this
field was neglected.  Fix that now, so that commands like

    ./git -P log -1 --color=always --author=A origin/master

will run leak-free.

1. 80235ba79ef ("log --author=me --grep=it" should find intersection,
    not union, 2010-01-17)
"""

> Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
> ---
>  grep.c | 1 +
>  1 file changed, 1 insertion(+)
>
> diff --git a/grep.c b/grep.c
> index a4450df4559..c908535e0d8 100644
> --- a/grep.c
> +++ b/grep.c
> @@ -795,6 +795,7 @@ static void free_grep_pat(struct grep_pat *pattern)
>  void free_grep_patterns(struct grep_opt *opt)
>  {
>         free_grep_pat(opt->pattern_list);
> +       free_grep_pat(opt->header_list);
>
>         if (opt->pattern_expression)
>                 free_pattern_expr(opt->pattern_expression);
> --
> 2.39.0.1225.g30a3d88132d

Actual code change looks good.

^ permalink raw reply	[flat|nested] 193+ messages in thread

* Re: [PATCH v5 18/19] receive-pack: free() the "ref_name" in "struct command"
  2023-01-18 12:08         ` [PATCH v5 18/19] receive-pack: free() the "ref_name" in "struct command" Ævar Arnfjörð Bjarmason
@ 2023-01-26  2:37           ` Elijah Newren
  0 siblings, 0 replies; 193+ messages in thread
From: Elijah Newren @ 2023-01-26  2:37 UTC (permalink / raw)
  To: Ævar Arnfjörð Bjarmason
  Cc: git, René Scharfe, Junio C Hamano, Eric Sunshine

On Wed, Jan 18, 2023 at 4:54 AM Ævar Arnfjörð Bjarmason
<avarab@gmail.com> wrote:
>
> Fix a memory leak that's been with us since this code was introduced
> in 575f497456e (Add first cut at "git-receive-pack", 2005-06-29), see
> eb1af2df0b1 (git-receive-pack: start parsing ref update commands,
> 2005-06-29) for the later change that refactored the code to add the
> "ref_name" member.

This should be two sentences, not one.  s/), see/). See/ should do it.

> Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
> ---
>  builtin/receive-pack.c                 | 10 ++++++++++
>  t/t5405-send-pack-rewind.sh            |  1 +
>  t/t5406-remote-rejects.sh              |  1 +
>  t/t5507-remote-environment.sh          |  2 ++
>  t/t5522-pull-symlink.sh                |  1 +
>  t/t5527-fetch-odd-refs.sh              |  1 +
>  t/t5560-http-backend-noserver.sh       |  1 +
>  t/t5561-http-backend.sh                |  1 +
>  t/t5562-http-backend-content-length.sh |  2 ++
>  t/t5705-session-id-in-capabilities.sh  |  1 +
>  10 files changed, 21 insertions(+)
>
[...]

Code changes look good.

^ permalink raw reply	[flat|nested] 193+ messages in thread

* Re: [PATCH v5 19/19] push: free_refs() the "local_refs" in set_refspecs()
  2023-01-18 12:08         ` [PATCH v5 19/19] push: free_refs() the "local_refs" in set_refspecs() Ævar Arnfjörð Bjarmason
@ 2023-01-26  2:44           ` Elijah Newren
  0 siblings, 0 replies; 193+ messages in thread
From: Elijah Newren @ 2023-01-26  2:44 UTC (permalink / raw)
  To: Ævar Arnfjörð Bjarmason
  Cc: git, René Scharfe, Junio C Hamano, Eric Sunshine

On Wed, Jan 18, 2023 at 5:08 AM Ævar Arnfjörð Bjarmason
<avarab@gmail.com> wrote:
>
> Fix a memory leak that's been with us since this code was added in
> ca02465b413 (push: use remote.$name.push as a refmap, 2013-12-03).
>
> Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
> ---
>  builtin/push.c                          | 1 +
>  t/t1416-ref-transaction-hooks.sh        | 1 +
>  t/t2402-worktree-list.sh                | 1 +
>  t/t5504-fetch-receive-strict.sh         | 1 +
>  t/t5523-push-upstream.sh                | 1 +
>  t/t5529-push-errors.sh                  | 2 ++
>  t/t5546-receive-limits.sh               | 2 ++
>  t/t5547-push-quarantine.sh              | 2 ++
>  t/t5606-clone-options.sh                | 1 +
>  t/t5810-proto-disable-local.sh          | 2 ++
>  t/t5813-proto-disable-ssh.sh            | 2 ++
>  t/t7409-submodule-detached-work-tree.sh | 1 +
>  t/t7416-submodule-dash-url.sh           | 2 ++
>  t/t7450-bad-git-dotfiles.sh             | 2 ++
>  14 files changed, 21 insertions(+)
>
> diff --git a/builtin/push.c b/builtin/push.c
> index 60ac8017e52..f48e4c6a856 100644
> --- a/builtin/push.c
> +++ b/builtin/push.c
> @@ -129,6 +129,7 @@ static void set_refspecs(const char **refs, int nr, const char *repo)
>                 } else
>                         refspec_append(&rs, ref);
>         }
> +       free_refs(local_refs);

In the cover letter, you said you took Rene's feedback as a possible
future improvement, but perhaps it's at least calling out in the code
with a TODO comment?


>  }
>
>  static int push_url_of_remote(struct remote *remote, const char ***url_p)
> diff --git a/t/t1416-ref-transaction-hooks.sh b/t/t1416-ref-transaction-hooks.sh
> index 27731722a5b..b32ca798f9f 100755
> --- a/t/t1416-ref-transaction-hooks.sh
> +++ b/t/t1416-ref-transaction-hooks.sh
> @@ -5,6 +5,7 @@ test_description='reference transaction hooks'
>  GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
>  export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
>
> +TEST_PASSES_SANITIZE_LEAK=true
>  . ./test-lib.sh
>
>  test_expect_success setup '
> diff --git a/t/t2402-worktree-list.sh b/t/t2402-worktree-list.sh
> index 79e0fce2d90..9ad9be0c208 100755
> --- a/t/t2402-worktree-list.sh
> +++ b/t/t2402-worktree-list.sh
> @@ -5,6 +5,7 @@ test_description='test git worktree list'
>  GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
>  export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
>
> +TEST_PASSES_SANITIZE_LEAK=true
>  . ./test-lib.sh
>
>  test_expect_success 'setup' '
> diff --git a/t/t5504-fetch-receive-strict.sh b/t/t5504-fetch-receive-strict.sh
> index ac4099ca893..14e8af1f3b7 100755
> --- a/t/t5504-fetch-receive-strict.sh
> +++ b/t/t5504-fetch-receive-strict.sh
> @@ -4,6 +4,7 @@ test_description='fetch/receive strict mode'
>  GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
>  export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
>
> +TEST_PASSES_SANITIZE_LEAK=true
>  . ./test-lib.sh
>
>  test_expect_success 'setup and inject "corrupt or missing" object' '
> diff --git a/t/t5523-push-upstream.sh b/t/t5523-push-upstream.sh
> index fdb42920564..c9acc076353 100755
> --- a/t/t5523-push-upstream.sh
> +++ b/t/t5523-push-upstream.sh
> @@ -4,6 +4,7 @@ test_description='push with --set-upstream'
>  GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
>  export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
>
> +TEST_PASSES_SANITIZE_LEAK=true
>  . ./test-lib.sh
>  . "$TEST_DIRECTORY"/lib-terminal.sh
>
> diff --git a/t/t5529-push-errors.sh b/t/t5529-push-errors.sh
> index ce85fd30ad1..0247137cb36 100755
> --- a/t/t5529-push-errors.sh
> +++ b/t/t5529-push-errors.sh
> @@ -1,6 +1,8 @@
>  #!/bin/sh
>
>  test_description='detect some push errors early (before contacting remote)'
> +
> +TEST_PASSES_SANITIZE_LEAK=true
>  . ./test-lib.sh
>
>  test_expect_success 'setup commits' '
> diff --git a/t/t5546-receive-limits.sh b/t/t5546-receive-limits.sh
> index 0b0e987fdb7..eed3c9d81ab 100755
> --- a/t/t5546-receive-limits.sh
> +++ b/t/t5546-receive-limits.sh
> @@ -1,6 +1,8 @@
>  #!/bin/sh
>
>  test_description='check receive input limits'
> +
> +TEST_PASSES_SANITIZE_LEAK=true
>  . ./test-lib.sh
>
>  # Let's run tests with different unpack limits: 1 and 10000
> diff --git a/t/t5547-push-quarantine.sh b/t/t5547-push-quarantine.sh
> index 1876fb34e51..9f899b8c7d7 100755
> --- a/t/t5547-push-quarantine.sh
> +++ b/t/t5547-push-quarantine.sh
> @@ -1,6 +1,8 @@
>  #!/bin/sh
>
>  test_description='check quarantine of objects during push'
> +
> +TEST_PASSES_SANITIZE_LEAK=true
>  . ./test-lib.sh
>
>  test_expect_success 'create picky dest repo' '
> diff --git a/t/t5606-clone-options.sh b/t/t5606-clone-options.sh
> index cf221e92c4d..27f9f776389 100755
> --- a/t/t5606-clone-options.sh
> +++ b/t/t5606-clone-options.sh
> @@ -4,6 +4,7 @@ test_description='basic clone options'
>  GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
>  export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
>
> +TEST_PASSES_SANITIZE_LEAK=true
>  . ./test-lib.sh
>
>  test_expect_success 'setup' '
> diff --git a/t/t5810-proto-disable-local.sh b/t/t5810-proto-disable-local.sh
> index c1ef99b85c2..862610256fb 100755
> --- a/t/t5810-proto-disable-local.sh
> +++ b/t/t5810-proto-disable-local.sh
> @@ -1,6 +1,8 @@
>  #!/bin/sh
>
>  test_description='test disabling of local paths in clone/fetch'
> +
> +TEST_PASSES_SANITIZE_LEAK=true
>  . ./test-lib.sh
>  . "$TEST_DIRECTORY/lib-proto-disable.sh"
>
> diff --git a/t/t5813-proto-disable-ssh.sh b/t/t5813-proto-disable-ssh.sh
> index 3f084ee3065..2e975dc70ec 100755
> --- a/t/t5813-proto-disable-ssh.sh
> +++ b/t/t5813-proto-disable-ssh.sh
> @@ -1,6 +1,8 @@
>  #!/bin/sh
>
>  test_description='test disabling of git-over-ssh in clone/fetch'
> +
> +TEST_PASSES_SANITIZE_LEAK=true
>  . ./test-lib.sh
>  . "$TEST_DIRECTORY/lib-proto-disable.sh"
>
> diff --git a/t/t7409-submodule-detached-work-tree.sh b/t/t7409-submodule-detached-work-tree.sh
> index 374ed481e9c..574a6fc526e 100755
> --- a/t/t7409-submodule-detached-work-tree.sh
> +++ b/t/t7409-submodule-detached-work-tree.sh
> @@ -13,6 +13,7 @@ TEST_NO_CREATE_REPO=1
>  GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
>  export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
>
> +TEST_PASSES_SANITIZE_LEAK=true
>  . ./test-lib.sh
>
>  test_expect_success 'setup' '
> diff --git a/t/t7416-submodule-dash-url.sh b/t/t7416-submodule-dash-url.sh
> index 3ebd9859814..7cf72b9a076 100755
> --- a/t/t7416-submodule-dash-url.sh
> +++ b/t/t7416-submodule-dash-url.sh
> @@ -1,6 +1,8 @@
>  #!/bin/sh
>
>  test_description='check handling of disallowed .gitmodule urls'
> +
> +TEST_PASSES_SANITIZE_LEAK=true
>  . ./test-lib.sh
>
>  test_expect_success 'setup' '
> diff --git a/t/t7450-bad-git-dotfiles.sh b/t/t7450-bad-git-dotfiles.sh
> index ba1f569bcbb..0d0c3f2c683 100755
> --- a/t/t7450-bad-git-dotfiles.sh
> +++ b/t/t7450-bad-git-dotfiles.sh
> @@ -12,6 +12,8 @@ Such as:
>
>    - symlinked .gitmodules, etc
>  '
> +
> +TEST_PASSES_SANITIZE_LEAK=true
>  . ./test-lib.sh
>  . "$TEST_DIRECTORY"/lib-pack.sh
>
> --
> 2.39.0.1225.g30a3d88132d
>

^ permalink raw reply	[flat|nested] 193+ messages in thread

* [PATCH v6 00/19] leak fixes: various simple leak fixes
  2023-01-18 12:08       ` [PATCH v5 00/19] leak fixes: various simple leak fixes Ævar Arnfjörð Bjarmason
                           ` (18 preceding siblings ...)
  2023-01-18 12:08         ` [PATCH v5 19/19] push: free_refs() the "local_refs" in set_refspecs() Ævar Arnfjörð Bjarmason
@ 2023-02-02  9:52         ` Ævar Arnfjörð Bjarmason
  2023-02-02  9:52           ` [PATCH v6 01/19] tests: mark tests as passing with SANITIZE=leak Ævar Arnfjörð Bjarmason
                             ` (19 more replies)
  19 siblings, 20 replies; 193+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2023-02-02  9:52 UTC (permalink / raw)
  To: git
  Cc: René Scharfe, Junio C Hamano, Eric Sunshine, Elijah Newren,
	Ævar Arnfjörð Bjarmason

See
https://lore.kernel.org/git/cover-v5-00.19-00000000000-20230118T120334Z-avarab@gmail.com/
for the v5. Changes since then:

* Rebased on master, the recent "fsck" changes made the check_tag()
  patch here redundant, and made various existing tests leak-free,
  which we now mark as such.

* Took major rewrites of commit messages from Elijah, thanks. Added a
  corresponding Helped-by footer to those. Fixed other typos etc. in
  commit messages.

* Add a new 18/19 which addreses the TODO issue René & Elijah pointed
  out in previous rounds.

  I was hoping to keep larger changes like that out of this topic, but
  if we need to explain with a "FIXME" comment or similar what exactly
  we need to fix here (as was suggested), then we might as well just
  fix it instead.

* The subsequent free_refs() patch is the same, but we now explain why
  we're not leaking the "remote" (it's free'd by
  "the_repository->remote_state" cleanup).

CI & branch for this at:
https://github.com/avar/git/tree/avar/leak-fixes-more-misc-trivial-6

Ævar Arnfjörð Bjarmason (19):
  tests: mark tests as passing with SANITIZE=leak
  bundle.c: don't leak the "args" in the "struct child_process"
  commit-graph: use free_commit_graph() instead of UNLEAK()
  clone: use free() instead of UNLEAK()
  various: add missing clear_pathspec(), fix leaks
  name-rev: don't xstrdup() an already dup'd string
  repack: fix leaks on error with "goto cleanup"
  worktree: fix a trivial leak in prune_worktrees()
  http-backend.c: fix "dir" and "cmd_arg" leaks in cmd_main()
  http-backend.c: fix cmd_main() memory leak, refactor reg{exec,free}()
  commit-graph: fix a parse_options_concat() leak
  show-branch: free() allocated "head" before return
  builtin/merge.c: use fixed strings, not "strbuf", fix leak
  builtin/merge.c: free "&buf" on "Your local changes..." error
  grep.c: refactor free_grep_patterns()
  grep API: plug memory leaks by freeing "header_list"
  receive-pack: free() the "ref_name" in "struct command"
  push: refactor refspec_append_mapped() for subsequent leak-fix
  push: free_refs() the "local_refs" in set_refspecs()

 archive.c                                  |  1 +
 builtin/clean.c                            |  1 +
 builtin/clone.c                            |  5 ++--
 builtin/commit-graph.c                     | 10 +++++---
 builtin/merge.c                            | 14 +++++-----
 builtin/name-rev.c                         | 23 ++++++++---------
 builtin/push.c                             | 30 +++++++++++++---------
 builtin/receive-pack.c                     | 10 ++++++++
 builtin/repack.c                           | 13 +++++-----
 builtin/reset.c                            | 11 +++++---
 builtin/show-branch.c                      |  1 +
 builtin/stash.c                            |  7 +++--
 builtin/worktree.c                         |  6 ++---
 bundle.c                                   |  6 +++--
 grep.c                                     | 15 +++++++----
 http-backend.c                             |  9 +++++--
 t/t0023-crlf-am.sh                         |  1 +
 t/t1301-shared-repo.sh                     |  1 +
 t/t1302-repo-version.sh                    |  1 +
 t/t1304-default-acl.sh                     |  1 +
 t/t1408-packed-refs.sh                     |  1 +
 t/t1410-reflog.sh                          |  1 +
 t/t1416-ref-transaction-hooks.sh           |  1 +
 t/t1451-fsck-buffer.sh                     |  2 ++
 t/t2401-worktree-prune.sh                  |  1 +
 t/t2402-worktree-list.sh                   |  1 +
 t/t2406-worktree-repair.sh                 |  1 +
 t/t3210-pack-refs.sh                       |  1 +
 t/t3800-mktag.sh                           |  1 +
 t/t4152-am-subjects.sh                     |  2 ++
 t/t4254-am-corrupt.sh                      |  2 ++
 t/t4256-am-format-flowed.sh                |  1 +
 t/t4257-am-interactive.sh                  |  2 ++
 t/t5001-archive-attr.sh                    |  1 +
 t/t5004-archive-corner-cases.sh            |  2 ++
 t/t5302-pack-index.sh                      |  2 ++
 t/t5306-pack-nobase.sh                     |  2 ++
 t/t5312-prune-corruption.sh                |  1 +
 t/t5317-pack-objects-filter-objects.sh     |  1 +
 t/t5330-no-lazy-fetch-with-commit-graph.sh |  1 +
 t/t5403-post-checkout-hook.sh              |  1 +
 t/t5405-send-pack-rewind.sh                |  1 +
 t/t5406-remote-rejects.sh                  |  1 +
 t/t5502-quickfetch.sh                      |  1 +
 t/t5504-fetch-receive-strict.sh            |  1 +
 t/t5507-remote-environment.sh              |  2 ++
 t/t5522-pull-symlink.sh                    |  1 +
 t/t5523-push-upstream.sh                   |  1 +
 t/t5527-fetch-odd-refs.sh                  |  1 +
 t/t5529-push-errors.sh                     |  2 ++
 t/t5546-receive-limits.sh                  |  2 ++
 t/t5547-push-quarantine.sh                 |  2 ++
 t/t5560-http-backend-noserver.sh           |  1 +
 t/t5561-http-backend.sh                    |  1 +
 t/t5562-http-backend-content-length.sh     |  2 ++
 t/t5573-pull-verify-signatures.sh          |  2 ++
 t/t5604-clone-reference.sh                 |  1 +
 t/t5606-clone-options.sh                   |  1 +
 t/t5613-info-alternate.sh                  |  2 ++
 t/t5705-session-id-in-capabilities.sh      |  1 +
 t/t5810-proto-disable-local.sh             |  2 ++
 t/t5813-proto-disable-ssh.sh               |  2 ++
 t/t6011-rev-list-with-bad-commit.sh        |  1 +
 t/t6014-rev-list-all.sh                    |  1 +
 t/t6021-rev-list-exclude-hidden.sh         |  1 +
 t/t6439-merge-co-error-msgs.sh             |  1 +
 t/t6501-freshen-objects.sh                 |  1 +
 t/t7105-reset-patch.sh                     |  2 ++
 t/t7106-reset-unborn-branch.sh             |  2 ++
 t/t7107-reset-pathspec-file.sh             |  1 +
 t/t7301-clean-interactive.sh               |  1 +
 t/t7403-submodule-sync.sh                  |  1 +
 t/t7409-submodule-detached-work-tree.sh    |  1 +
 t/t7416-submodule-dash-url.sh              |  2 ++
 t/t7450-bad-git-dotfiles.sh                |  2 ++
 t/t7612-merge-verify-signatures.sh         |  1 +
 t/t7701-repack-unpack-unreachable.sh       |  1 +
 77 files changed, 181 insertions(+), 62 deletions(-)

Range-diff against v5:
 1:  c47fc0fb637 !  1:  36da48d4db9 tests: mark tests as passing with SANITIZE=leak
    @@ Commit message
           t7701-repack-unpack-unreachable.sh: In b0c61be3209 (Merge branch
           'rs/reflog-expiry-cleanup', 2022-12-26)
     
    +    - t3800-mktag.sh, t5302-pack-index.sh, t5306-pack-nobase.sh,
    +      t5573-pull-verify-signatures.sh, t7612-merge-verify-signatures.sh: In
    +      69bbbe484ba (hash-object: use fsck for object checks, 2023-01-18).
    +
    +    - t1451-fsck-buffer.sh: In 8e4309038f0 (fsck: do not assume
    +      NUL-termination of buffers, 2023-01-19).
    +
    +    - t6501-freshen-objects.sh: In abf2bb895b4 (Merge branch
    +      'jk/hash-object-fsck', 2023-01-30)
    +
         1. 9ea1378d046 (Merge branch 'ab/various-leak-fixes', 2022-12-14)
     
         Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
    @@ t/t0023-crlf-am.sh
      cat >patchfile <<\EOF
     
      ## t/t1301-shared-repo.sh ##
    -@@ t/t1301-shared-repo.sh: test_description='Test shared repository initialization'
    - GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
    +@@ t/t1301-shared-repo.sh: GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
      export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
      
    + TEST_CREATE_REPO_NO_TEMPLATE=1
     +TEST_PASSES_SANITIZE_LEAK=true
      . ./test-lib.sh
      
    @@ t/t1410-reflog.sh: test_description='Test prune and reflog expiration'
      
      check_have () {
     
    + ## t/t1451-fsck-buffer.sh ##
    +@@ t/t1451-fsck-buffer.sh: so.
    + These tests _might_ catch such overruns in normal use, but should be run with
    + ASan or valgrind for more confidence.
    + '
    ++
    ++TEST_PASSES_SANITIZE_LEAK=true
    + . ./test-lib.sh
    + 
    + # the general idea for tags and commits is to build up the "base" file
    +
      ## t/t3210-pack-refs.sh ##
     @@ t/t3210-pack-refs.sh: semantic is still the same.
      GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
    @@ t/t3210-pack-refs.sh: semantic is still the same.
      
      test_expect_success 'enable reflogs' '
     
    + ## t/t3800-mktag.sh ##
    +@@
    + 
    + test_description='git mktag: tag object verify test'
    + 
    ++TEST_PASSES_SANITIZE_LEAK=true
    + . ./test-lib.sh
    + 
    + ###########################################################
    +
      ## t/t4152-am-subjects.sh ##
     @@
      #!/bin/sh
    @@ t/t4257-am-interactive.sh
      
      test_expect_success 'set up patches to apply' '
     
    + ## t/t5302-pack-index.sh ##
    +@@
    + #
    + 
    + test_description='pack index with 64-bit offsets and object CRC'
    ++
    ++TEST_PASSES_SANITIZE_LEAK=true
    + . ./test-lib.sh
    + 
    + test_expect_success 'setup' '
    +
    + ## t/t5306-pack-nobase.sh ##
    +@@
    + test_description='git-pack-object with missing base
    + 
    + '
    ++
    ++TEST_PASSES_SANITIZE_LEAK=true
    + . ./test-lib.sh
    + 
    + # Create A-B chain
    +
      ## t/t5317-pack-objects-filter-objects.sh ##
     @@ t/t5317-pack-objects-filter-objects.sh: test_description='git pack-objects using object filtering'
      GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
    @@ t/t5502-quickfetch.sh: test_description='test quickfetch from local'
      
      test_expect_success setup '
     
    + ## t/t5573-pull-verify-signatures.sh ##
    +@@
    + #!/bin/sh
    + 
    + test_description='pull signature verification tests'
    ++
    ++TEST_PASSES_SANITIZE_LEAK=true
    + . ./test-lib.sh
    + . "$TEST_DIRECTORY/lib-gpg.sh"
    + 
    +
      ## t/t5604-clone-reference.sh ##
     @@ t/t5604-clone-reference.sh: test_description='test clone --reference'
      GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
    @@ t/t6021-rev-list-exclude-hidden.sh
      
      test_expect_success 'setup' '
     
    + ## t/t6501-freshen-objects.sh ##
    +@@ t/t6501-freshen-objects.sh: test_description='check pruning of dependent objects'
    + GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
    + export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
    + 
    ++TEST_PASSES_SANITIZE_LEAK=true
    + . ./test-lib.sh
    + 
    + # We care about reachability, so we do not want to use
    +
      ## t/t7403-submodule-sync.sh ##
     @@ t/t7403-submodule-sync.sh: These tests exercise the "git submodule sync" subcommand.
      GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
    @@ t/t7403-submodule-sync.sh: These tests exercise the "git submodule sync" subcomm
      
      test_expect_success setup '
     
    + ## t/t7612-merge-verify-signatures.sh ##
    +@@ t/t7612-merge-verify-signatures.sh: test_description='merge signature verification tests'
    + GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
    + export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
    + 
    ++TEST_PASSES_SANITIZE_LEAK=true
    + . ./test-lib.sh
    + . "$TEST_DIRECTORY/lib-gpg.sh"
    + 
    +
      ## t/t7701-repack-unpack-unreachable.sh ##
     @@ t/t7701-repack-unpack-unreachable.sh: test_description='git repack works correctly'
      GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
 2:  9eb758117dc !  2:  f0f1a388350 bundle.c: don't leak the "args" in the "struct child_process"
    @@ Commit message
         bundle.c: don't leak the "args" in the "struct child_process"
     
         Fix a leak that's been here since 7366096de9d (bundle API: change
    -    "flags" to be "extra_index_pack_args", 2021-09-05), if can't verify
    -    the bundle we didn't call child_process_clear() to clear the "args".
    +    "flags" to be "extra_index_pack_args", 2021-09-05). If we can't verify
    +    the bundle, we didn't call child_process_clear() to clear the "args".
     
    -    But rather than doing that let's verify the bundle before we start
    -    preparing the process we're going to spawn, if we get an error we
    -    don't need to push anything to the "args".
    +    But rather than adding an additional child_process_clear() call, let's
    +    verify the bundle before we start preparing the process we're going to
    +    spawn. If we fail to verify, we don't need to push anything to the
    +    child_process "args".
     
    +    Helped-by: Elijah Newren <newren@gmail.com>
         Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
     
      ## bundle.c ##
 3:  01b6229f18a =  3:  cf0dddf4e8c commit-graph: use free_commit_graph() instead of UNLEAK()
 4:  f4f3aef2861 =  4:  0430c1fec1b clone: use free() instead of UNLEAK()
 5:  8d10fbe0b8f =  5:  fb2d9875c73 various: add missing clear_pathspec(), fix leaks
 6:  eb5dc3ac192 =  6:  bca659788de name-rev: don't xstrdup() an already dup'd string
 7:  1fac90c306a !  7:  09950d92940 repack: fix leaks on error with "goto cleanup"
    @@ Metadata
      ## Commit message ##
         repack: fix leaks on error with "goto cleanup"
     
    -    Change cmd_repack() to "goto cleanup" rather than "return ret" on
    -    error, when we returned we'd potentially skip cleaning up the
    -    string_lists and other data we'd allocated in this function.
    +    In cmd_repack() when we hit an error, replace "return ret" with "goto
    +    cleanup" to ensure we free the necessary data structures.
     
    +    Helped-by: Elijah Newren <newren@gmail.com>
         Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
     
      ## builtin/repack.c ##
    @@ builtin/repack.c: int cmd_repack(int argc, const char **argv, const char *prefix
     +	return ret;
      }
     
    + ## t/t5312-prune-corruption.sh ##
    +@@ t/t5312-prune-corruption.sh: what currently happens. If that changes, these tests should be revisited.
    + GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
    + export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
    + 
    ++TEST_PASSES_SANITIZE_LEAK=true
    + . ./test-lib.sh
    + 
    + test_expect_success 'disable reflogs' '
    +
      ## t/t6011-rev-list-with-bad-commit.sh ##
     @@
      
 8:  02248aca3eb =  8:  cd3eb9e68ff worktree: fix a trivial leak in prune_worktrees()
 9:  b39d6d29dd5 =  9:  e80a719913b http-backend.c: fix "dir" and "cmd_arg" leaks in cmd_main()
10:  928dea2d4ee = 10:  9d9df0caf17 http-backend.c: fix cmd_main() memory leak, refactor reg{exec,free}()
11:  5770b9eb764 = 11:  65e25377791 commit-graph: fix a parse_options_concat() leak
12:  3ff86cb808c = 12:  3b1d47b9d62 show-branch: free() allocated "head" before return
13:  1f3e3524580 = 13:  a85e5f3b14e builtin/merge.c: use fixed strings, not "strbuf", fix leak
14:  15e4b8db805 = 14:  7dbc422d5b4 builtin/merge.c: free "&buf" on "Your local changes..." error
15:  d36ad1f818a <  -:  ----------- object-file.c: release the "tag" in check_tag()
16:  10959760dfc ! 15:  aa51668b70d grep.c: refactor free_grep_patterns()
    @@ Commit message
         grep.c: refactor free_grep_patterns()
     
         Refactor the free_grep_patterns() function to split out the freeing of
    -    the "struct grep_pat" it contains, right now we're only freeing the
    +    the "struct grep_pat" it contains. Right now we're only freeing the
         "pattern_list", but we should be freeing another member of the same
         type, which we'll do in the subsequent commit.
     
    @@ Commit message
     
                 if (!x)
                         return;
    -            free(y);
    +            free_pattern_expr(y);
     
    -    But after the cleanup in db84376f981 (which was a narrow segfault fix,
    -    and thus avoided refactoring this) we ended up with:
    +    While at it, instead of:
     
                 if (!x)
                         return;
    -            free(x);
    +            free_pattern_expr(x);
     
         Let's instead do:
     
                 if (x)
    -                    free(x);
    +                    free_pattern_expr(x);
     
    -    This doesn't matter for the subsequent change, but as we're
    -    refactoring this function let's make it easier to reason about, and to
    -    extend in the future, i.e. if we start to free free() members that
    -    come after "pattern_expression" in the "struct grep_opt".
    +    This will make it easier to free additional members from
    +    free_grep_patterns() in the future.
     
    +    Helped-by: Elijah Newren <newren@gmail.com>
         Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
     
      ## grep.c ##
17:  6a8f4a567aa ! 16:  0c51ea7fd2d grep API: plug memory leaks by freeing "header_list"
    @@ Metadata
      ## Commit message ##
         grep API: plug memory leaks by freeing "header_list"
     
    -    When the "header_list" struct member was added in [1] it wasn't made
    -    to free the list using loop added for the adjacent "pattern_list"
    -    member, see [2] for when we started freeing it.
    -
    -    This makes e.g. this command leak-free when run on git.git:
    +    When the "header_list" struct member was added in [1], freeing this
    +    field was neglected. Fix that now, so that commands like
     
                 ./git -P log -1 --color=always --author=A origin/master
     
    +    will run leak-free.
    +
         1. 80235ba79ef ("log --author=me --grep=it" should find intersection,
            not union, 2010-01-17)
    -    2. b48fb5b6a95 (grep: free expressions and patterns when done.,
    -       2006-09-27)
     
    +    Helped-by: Elijah Newren <newren@gmail.com>
         Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
     
      ## grep.c ##
18:  3c3d48df04b ! 17:  4b2db91f5cb receive-pack: free() the "ref_name" in "struct command"
    @@ Commit message
         receive-pack: free() the "ref_name" in "struct command"
     
         Fix a memory leak that's been with us since this code was introduced
    -    in 575f497456e (Add first cut at "git-receive-pack", 2005-06-29), see
    +    in 575f497456e (Add first cut at "git-receive-pack", 2005-06-29). See
         eb1af2df0b1 (git-receive-pack: start parsing ref update commands,
         2005-06-29) for the later change that refactored the code to add the
         "ref_name" member.
 -:  ----------- > 18:  aa33f7e05c8 push: refactor refspec_append_mapped() for subsequent leak-fix
19:  f29500a4abc ! 19:  67076dfba6d push: free_refs() the "local_refs" in set_refspecs()
    @@ Commit message
         Fix a memory leak that's been with us since this code was added in
         ca02465b413 (push: use remote.$name.push as a refmap, 2013-12-03).
     
    +    The "remote = remote_get(...)" added in the same commit would seem to
    +    leak based only on the context here, but that function is a wrapper
    +    for sticking the remotes we fetch into "the_repository->remote_state".
    +
    +    See fd3cb0501e1 (remote: move static variables into per-repository
    +    struct, 2021-11-17) for the addition of code in repository.c that
    +    free's the "remote" allocated here.
    +
         Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
     
      ## builtin/push.c ##
-- 
2.39.1.1392.g63e6d408230


^ permalink raw reply	[flat|nested] 193+ messages in thread

* [PATCH v6 01/19] tests: mark tests as passing with SANITIZE=leak
  2023-02-02  9:52         ` [PATCH v6 00/19] leak fixes: various simple leak fixes Ævar Arnfjörð Bjarmason
@ 2023-02-02  9:52           ` Ævar Arnfjörð Bjarmason
  2023-02-02  9:52           ` [PATCH v6 02/19] bundle.c: don't leak the "args" in the "struct child_process" Ævar Arnfjörð Bjarmason
                             ` (18 subsequent siblings)
  19 siblings, 0 replies; 193+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2023-02-02  9:52 UTC (permalink / raw)
  To: git
  Cc: René Scharfe, Junio C Hamano, Eric Sunshine, Elijah Newren,
	Ævar Arnfjörð Bjarmason

When the "ab/various-leak-fixes" topic was merged in [1] only t6021
would fail if the tests were run in the
"GIT_TEST_PASSING_SANITIZE_LEAK=check" mode, i.e. to check whether we
marked all leak-free tests with "TEST_PASSES_SANITIZE_LEAK=true".

Since then we've had various tests starting to pass under
SANITIZE=leak. Let's mark those as passing, this is when they started
to pass, narrowed down with "git bisect":

- t5317-pack-objects-filter-objects.sh: In
  faebba436e6 (list-objects-filter: plug pattern_list leak, 2022-12-01).

- t3210-pack-refs.sh, t5613-info-alternate.sh,
  t7403-submodule-sync.sh: In 189e97bc4ba (diff: remove parseopts member
  from struct diff_options, 2022-12-01).

- t1408-packed-refs.sh: In ab91f6b7c42 (Merge branch
  'rs/diff-parseopts', 2022-12-19).

- t0023-crlf-am.sh, t4152-am-subjects.sh, t4254-am-corrupt.sh,
  t4256-am-format-flowed.sh, t4257-am-interactive.sh,
  t5403-post-checkout-hook.sh: In a658e881c13 (am: don't pass strvec to
  apply_parse_options(), 2022-12-13)

- t1301-shared-repo.sh, t1302-repo-version.sh: In b07a819c05f (reflog:
  clear leftovers in reflog_expiry_cleanup(), 2022-12-13).

- t1304-default-acl.sh, t1410-reflog.sh,
  t5330-no-lazy-fetch-with-commit-graph.sh, t5502-quickfetch.sh,
  t5604-clone-reference.sh, t6014-rev-list-all.sh,
  t7701-repack-unpack-unreachable.sh: In b0c61be3209 (Merge branch
  'rs/reflog-expiry-cleanup', 2022-12-26)

- t3800-mktag.sh, t5302-pack-index.sh, t5306-pack-nobase.sh,
  t5573-pull-verify-signatures.sh, t7612-merge-verify-signatures.sh: In
  69bbbe484ba (hash-object: use fsck for object checks, 2023-01-18).

- t1451-fsck-buffer.sh: In 8e4309038f0 (fsck: do not assume
  NUL-termination of buffers, 2023-01-19).

- t6501-freshen-objects.sh: In abf2bb895b4 (Merge branch
  'jk/hash-object-fsck', 2023-01-30)

1. 9ea1378d046 (Merge branch 'ab/various-leak-fixes', 2022-12-14)

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 t/t0023-crlf-am.sh                         | 1 +
 t/t1301-shared-repo.sh                     | 1 +
 t/t1302-repo-version.sh                    | 1 +
 t/t1304-default-acl.sh                     | 1 +
 t/t1408-packed-refs.sh                     | 1 +
 t/t1410-reflog.sh                          | 1 +
 t/t1451-fsck-buffer.sh                     | 2 ++
 t/t3210-pack-refs.sh                       | 1 +
 t/t3800-mktag.sh                           | 1 +
 t/t4152-am-subjects.sh                     | 2 ++
 t/t4254-am-corrupt.sh                      | 2 ++
 t/t4256-am-format-flowed.sh                | 1 +
 t/t4257-am-interactive.sh                  | 2 ++
 t/t5302-pack-index.sh                      | 2 ++
 t/t5306-pack-nobase.sh                     | 2 ++
 t/t5317-pack-objects-filter-objects.sh     | 1 +
 t/t5330-no-lazy-fetch-with-commit-graph.sh | 1 +
 t/t5403-post-checkout-hook.sh              | 1 +
 t/t5502-quickfetch.sh                      | 1 +
 t/t5573-pull-verify-signatures.sh          | 2 ++
 t/t5604-clone-reference.sh                 | 1 +
 t/t5613-info-alternate.sh                  | 2 ++
 t/t6014-rev-list-all.sh                    | 1 +
 t/t6021-rev-list-exclude-hidden.sh         | 1 +
 t/t6501-freshen-objects.sh                 | 1 +
 t/t7403-submodule-sync.sh                  | 1 +
 t/t7612-merge-verify-signatures.sh         | 1 +
 t/t7701-repack-unpack-unreachable.sh       | 1 +
 28 files changed, 36 insertions(+)

diff --git a/t/t0023-crlf-am.sh b/t/t0023-crlf-am.sh
index f9bbb91f64e..575805513a3 100755
--- a/t/t0023-crlf-am.sh
+++ b/t/t0023-crlf-am.sh
@@ -2,6 +2,7 @@
 
 test_description='Test am with auto.crlf'
 
+TEST_PASSES_SANITIZE_LEAK=true
 . ./test-lib.sh
 
 cat >patchfile <<\EOF
diff --git a/t/t1301-shared-repo.sh b/t/t1301-shared-repo.sh
index 58d6da7feb1..1b6437ec079 100755
--- a/t/t1301-shared-repo.sh
+++ b/t/t1301-shared-repo.sh
@@ -9,6 +9,7 @@ GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
 export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
 
 TEST_CREATE_REPO_NO_TEMPLATE=1
+TEST_PASSES_SANITIZE_LEAK=true
 . ./test-lib.sh
 
 # Remove a default ACL from the test dir if possible.
diff --git a/t/t1302-repo-version.sh b/t/t1302-repo-version.sh
index 7cf80bf66a6..70389fa2ebb 100755
--- a/t/t1302-repo-version.sh
+++ b/t/t1302-repo-version.sh
@@ -5,6 +5,7 @@
 
 test_description='Test repository version check'
 
+TEST_PASSES_SANITIZE_LEAK=true
 . ./test-lib.sh
 
 test_expect_success 'setup' '
diff --git a/t/t1304-default-acl.sh b/t/t1304-default-acl.sh
index c69ae41306c..31b89dd9693 100755
--- a/t/t1304-default-acl.sh
+++ b/t/t1304-default-acl.sh
@@ -9,6 +9,7 @@ test_description='Test repository with default ACL'
 # => this must come before . ./test-lib.sh
 umask 077
 
+TEST_PASSES_SANITIZE_LEAK=true
 . ./test-lib.sh
 
 # We need an arbitrary other user give permission to using ACLs. root
diff --git a/t/t1408-packed-refs.sh b/t/t1408-packed-refs.sh
index 41ba1f1d7fc..9469c79a585 100755
--- a/t/t1408-packed-refs.sh
+++ b/t/t1408-packed-refs.sh
@@ -5,6 +5,7 @@ test_description='packed-refs entries are covered by loose refs'
 GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
 export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
 
+TEST_PASSES_SANITIZE_LEAK=true
 . ./test-lib.sh
 
 test_expect_success setup '
diff --git a/t/t1410-reflog.sh b/t/t1410-reflog.sh
index aa59954f6c5..6c45965b1e4 100755
--- a/t/t1410-reflog.sh
+++ b/t/t1410-reflog.sh
@@ -7,6 +7,7 @@ test_description='Test prune and reflog expiration'
 GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
 export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
 
+TEST_PASSES_SANITIZE_LEAK=true
 . ./test-lib.sh
 
 check_have () {
diff --git a/t/t1451-fsck-buffer.sh b/t/t1451-fsck-buffer.sh
index 9ac270abab6..3413da40e4a 100755
--- a/t/t1451-fsck-buffer.sh
+++ b/t/t1451-fsck-buffer.sh
@@ -14,6 +14,8 @@ so.
 These tests _might_ catch such overruns in normal use, but should be run with
 ASan or valgrind for more confidence.
 '
+
+TEST_PASSES_SANITIZE_LEAK=true
 . ./test-lib.sh
 
 # the general idea for tags and commits is to build up the "base" file
diff --git a/t/t3210-pack-refs.sh b/t/t3210-pack-refs.sh
index 577f32dc71f..07a0ff93def 100755
--- a/t/t3210-pack-refs.sh
+++ b/t/t3210-pack-refs.sh
@@ -12,6 +12,7 @@ semantic is still the same.
 GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
 export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
 
+TEST_PASSES_SANITIZE_LEAK=true
 . ./test-lib.sh
 
 test_expect_success 'enable reflogs' '
diff --git a/t/t3800-mktag.sh b/t/t3800-mktag.sh
index e3cf0ffbe59..d3e428ff46e 100755
--- a/t/t3800-mktag.sh
+++ b/t/t3800-mktag.sh
@@ -4,6 +4,7 @@
 
 test_description='git mktag: tag object verify test'
 
+TEST_PASSES_SANITIZE_LEAK=true
 . ./test-lib.sh
 
 ###########################################################
diff --git a/t/t4152-am-subjects.sh b/t/t4152-am-subjects.sh
index 4c68245acad..9f2edba1f83 100755
--- a/t/t4152-am-subjects.sh
+++ b/t/t4152-am-subjects.sh
@@ -1,6 +1,8 @@
 #!/bin/sh
 
 test_description='test subject preservation with format-patch | am'
+
+TEST_PASSES_SANITIZE_LEAK=true
 . ./test-lib.sh
 
 make_patches() {
diff --git a/t/t4254-am-corrupt.sh b/t/t4254-am-corrupt.sh
index 54be7da1611..45f1d4f95e5 100755
--- a/t/t4254-am-corrupt.sh
+++ b/t/t4254-am-corrupt.sh
@@ -1,6 +1,8 @@
 #!/bin/sh
 
 test_description='git am with corrupt input'
+
+TEST_PASSES_SANITIZE_LEAK=true
 . ./test-lib.sh
 
 make_mbox_with_nul () {
diff --git a/t/t4256-am-format-flowed.sh b/t/t4256-am-format-flowed.sh
index 2369c4e17ad..1015273bc82 100755
--- a/t/t4256-am-format-flowed.sh
+++ b/t/t4256-am-format-flowed.sh
@@ -2,6 +2,7 @@
 
 test_description='test format=flowed support of git am'
 
+TEST_PASSES_SANITIZE_LEAK=true
 . ./test-lib.sh
 
 test_expect_success 'setup' '
diff --git a/t/t4257-am-interactive.sh b/t/t4257-am-interactive.sh
index aed8f4de3d6..f26d7fd2dbd 100755
--- a/t/t4257-am-interactive.sh
+++ b/t/t4257-am-interactive.sh
@@ -1,6 +1,8 @@
 #!/bin/sh
 
 test_description='am --interactive tests'
+
+TEST_PASSES_SANITIZE_LEAK=true
 . ./test-lib.sh
 
 test_expect_success 'set up patches to apply' '
diff --git a/t/t5302-pack-index.sh b/t/t5302-pack-index.sh
index 59e9e77223b..f89809be53c 100755
--- a/t/t5302-pack-index.sh
+++ b/t/t5302-pack-index.sh
@@ -4,6 +4,8 @@
 #
 
 test_description='pack index with 64-bit offsets and object CRC'
+
+TEST_PASSES_SANITIZE_LEAK=true
 . ./test-lib.sh
 
 test_expect_success 'setup' '
diff --git a/t/t5306-pack-nobase.sh b/t/t5306-pack-nobase.sh
index 51973f4a512..846c5ca7d34 100755
--- a/t/t5306-pack-nobase.sh
+++ b/t/t5306-pack-nobase.sh
@@ -6,6 +6,8 @@
 test_description='git-pack-object with missing base
 
 '
+
+TEST_PASSES_SANITIZE_LEAK=true
 . ./test-lib.sh
 
 # Create A-B chain
diff --git a/t/t5317-pack-objects-filter-objects.sh b/t/t5317-pack-objects-filter-objects.sh
index 5b707d911b5..b26d476c646 100755
--- a/t/t5317-pack-objects-filter-objects.sh
+++ b/t/t5317-pack-objects-filter-objects.sh
@@ -5,6 +5,7 @@ test_description='git pack-objects using object filtering'
 GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
 export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
 
+TEST_PASSES_SANITIZE_LEAK=true
 . ./test-lib.sh
 
 # Test blob:none filter.
diff --git a/t/t5330-no-lazy-fetch-with-commit-graph.sh b/t/t5330-no-lazy-fetch-with-commit-graph.sh
index 2cc7fd7a476..5eb28f0512d 100755
--- a/t/t5330-no-lazy-fetch-with-commit-graph.sh
+++ b/t/t5330-no-lazy-fetch-with-commit-graph.sh
@@ -2,6 +2,7 @@
 
 test_description='test for no lazy fetch with the commit-graph'
 
+TEST_PASSES_SANITIZE_LEAK=true
 . ./test-lib.sh
 
 test_expect_success 'setup: prepare a repository with a commit' '
diff --git a/t/t5403-post-checkout-hook.sh b/t/t5403-post-checkout-hook.sh
index 978f240cdac..cfaae547398 100755
--- a/t/t5403-post-checkout-hook.sh
+++ b/t/t5403-post-checkout-hook.sh
@@ -7,6 +7,7 @@ test_description='Test the post-checkout hook.'
 GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
 export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
 
+TEST_PASSES_SANITIZE_LEAK=true
 . ./test-lib.sh
 
 test_expect_success setup '
diff --git a/t/t5502-quickfetch.sh b/t/t5502-quickfetch.sh
index b160f8b7fb7..7b3ff21b984 100755
--- a/t/t5502-quickfetch.sh
+++ b/t/t5502-quickfetch.sh
@@ -5,6 +5,7 @@ test_description='test quickfetch from local'
 GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
 export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
 
+TEST_PASSES_SANITIZE_LEAK=true
 . ./test-lib.sh
 
 test_expect_success setup '
diff --git a/t/t5573-pull-verify-signatures.sh b/t/t5573-pull-verify-signatures.sh
index a53dd8550d0..1221ac05978 100755
--- a/t/t5573-pull-verify-signatures.sh
+++ b/t/t5573-pull-verify-signatures.sh
@@ -1,6 +1,8 @@
 #!/bin/sh
 
 test_description='pull signature verification tests'
+
+TEST_PASSES_SANITIZE_LEAK=true
 . ./test-lib.sh
 . "$TEST_DIRECTORY/lib-gpg.sh"
 
diff --git a/t/t5604-clone-reference.sh b/t/t5604-clone-reference.sh
index 2734e37e880..dc86dea1333 100755
--- a/t/t5604-clone-reference.sh
+++ b/t/t5604-clone-reference.sh
@@ -7,6 +7,7 @@ test_description='test clone --reference'
 GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
 export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
 
+TEST_PASSES_SANITIZE_LEAK=true
 . ./test-lib.sh
 
 base_dir=$(pwd)
diff --git a/t/t5613-info-alternate.sh b/t/t5613-info-alternate.sh
index 895f46bb911..7708cbafa98 100755
--- a/t/t5613-info-alternate.sh
+++ b/t/t5613-info-alternate.sh
@@ -4,6 +4,8 @@
 #
 
 test_description='test transitive info/alternate entries'
+
+TEST_PASSES_SANITIZE_LEAK=true
 . ./test-lib.sh
 
 test_expect_success 'preparing first repository' '
diff --git a/t/t6014-rev-list-all.sh b/t/t6014-rev-list-all.sh
index c9bedd29cba..16b8bd1d090 100755
--- a/t/t6014-rev-list-all.sh
+++ b/t/t6014-rev-list-all.sh
@@ -2,6 +2,7 @@
 
 test_description='--all includes detached HEADs'
 
+TEST_PASSES_SANITIZE_LEAK=true
 . ./test-lib.sh
 
 
diff --git a/t/t6021-rev-list-exclude-hidden.sh b/t/t6021-rev-list-exclude-hidden.sh
index 32b2b094138..11c50b7c0dd 100755
--- a/t/t6021-rev-list-exclude-hidden.sh
+++ b/t/t6021-rev-list-exclude-hidden.sh
@@ -2,6 +2,7 @@
 
 test_description='git rev-list --exclude-hidden test'
 
+TEST_PASSES_SANITIZE_LEAK=true
 . ./test-lib.sh
 
 test_expect_success 'setup' '
diff --git a/t/t6501-freshen-objects.sh b/t/t6501-freshen-objects.sh
index 10662456aee..3968b47ed53 100755
--- a/t/t6501-freshen-objects.sh
+++ b/t/t6501-freshen-objects.sh
@@ -28,6 +28,7 @@ test_description='check pruning of dependent objects'
 GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
 export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
 
+TEST_PASSES_SANITIZE_LEAK=true
 . ./test-lib.sh
 
 # We care about reachability, so we do not want to use
diff --git a/t/t7403-submodule-sync.sh b/t/t7403-submodule-sync.sh
index ea92ef52a5e..ff09443a0a4 100755
--- a/t/t7403-submodule-sync.sh
+++ b/t/t7403-submodule-sync.sh
@@ -11,6 +11,7 @@ These tests exercise the "git submodule sync" subcommand.
 GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
 export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
 
+TEST_PASSES_SANITIZE_LEAK=true
 . ./test-lib.sh
 
 test_expect_success setup '
diff --git a/t/t7612-merge-verify-signatures.sh b/t/t7612-merge-verify-signatures.sh
index 61330f71b17..f5c90cc22a1 100755
--- a/t/t7612-merge-verify-signatures.sh
+++ b/t/t7612-merge-verify-signatures.sh
@@ -4,6 +4,7 @@ test_description='merge signature verification tests'
 GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
 export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
 
+TEST_PASSES_SANITIZE_LEAK=true
 . ./test-lib.sh
 . "$TEST_DIRECTORY/lib-gpg.sh"
 
diff --git a/t/t7701-repack-unpack-unreachable.sh b/t/t7701-repack-unpack-unreachable.sh
index b7ac4f598a8..ebb267855fe 100755
--- a/t/t7701-repack-unpack-unreachable.sh
+++ b/t/t7701-repack-unpack-unreachable.sh
@@ -5,6 +5,7 @@ test_description='git repack works correctly'
 GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
 export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
 
+TEST_PASSES_SANITIZE_LEAK=true
 . ./test-lib.sh
 
 fsha1=
-- 
2.39.1.1392.g63e6d408230


^ permalink raw reply related	[flat|nested] 193+ messages in thread

* [PATCH v6 02/19] bundle.c: don't leak the "args" in the "struct child_process"
  2023-02-02  9:52         ` [PATCH v6 00/19] leak fixes: various simple leak fixes Ævar Arnfjörð Bjarmason
  2023-02-02  9:52           ` [PATCH v6 01/19] tests: mark tests as passing with SANITIZE=leak Ævar Arnfjörð Bjarmason
@ 2023-02-02  9:52           ` Ævar Arnfjörð Bjarmason
  2023-02-02  9:52           ` [PATCH v6 03/19] commit-graph: use free_commit_graph() instead of UNLEAK() Ævar Arnfjörð Bjarmason
                             ` (17 subsequent siblings)
  19 siblings, 0 replies; 193+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2023-02-02  9:52 UTC (permalink / raw)
  To: git
  Cc: René Scharfe, Junio C Hamano, Eric Sunshine, Elijah Newren,
	Ævar Arnfjörð Bjarmason

Fix a leak that's been here since 7366096de9d (bundle API: change
"flags" to be "extra_index_pack_args", 2021-09-05). If we can't verify
the bundle, we didn't call child_process_clear() to clear the "args".

But rather than adding an additional child_process_clear() call, let's
verify the bundle before we start preparing the process we're going to
spawn. If we fail to verify, we don't need to push anything to the
child_process "args".

Helped-by: Elijah Newren <newren@gmail.com>
Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 bundle.c | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/bundle.c b/bundle.c
index 4ef7256aa11..9ebb10a8f72 100644
--- a/bundle.c
+++ b/bundle.c
@@ -627,6 +627,10 @@ int unbundle(struct repository *r, struct bundle_header *header,
 	     enum verify_bundle_flags flags)
 {
 	struct child_process ip = CHILD_PROCESS_INIT;
+
+	if (verify_bundle(r, header, flags))
+		return -1;
+
 	strvec_pushl(&ip.args, "index-pack", "--fix-thin", "--stdin", NULL);
 
 	/* If there is a filter, then we need to create the promisor pack. */
@@ -638,8 +642,6 @@ int unbundle(struct repository *r, struct bundle_header *header,
 		strvec_clear(extra_index_pack_args);
 	}
 
-	if (verify_bundle(r, header, flags))
-		return -1;
 	ip.in = bundle_fd;
 	ip.no_stdout = 1;
 	ip.git_cmd = 1;
-- 
2.39.1.1392.g63e6d408230


^ permalink raw reply related	[flat|nested] 193+ messages in thread

* [PATCH v6 03/19] commit-graph: use free_commit_graph() instead of UNLEAK()
  2023-02-02  9:52         ` [PATCH v6 00/19] leak fixes: various simple leak fixes Ævar Arnfjörð Bjarmason
  2023-02-02  9:52           ` [PATCH v6 01/19] tests: mark tests as passing with SANITIZE=leak Ævar Arnfjörð Bjarmason
  2023-02-02  9:52           ` [PATCH v6 02/19] bundle.c: don't leak the "args" in the "struct child_process" Ævar Arnfjörð Bjarmason
@ 2023-02-02  9:52           ` Ævar Arnfjörð Bjarmason
  2023-02-02  9:52           ` [PATCH v6 04/19] clone: use free() " Ævar Arnfjörð Bjarmason
                             ` (16 subsequent siblings)
  19 siblings, 0 replies; 193+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2023-02-02  9:52 UTC (permalink / raw)
  To: git
  Cc: René Scharfe, Junio C Hamano, Eric Sunshine, Elijah Newren,
	Ævar Arnfjörð Bjarmason

In 0bfb48e6723 (builtin/commit-graph.c: UNLEAK variables, 2018-10-03)
this was made to UNLEAK(), but we can just as easily invoke the
free_commit_graph() function added in c3756d5b7fc (commit-graph: add
free_commit_graph, 2018-07-11) instead.

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 builtin/commit-graph.c | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/builtin/commit-graph.c b/builtin/commit-graph.c
index e8f77f535f3..0102ac8540e 100644
--- a/builtin/commit-graph.c
+++ b/builtin/commit-graph.c
@@ -67,6 +67,7 @@ static int graph_verify(int argc, const char **argv, const char *prefix)
 	int fd;
 	struct stat st;
 	int flags = 0;
+	int ret;
 
 	static struct option builtin_commit_graph_verify_options[] = {
 		OPT_BOOL(0, "shallow", &opts.shallow,
@@ -111,8 +112,9 @@ static int graph_verify(int argc, const char **argv, const char *prefix)
 	if (!graph)
 		return !!open_ok;
 
-	UNLEAK(graph);
-	return verify_commit_graph(the_repository, graph, flags);
+	ret = verify_commit_graph(the_repository, graph, flags);
+	free_commit_graph(graph);
+	return ret;
 }
 
 extern int read_replace_refs;
-- 
2.39.1.1392.g63e6d408230


^ permalink raw reply related	[flat|nested] 193+ messages in thread

* [PATCH v6 04/19] clone: use free() instead of UNLEAK()
  2023-02-02  9:52         ` [PATCH v6 00/19] leak fixes: various simple leak fixes Ævar Arnfjörð Bjarmason
                             ` (2 preceding siblings ...)
  2023-02-02  9:52           ` [PATCH v6 03/19] commit-graph: use free_commit_graph() instead of UNLEAK() Ævar Arnfjörð Bjarmason
@ 2023-02-02  9:52           ` Ævar Arnfjörð Bjarmason
  2023-02-02  9:52           ` [PATCH v6 05/19] various: add missing clear_pathspec(), fix leaks Ævar Arnfjörð Bjarmason
                             ` (15 subsequent siblings)
  19 siblings, 0 replies; 193+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2023-02-02  9:52 UTC (permalink / raw)
  To: git
  Cc: René Scharfe, Junio C Hamano, Eric Sunshine, Elijah Newren,
	Ævar Arnfjörð Bjarmason

Change an UNLEAK() added in 0c4542738e6 (clone: free or UNLEAK further
pointers when finished, 2021-03-14) to use a "to_free" pattern
instead. In this case the "repo" can be either this absolute_pathdup()
value, or in the "else if" branch seen in the context the the
"argv[0]" argument to "main()".

We can only free() the value in the former case, hence the "to_free"
pattern.

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 builtin/clone.c | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/builtin/clone.c b/builtin/clone.c
index 5453ba5277f..ba82f5e4108 100644
--- a/builtin/clone.c
+++ b/builtin/clone.c
@@ -892,6 +892,7 @@ int cmd_clone(int argc, const char **argv, const char *prefix)
 	int is_bundle = 0, is_local;
 	int reject_shallow = 0;
 	const char *repo_name, *repo, *work_tree, *git_dir;
+	char *repo_to_free = NULL;
 	char *path = NULL, *dir, *display_repo = NULL;
 	int dest_exists, real_dest_exists = 0;
 	const struct ref *refs, *remote_head;
@@ -949,7 +950,7 @@ int cmd_clone(int argc, const char **argv, const char *prefix)
 	path = get_repo_path(repo_name, &is_bundle);
 	if (path) {
 		FREE_AND_NULL(path);
-		repo = absolute_pathdup(repo_name);
+		repo = repo_to_free = absolute_pathdup(repo_name);
 	} else if (strchr(repo_name, ':')) {
 		repo = repo_name;
 		display_repo = transport_anonymize_url(repo);
@@ -1413,7 +1414,7 @@ int cmd_clone(int argc, const char **argv, const char *prefix)
 	free(unborn_head);
 	free(dir);
 	free(path);
-	UNLEAK(repo);
+	free(repo_to_free);
 	junk_mode = JUNK_LEAVE_ALL;
 
 	transport_ls_refs_options_release(&transport_ls_refs_options);
-- 
2.39.1.1392.g63e6d408230


^ permalink raw reply related	[flat|nested] 193+ messages in thread

* [PATCH v6 05/19] various: add missing clear_pathspec(), fix leaks
  2023-02-02  9:52         ` [PATCH v6 00/19] leak fixes: various simple leak fixes Ævar Arnfjörð Bjarmason
                             ` (3 preceding siblings ...)
  2023-02-02  9:52           ` [PATCH v6 04/19] clone: use free() " Ævar Arnfjörð Bjarmason
@ 2023-02-02  9:52           ` Ævar Arnfjörð Bjarmason
  2023-02-02  9:52           ` [PATCH v6 06/19] name-rev: don't xstrdup() an already dup'd string Ævar Arnfjörð Bjarmason
                             ` (14 subsequent siblings)
  19 siblings, 0 replies; 193+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2023-02-02  9:52 UTC (permalink / raw)
  To: git
  Cc: René Scharfe, Junio C Hamano, Eric Sunshine, Elijah Newren,
	Ævar Arnfjörð Bjarmason

Fix memory leaks resulting from a missing clear_pathspec().

- archive.c: Plug a leak in the "struct archiver_args", and
  clear_pathspec() the "pathspec" member that the "parse_pathspec_arg()"
  call in this function populates.

- builtin/clean.c: Fix a memory leak that's been with us since
  893d839970c (clean: convert to use parse_pathspec, 2013-07-14).

- builtin/reset.c: Add clear_pathspec() calls to cmd_reset(),
  including to the codepaths where we'd return early.

- builtin/stash.c: Call clear_pathspec() on the pathspec initialized
  in push_stash().

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 archive.c                       |  1 +
 builtin/clean.c                 |  1 +
 builtin/reset.c                 | 11 ++++++++---
 builtin/stash.c                 |  7 +++++--
 t/t5001-archive-attr.sh         |  1 +
 t/t5004-archive-corner-cases.sh |  2 ++
 t/t7105-reset-patch.sh          |  2 ++
 t/t7106-reset-unborn-branch.sh  |  2 ++
 t/t7107-reset-pathspec-file.sh  |  1 +
 t/t7301-clean-interactive.sh    |  1 +
 10 files changed, 24 insertions(+), 5 deletions(-)

diff --git a/archive.c b/archive.c
index 81ff76fce99..f2a8756d84f 100644
--- a/archive.c
+++ b/archive.c
@@ -710,6 +710,7 @@ int write_archive(int argc, const char **argv, const char *prefix,
 
 	string_list_clear_func(&args.extra_files, extra_file_info_clear);
 	free(args.refname);
+	clear_pathspec(&args.pathspec);
 
 	return rc;
 }
diff --git a/builtin/clean.c b/builtin/clean.c
index b2701a28158..b15eab328b7 100644
--- a/builtin/clean.c
+++ b/builtin/clean.c
@@ -1092,5 +1092,6 @@ int cmd_clean(int argc, const char **argv, const char *prefix)
 	strbuf_release(&buf);
 	string_list_clear(&del_list, 0);
 	string_list_clear(&exclude_list, 0);
+	clear_pathspec(&pathspec);
 	return (errors != 0);
 }
diff --git a/builtin/reset.c b/builtin/reset.c
index fea20a9ba0b..e9c10618cd3 100644
--- a/builtin/reset.c
+++ b/builtin/reset.c
@@ -390,7 +390,8 @@ int cmd_reset(int argc, const char **argv, const char *prefix)
 		if (reset_type != NONE)
 			die(_("options '%s' and '%s' cannot be used together"), "--patch", "--{hard,mixed,soft}");
 		trace2_cmd_mode("patch-interactive");
-		return run_add_interactive(rev, "--patch=reset", &pathspec);
+		update_ref_status = run_add_interactive(rev, "--patch=reset", &pathspec);
+		goto cleanup;
 	}
 
 	/* git reset tree [--] paths... can be used to
@@ -439,8 +440,10 @@ int cmd_reset(int argc, const char **argv, const char *prefix)
 				       LOCK_DIE_ON_ERROR);
 		if (reset_type == MIXED) {
 			int flags = quiet ? REFRESH_QUIET : REFRESH_IN_PORCELAIN;
-			if (read_from_tree(&pathspec, &oid, intent_to_add))
-				return 1;
+			if (read_from_tree(&pathspec, &oid, intent_to_add)) {
+				update_ref_status = 1;
+				goto cleanup;
+			}
 			the_index.updated_skipworktree = 1;
 			if (!no_refresh && get_git_work_tree()) {
 				uint64_t t_begin, t_delta_in_ms;
@@ -488,5 +491,7 @@ int cmd_reset(int argc, const char **argv, const char *prefix)
 
 	discard_index(&the_index);
 
+cleanup:
+	clear_pathspec(&pathspec);
 	return update_ref_status;
 }
diff --git a/builtin/stash.c b/builtin/stash.c
index 839569a9803..71a4ee6b1a5 100644
--- a/builtin/stash.c
+++ b/builtin/stash.c
@@ -1727,6 +1727,7 @@ static int push_stash(int argc, const char **argv, const char *prefix,
 		OPT_PATHSPEC_FILE_NUL(&pathspec_file_nul),
 		OPT_END()
 	};
+	int ret;
 
 	if (argc) {
 		force_assume = !strcmp(argv[0], "-p");
@@ -1766,8 +1767,10 @@ static int push_stash(int argc, const char **argv, const char *prefix,
 		die(_("the option '%s' requires '%s'"), "--pathspec-file-nul", "--pathspec-from-file");
 	}
 
-	return do_push_stash(&ps, stash_msg, quiet, keep_index, patch_mode,
-			     include_untracked, only_staged);
+	ret = do_push_stash(&ps, stash_msg, quiet, keep_index, patch_mode,
+			    include_untracked, only_staged);
+	clear_pathspec(&ps);
+	return ret;
 }
 
 static int push_stash_unassumed(int argc, const char **argv, const char *prefix)
diff --git a/t/t5001-archive-attr.sh b/t/t5001-archive-attr.sh
index 2f6eef5e372..04d300eeda7 100755
--- a/t/t5001-archive-attr.sh
+++ b/t/t5001-archive-attr.sh
@@ -3,6 +3,7 @@
 test_description='git archive attribute tests'
 
 TEST_CREATE_REPO_NO_TEMPLATE=1
+TEST_PASSES_SANITIZE_LEAK=true
 . ./test-lib.sh
 
 SUBSTFORMAT='%H (%h)%n'
diff --git a/t/t5004-archive-corner-cases.sh b/t/t5004-archive-corner-cases.sh
index ae508e21623..9f2c6da80e8 100755
--- a/t/t5004-archive-corner-cases.sh
+++ b/t/t5004-archive-corner-cases.sh
@@ -1,6 +1,8 @@
 #!/bin/sh
 
 test_description='test corner cases of git-archive'
+
+TEST_PASSES_SANITIZE_LEAK=true
 . ./test-lib.sh
 
 # the 10knuls.tar file is used to test for an empty git generated tar
diff --git a/t/t7105-reset-patch.sh b/t/t7105-reset-patch.sh
index fc2a6cf5c7a..9b46da7aaa7 100755
--- a/t/t7105-reset-patch.sh
+++ b/t/t7105-reset-patch.sh
@@ -1,6 +1,8 @@
 #!/bin/sh
 
 test_description='git reset --patch'
+
+TEST_PASSES_SANITIZE_LEAK=true
 . ./lib-patch-mode.sh
 
 test_expect_success PERL 'setup' '
diff --git a/t/t7106-reset-unborn-branch.sh b/t/t7106-reset-unborn-branch.sh
index ecb85c3b823..a0b67a0b843 100755
--- a/t/t7106-reset-unborn-branch.sh
+++ b/t/t7106-reset-unborn-branch.sh
@@ -1,6 +1,8 @@
 #!/bin/sh
 
 test_description='git reset should work on unborn branch'
+
+TEST_PASSES_SANITIZE_LEAK=true
 . ./test-lib.sh
 
 test_expect_success 'setup' '
diff --git a/t/t7107-reset-pathspec-file.sh b/t/t7107-reset-pathspec-file.sh
index 523efbecde1..af5ea406db3 100755
--- a/t/t7107-reset-pathspec-file.sh
+++ b/t/t7107-reset-pathspec-file.sh
@@ -2,6 +2,7 @@
 
 test_description='reset --pathspec-from-file'
 
+TEST_PASSES_SANITIZE_LEAK=true
 . ./test-lib.sh
 
 test_tick
diff --git a/t/t7301-clean-interactive.sh b/t/t7301-clean-interactive.sh
index a07e8b86de2..d82a3210a1d 100755
--- a/t/t7301-clean-interactive.sh
+++ b/t/t7301-clean-interactive.sh
@@ -2,6 +2,7 @@
 
 test_description='git clean -i basic tests'
 
+TEST_PASSES_SANITIZE_LEAK=true
 . ./test-lib.sh
 . "$TEST_DIRECTORY"/lib-terminal.sh
 
-- 
2.39.1.1392.g63e6d408230


^ permalink raw reply related	[flat|nested] 193+ messages in thread

* [PATCH v6 06/19] name-rev: don't xstrdup() an already dup'd string
  2023-02-02  9:52         ` [PATCH v6 00/19] leak fixes: various simple leak fixes Ævar Arnfjörð Bjarmason
                             ` (4 preceding siblings ...)
  2023-02-02  9:52           ` [PATCH v6 05/19] various: add missing clear_pathspec(), fix leaks Ævar Arnfjörð Bjarmason
@ 2023-02-02  9:52           ` Ævar Arnfjörð Bjarmason
  2023-02-02  9:52           ` [PATCH v6 07/19] repack: fix leaks on error with "goto cleanup" Ævar Arnfjörð Bjarmason
                             ` (13 subsequent siblings)
  19 siblings, 0 replies; 193+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2023-02-02  9:52 UTC (permalink / raw)
  To: git
  Cc: René Scharfe, Junio C Hamano, Eric Sunshine, Elijah Newren,
	Ævar Arnfjörð Bjarmason

When "add_to_tip_table()" is called with a non-zero
"shorten_unambiguous" we always return an xstrdup()'d string, which
we'd then xstrdup() again, leaking memory. See [1] and [2] for how
this leak came about.

We could xstrdup() only if "shorten_unambiguous" wasn't true, but
let's instead inline this code, so that information on whether we need
to xstrdup() is contained within add_to_tip_table().

1. 98c5c4ad015 (name-rev: allow to specify a subpath for --refs
   option, 2013-06-18)
2. b23e0b9353e (name-rev: allow converting the exact object name at
   the tip of a ref, 2013-07-07)

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 builtin/name-rev.c | 23 ++++++++++-------------
 1 file changed, 10 insertions(+), 13 deletions(-)

diff --git a/builtin/name-rev.c b/builtin/name-rev.c
index 15535e914a6..49fae523694 100644
--- a/builtin/name-rev.c
+++ b/builtin/name-rev.c
@@ -273,17 +273,6 @@ static int subpath_matches(const char *path, const char *filter)
 	return -1;
 }
 
-static const char *name_ref_abbrev(const char *refname, int shorten_unambiguous)
-{
-	if (shorten_unambiguous)
-		refname = shorten_unambiguous_ref(refname, 0);
-	else if (skip_prefix(refname, "refs/heads/", &refname))
-		; /* refname already advanced */
-	else
-		skip_prefix(refname, "refs/", &refname);
-	return refname;
-}
-
 struct name_ref_data {
 	int tags_only;
 	int name_only;
@@ -309,11 +298,19 @@ static void add_to_tip_table(const struct object_id *oid, const char *refname,
 			     int shorten_unambiguous, struct commit *commit,
 			     timestamp_t taggerdate, int from_tag, int deref)
 {
-	refname = name_ref_abbrev(refname, shorten_unambiguous);
+	char *short_refname = NULL;
+
+	if (shorten_unambiguous)
+		short_refname = shorten_unambiguous_ref(refname, 0);
+	else if (skip_prefix(refname, "refs/heads/", &refname))
+		; /* refname already advanced */
+	else
+		skip_prefix(refname, "refs/", &refname);
 
 	ALLOC_GROW(tip_table.table, tip_table.nr + 1, tip_table.alloc);
 	oidcpy(&tip_table.table[tip_table.nr].oid, oid);
-	tip_table.table[tip_table.nr].refname = xstrdup(refname);
+	tip_table.table[tip_table.nr].refname = short_refname ?
+		short_refname : xstrdup(refname);
 	tip_table.table[tip_table.nr].commit = commit;
 	tip_table.table[tip_table.nr].taggerdate = taggerdate;
 	tip_table.table[tip_table.nr].from_tag = from_tag;
-- 
2.39.1.1392.g63e6d408230


^ permalink raw reply related	[flat|nested] 193+ messages in thread

* [PATCH v6 07/19] repack: fix leaks on error with "goto cleanup"
  2023-02-02  9:52         ` [PATCH v6 00/19] leak fixes: various simple leak fixes Ævar Arnfjörð Bjarmason
                             ` (5 preceding siblings ...)
  2023-02-02  9:52           ` [PATCH v6 06/19] name-rev: don't xstrdup() an already dup'd string Ævar Arnfjörð Bjarmason
@ 2023-02-02  9:52           ` Ævar Arnfjörð Bjarmason
  2023-02-02  9:52           ` [PATCH v6 08/19] worktree: fix a trivial leak in prune_worktrees() Ævar Arnfjörð Bjarmason
                             ` (12 subsequent siblings)
  19 siblings, 0 replies; 193+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2023-02-02  9:52 UTC (permalink / raw)
  To: git
  Cc: René Scharfe, Junio C Hamano, Eric Sunshine, Elijah Newren,
	Ævar Arnfjörð Bjarmason

In cmd_repack() when we hit an error, replace "return ret" with "goto
cleanup" to ensure we free the necessary data structures.

Helped-by: Elijah Newren <newren@gmail.com>
Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 builtin/repack.c                    | 13 +++++++------
 t/t5312-prune-corruption.sh         |  1 +
 t/t6011-rev-list-with-bad-commit.sh |  1 +
 3 files changed, 9 insertions(+), 6 deletions(-)

diff --git a/builtin/repack.c b/builtin/repack.c
index c1402ad038f..f6493795318 100644
--- a/builtin/repack.c
+++ b/builtin/repack.c
@@ -948,7 +948,7 @@ int cmd_repack(int argc, const char **argv, const char *prefix)
 
 	ret = start_command(&cmd);
 	if (ret)
-		return ret;
+		goto cleanup;
 
 	if (geometry) {
 		FILE *in = xfdopen(cmd.in, "w");
@@ -977,7 +977,7 @@ int cmd_repack(int argc, const char **argv, const char *prefix)
 	fclose(out);
 	ret = finish_command(&cmd);
 	if (ret)
-		return ret;
+		goto cleanup;
 
 	if (!names.nr && !po_args.quiet)
 		printf_ln(_("Nothing new to pack."));
@@ -1007,7 +1007,7 @@ int cmd_repack(int argc, const char **argv, const char *prefix)
 				       &existing_nonkept_packs,
 				       &existing_kept_packs);
 		if (ret)
-			return ret;
+			goto cleanup;
 
 		if (delete_redundant && expire_to) {
 			/*
@@ -1039,7 +1039,7 @@ int cmd_repack(int argc, const char **argv, const char *prefix)
 					       &existing_nonkept_packs,
 					       &existing_kept_packs);
 			if (ret)
-				return ret;
+				goto cleanup;
 		}
 	}
 
@@ -1115,7 +1115,7 @@ int cmd_repack(int argc, const char **argv, const char *prefix)
 		string_list_clear(&include, 0);
 
 		if (ret)
-			return ret;
+			goto cleanup;
 	}
 
 	reprepare_packed_git(the_repository);
@@ -1172,10 +1172,11 @@ int cmd_repack(int argc, const char **argv, const char *prefix)
 		write_midx_file(get_object_directory(), NULL, NULL, flags);
 	}
 
+cleanup:
 	string_list_clear(&names, 1);
 	string_list_clear(&existing_nonkept_packs, 0);
 	string_list_clear(&existing_kept_packs, 0);
 	clear_pack_geometry(geometry);
 
-	return 0;
+	return ret;
 }
diff --git a/t/t5312-prune-corruption.sh b/t/t5312-prune-corruption.sh
index 9d8e249ae8b..230cb387122 100755
--- a/t/t5312-prune-corruption.sh
+++ b/t/t5312-prune-corruption.sh
@@ -14,6 +14,7 @@ what currently happens. If that changes, these tests should be revisited.
 GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
 export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
 
+TEST_PASSES_SANITIZE_LEAK=true
 . ./test-lib.sh
 
 test_expect_success 'disable reflogs' '
diff --git a/t/t6011-rev-list-with-bad-commit.sh b/t/t6011-rev-list-with-bad-commit.sh
index bad02cf5b83..b2e422cf0f7 100755
--- a/t/t6011-rev-list-with-bad-commit.sh
+++ b/t/t6011-rev-list-with-bad-commit.sh
@@ -2,6 +2,7 @@
 
 test_description='git rev-list should notice bad commits'
 
+TEST_PASSES_SANITIZE_LEAK=true
 . ./test-lib.sh
 
 # Note:
-- 
2.39.1.1392.g63e6d408230


^ permalink raw reply related	[flat|nested] 193+ messages in thread

* [PATCH v6 08/19] worktree: fix a trivial leak in prune_worktrees()
  2023-02-02  9:52         ` [PATCH v6 00/19] leak fixes: various simple leak fixes Ævar Arnfjörð Bjarmason
                             ` (6 preceding siblings ...)
  2023-02-02  9:52           ` [PATCH v6 07/19] repack: fix leaks on error with "goto cleanup" Ævar Arnfjörð Bjarmason
@ 2023-02-02  9:52           ` Ævar Arnfjörð Bjarmason
  2023-02-02  9:52           ` [PATCH v6 09/19] http-backend.c: fix "dir" and "cmd_arg" leaks in cmd_main() Ævar Arnfjörð Bjarmason
                             ` (11 subsequent siblings)
  19 siblings, 0 replies; 193+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2023-02-02  9:52 UTC (permalink / raw)
  To: git
  Cc: René Scharfe, Junio C Hamano, Eric Sunshine, Elijah Newren,
	Ævar Arnfjörð Bjarmason

We were leaking both the "struct strbuf" in prune_worktrees(), as well
as the "path" we got from should_prune_worktree(). Since these were
the only two uses of the "struct string_list" let's change it to a
"DUP" and push these to it with "string_list_append_nodup()".

For the string_list_append_nodup() we could also string_list_append()
the main_path.buf, and then strbuf_release(&main_path) right away. But
doing it this way avoids an allocation, as we already have the "struct
strbuf" prepared for appending to "kept".

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 builtin/worktree.c         | 6 +++---
 t/t2401-worktree-prune.sh  | 1 +
 t/t2406-worktree-repair.sh | 1 +
 3 files changed, 5 insertions(+), 3 deletions(-)

diff --git a/builtin/worktree.c b/builtin/worktree.c
index f51c40f1e1e..254283aa6f5 100644
--- a/builtin/worktree.c
+++ b/builtin/worktree.c
@@ -173,7 +173,7 @@ static void prune_worktrees(void)
 {
 	struct strbuf reason = STRBUF_INIT;
 	struct strbuf main_path = STRBUF_INIT;
-	struct string_list kept = STRING_LIST_INIT_NODUP;
+	struct string_list kept = STRING_LIST_INIT_DUP;
 	DIR *dir = opendir(git_path("worktrees"));
 	struct dirent *d;
 	if (!dir)
@@ -184,14 +184,14 @@ static void prune_worktrees(void)
 		if (should_prune_worktree(d->d_name, &reason, &path, expire))
 			prune_worktree(d->d_name, reason.buf);
 		else if (path)
-			string_list_append(&kept, path)->util = xstrdup(d->d_name);
+			string_list_append_nodup(&kept, path)->util = xstrdup(d->d_name);
 	}
 	closedir(dir);
 
 	strbuf_add_absolute_path(&main_path, get_git_common_dir());
 	/* massage main worktree absolute path to match 'gitdir' content */
 	strbuf_strip_suffix(&main_path, "/.");
-	string_list_append(&kept, strbuf_detach(&main_path, NULL));
+	string_list_append_nodup(&kept, strbuf_detach(&main_path, NULL));
 	prune_dups(&kept);
 	string_list_clear(&kept, 1);
 
diff --git a/t/t2401-worktree-prune.sh b/t/t2401-worktree-prune.sh
index 3d28c7f06b2..568a47ec426 100755
--- a/t/t2401-worktree-prune.sh
+++ b/t/t2401-worktree-prune.sh
@@ -5,6 +5,7 @@ test_description='prune $GIT_DIR/worktrees'
 GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
 export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
 
+TEST_PASSES_SANITIZE_LEAK=true
 . ./test-lib.sh
 
 test_expect_success initialize '
diff --git a/t/t2406-worktree-repair.sh b/t/t2406-worktree-repair.sh
index 5c44453e1c1..8970780efcc 100755
--- a/t/t2406-worktree-repair.sh
+++ b/t/t2406-worktree-repair.sh
@@ -2,6 +2,7 @@
 
 test_description='test git worktree repair'
 
+TEST_PASSES_SANITIZE_LEAK=true
 . ./test-lib.sh
 
 test_expect_success setup '
-- 
2.39.1.1392.g63e6d408230


^ permalink raw reply related	[flat|nested] 193+ messages in thread

* [PATCH v6 09/19] http-backend.c: fix "dir" and "cmd_arg" leaks in cmd_main()
  2023-02-02  9:52         ` [PATCH v6 00/19] leak fixes: various simple leak fixes Ævar Arnfjörð Bjarmason
                             ` (7 preceding siblings ...)
  2023-02-02  9:52           ` [PATCH v6 08/19] worktree: fix a trivial leak in prune_worktrees() Ævar Arnfjörð Bjarmason
@ 2023-02-02  9:52           ` Ævar Arnfjörð Bjarmason
  2023-02-02  9:52           ` [PATCH v6 10/19] http-backend.c: fix cmd_main() memory leak, refactor reg{exec,free}() Ævar Arnfjörð Bjarmason
                             ` (10 subsequent siblings)
  19 siblings, 0 replies; 193+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2023-02-02  9:52 UTC (permalink / raw)
  To: git
  Cc: René Scharfe, Junio C Hamano, Eric Sunshine, Elijah Newren,
	Ævar Arnfjörð Bjarmason

Free the "dir" variable after we're done with it. Before
917adc03608 (http-backend: add GIT_PROJECT_ROOT environment var,
2009-10-30) there was no leak here, as we'd get it via getenv(), but
since 917adc03608 we've xstrdup()'d it (or the equivalent), so we need
to free() it.

We also need to free the "cmd_arg" variable, which has been leaked
ever since it was added in 2f4038ab337 (Git-aware CGI to provide dumb
HTTP transport, 2009-10-30).

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 http-backend.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/http-backend.c b/http-backend.c
index 6eb3b2fe51c..67819d931ce 100644
--- a/http-backend.c
+++ b/http-backend.c
@@ -786,6 +786,7 @@ int cmd_main(int argc, const char **argv)
 	if (!getenv("GIT_HTTP_EXPORT_ALL") &&
 	    access("git-daemon-export-ok", F_OK) )
 		not_found(&hdr, "Repository not exported: '%s'", dir);
+	free(dir);
 
 	http_config();
 	max_request_buffer = git_env_ulong("GIT_HTTP_MAX_REQUEST_BUFFER",
@@ -795,5 +796,6 @@ int cmd_main(int argc, const char **argv)
 		setenv(GIT_PROTOCOL_ENVIRONMENT, proto_header, 0);
 
 	cmd->imp(&hdr, cmd_arg);
+	free(cmd_arg);
 	return 0;
 }
-- 
2.39.1.1392.g63e6d408230


^ permalink raw reply related	[flat|nested] 193+ messages in thread

* [PATCH v6 10/19] http-backend.c: fix cmd_main() memory leak, refactor reg{exec,free}()
  2023-02-02  9:52         ` [PATCH v6 00/19] leak fixes: various simple leak fixes Ævar Arnfjörð Bjarmason
                             ` (8 preceding siblings ...)
  2023-02-02  9:52           ` [PATCH v6 09/19] http-backend.c: fix "dir" and "cmd_arg" leaks in cmd_main() Ævar Arnfjörð Bjarmason
@ 2023-02-02  9:52           ` Ævar Arnfjörð Bjarmason
  2023-02-02  9:52           ` [PATCH v6 11/19] commit-graph: fix a parse_options_concat() leak Ævar Arnfjörð Bjarmason
                             ` (9 subsequent siblings)
  19 siblings, 0 replies; 193+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2023-02-02  9:52 UTC (permalink / raw)
  To: git
  Cc: René Scharfe, Junio C Hamano, Eric Sunshine, Elijah Newren,
	Ævar Arnfjörð Bjarmason

Fix a memory leak that's been with us ever since
2f4038ab337 (Git-aware CGI to provide dumb HTTP transport,
2009-10-30). In this case we're not calling regerror() after a failed
regexec(), and don't otherwise use "re" afterwards.

We can therefore simplify this code by calling regfree() right after
the regexec(). An alternative fix would be to add a regfree() to both
the "return" and "break" path in this for-loop.

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 http-backend.c | 7 +++++--
 1 file changed, 5 insertions(+), 2 deletions(-)

diff --git a/http-backend.c b/http-backend.c
index 67819d931ce..8ab58e55f85 100644
--- a/http-backend.c
+++ b/http-backend.c
@@ -759,10 +759,14 @@ int cmd_main(int argc, const char **argv)
 		struct service_cmd *c = &services[i];
 		regex_t re;
 		regmatch_t out[1];
+		int ret;
 
 		if (regcomp(&re, c->pattern, REG_EXTENDED))
 			die("Bogus regex in service table: %s", c->pattern);
-		if (!regexec(&re, dir, 1, out, 0)) {
+		ret = regexec(&re, dir, 1, out, 0);
+		regfree(&re);
+
+		if (!ret) {
 			size_t n;
 
 			if (strcmp(method, c->method))
@@ -774,7 +778,6 @@ int cmd_main(int argc, const char **argv)
 			dir[out[0].rm_so] = 0;
 			break;
 		}
-		regfree(&re);
 	}
 
 	if (!cmd)
-- 
2.39.1.1392.g63e6d408230


^ permalink raw reply related	[flat|nested] 193+ messages in thread

* [PATCH v6 11/19] commit-graph: fix a parse_options_concat() leak
  2023-02-02  9:52         ` [PATCH v6 00/19] leak fixes: various simple leak fixes Ævar Arnfjörð Bjarmason
                             ` (9 preceding siblings ...)
  2023-02-02  9:52           ` [PATCH v6 10/19] http-backend.c: fix cmd_main() memory leak, refactor reg{exec,free}() Ævar Arnfjörð Bjarmason
@ 2023-02-02  9:52           ` Ævar Arnfjörð Bjarmason
  2023-02-02  9:52           ` [PATCH v6 12/19] show-branch: free() allocated "head" before return Ævar Arnfjörð Bjarmason
                             ` (8 subsequent siblings)
  19 siblings, 0 replies; 193+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2023-02-02  9:52 UTC (permalink / raw)
  To: git
  Cc: René Scharfe, Junio C Hamano, Eric Sunshine, Elijah Newren,
	Ævar Arnfjörð Bjarmason

When the parse_options_concat() was added to this file in
84e4484f128 (commit-graph: use parse_options_concat(), 2021-08-23) we
wouldn't free() it if we returned early in these cases.

Since "result" is 0 by default we can "goto cleanup" in both cases,
and only need to set "result" if write_commit_graph_reachable() fails.

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 builtin/commit-graph.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/builtin/commit-graph.c b/builtin/commit-graph.c
index 0102ac8540e..93704f95a9d 100644
--- a/builtin/commit-graph.c
+++ b/builtin/commit-graph.c
@@ -269,8 +269,8 @@ static int graph_write(int argc, const char **argv, const char *prefix)
 
 	if (opts.reachable) {
 		if (write_commit_graph_reachable(odb, flags, &write_opts))
-			return 1;
-		return 0;
+			result = 1;
+		goto cleanup;
 	}
 
 	if (opts.stdin_packs) {
-- 
2.39.1.1392.g63e6d408230


^ permalink raw reply related	[flat|nested] 193+ messages in thread

* [PATCH v6 12/19] show-branch: free() allocated "head" before return
  2023-02-02  9:52         ` [PATCH v6 00/19] leak fixes: various simple leak fixes Ævar Arnfjörð Bjarmason
                             ` (10 preceding siblings ...)
  2023-02-02  9:52           ` [PATCH v6 11/19] commit-graph: fix a parse_options_concat() leak Ævar Arnfjörð Bjarmason
@ 2023-02-02  9:52           ` Ævar Arnfjörð Bjarmason
  2023-02-02  9:52           ` [PATCH v6 13/19] builtin/merge.c: use fixed strings, not "strbuf", fix leak Ævar Arnfjörð Bjarmason
                             ` (7 subsequent siblings)
  19 siblings, 0 replies; 193+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2023-02-02  9:52 UTC (permalink / raw)
  To: git
  Cc: René Scharfe, Junio C Hamano, Eric Sunshine, Elijah Newren,
	Ævar Arnfjörð Bjarmason

Stop leaking the "head" variable, which we've been leaking since it
was originally added in [1], and in its current form since [2]

1. ed378ec7e85 (Make ref resolution saner, 2006-09-11)
2. d9e557a320b (show-branch: store resolved head in heap buffer,
   2017-02-14).

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 builtin/show-branch.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/builtin/show-branch.c b/builtin/show-branch.c
index c013abaf942..358ac3e519a 100644
--- a/builtin/show-branch.c
+++ b/builtin/show-branch.c
@@ -956,5 +956,6 @@ int cmd_show_branch(int ac, const char **av, const char *prefix)
 		if (shown_merge_point && --extra < 0)
 			break;
 	}
+	free(head);
 	return 0;
 }
-- 
2.39.1.1392.g63e6d408230


^ permalink raw reply related	[flat|nested] 193+ messages in thread

* [PATCH v6 13/19] builtin/merge.c: use fixed strings, not "strbuf", fix leak
  2023-02-02  9:52         ` [PATCH v6 00/19] leak fixes: various simple leak fixes Ævar Arnfjörð Bjarmason
                             ` (11 preceding siblings ...)
  2023-02-02  9:52           ` [PATCH v6 12/19] show-branch: free() allocated "head" before return Ævar Arnfjörð Bjarmason
@ 2023-02-02  9:52           ` Ævar Arnfjörð Bjarmason
  2023-02-02  9:52           ` [PATCH v6 14/19] builtin/merge.c: free "&buf" on "Your local changes..." error Ævar Arnfjörð Bjarmason
                             ` (6 subsequent siblings)
  19 siblings, 0 replies; 193+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2023-02-02  9:52 UTC (permalink / raw)
  To: git
  Cc: René Scharfe, Junio C Hamano, Eric Sunshine, Elijah Newren,
	Ævar Arnfjörð Bjarmason

Follow-up 465028e0e25 (merge: add missing strbuf_release(),
2021-10-07) and address the "msg" memory leak in this block. We could
free "&msg" before the "goto done" here, but even better is to avoid
allocating it in the first place.

By repeating the "Fast-forward" string here we can avoid using a
"struct strbuf" altogether.

Suggested-by: René Scharfe <l.s.r@web.de>
Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 builtin/merge.c                | 11 ++++-------
 t/t6439-merge-co-error-msgs.sh |  1 +
 2 files changed, 5 insertions(+), 7 deletions(-)

diff --git a/builtin/merge.c b/builtin/merge.c
index 74de2ebd2b3..32733e551d4 100644
--- a/builtin/merge.c
+++ b/builtin/merge.c
@@ -1560,7 +1560,9 @@ int cmd_merge(int argc, const char **argv, const char *prefix)
 			!common->next &&
 			oideq(&common->item->object.oid, &head_commit->object.oid)) {
 		/* Again the most common case of merging one remote. */
-		struct strbuf msg = STRBUF_INIT;
+		const char *msg = have_message ?
+			"Fast-forward (no commit created; -m option ignored)" :
+			"Fast-forward";
 		struct commit *commit;
 
 		if (verbosity >= 0) {
@@ -1570,10 +1572,6 @@ int cmd_merge(int argc, const char **argv, const char *prefix)
 			       find_unique_abbrev(&remoteheads->item->object.oid,
 						  DEFAULT_ABBREV));
 		}
-		strbuf_addstr(&msg, "Fast-forward");
-		if (have_message)
-			strbuf_addstr(&msg,
-				" (no commit created; -m option ignored)");
 		commit = remoteheads->item;
 		if (!commit) {
 			ret = 1;
@@ -1592,9 +1590,8 @@ int cmd_merge(int argc, const char **argv, const char *prefix)
 			goto done;
 		}
 
-		finish(head_commit, remoteheads, &commit->object.oid, msg.buf);
+		finish(head_commit, remoteheads, &commit->object.oid, msg);
 		remove_merge_branch_state(the_repository);
-		strbuf_release(&msg);
 		goto done;
 	} else if (!remoteheads->next && common->next)
 		;
diff --git a/t/t6439-merge-co-error-msgs.sh b/t/t6439-merge-co-error-msgs.sh
index 52cf0c87690..0cbec57cdab 100755
--- a/t/t6439-merge-co-error-msgs.sh
+++ b/t/t6439-merge-co-error-msgs.sh
@@ -5,6 +5,7 @@ test_description='unpack-trees error messages'
 GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
 export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
 
+TEST_PASSES_SANITIZE_LEAK=true
 . ./test-lib.sh
 
 
-- 
2.39.1.1392.g63e6d408230


^ permalink raw reply related	[flat|nested] 193+ messages in thread

* [PATCH v6 14/19] builtin/merge.c: free "&buf" on "Your local changes..." error
  2023-02-02  9:52         ` [PATCH v6 00/19] leak fixes: various simple leak fixes Ævar Arnfjörð Bjarmason
                             ` (12 preceding siblings ...)
  2023-02-02  9:52           ` [PATCH v6 13/19] builtin/merge.c: use fixed strings, not "strbuf", fix leak Ævar Arnfjörð Bjarmason
@ 2023-02-02  9:52           ` Ævar Arnfjörð Bjarmason
  2023-02-02  9:52           ` [PATCH v6 15/19] grep.c: refactor free_grep_patterns() Ævar Arnfjörð Bjarmason
                             ` (5 subsequent siblings)
  19 siblings, 0 replies; 193+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2023-02-02  9:52 UTC (permalink / raw)
  To: git
  Cc: René Scharfe, Junio C Hamano, Eric Sunshine, Elijah Newren,
	Ævar Arnfjörð Bjarmason

Plug a memory leak introduced in [1], since that change didn't follow
the "goto done" pattern introduced in [2] we'd leak the "&buf" memory.

1. e4cdfe84a0d (merge: abort if index does not match HEAD for trivial
   merges, 2022-07-23)
2. d5a35c114ab (Copy resolve_ref() return value for longer use,
   2011-11-13)

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 builtin/merge.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/builtin/merge.c b/builtin/merge.c
index 32733e551d4..5a834b1f291 100644
--- a/builtin/merge.c
+++ b/builtin/merge.c
@@ -1618,7 +1618,8 @@ int cmd_merge(int argc, const char **argv, const char *prefix)
 				error(_("Your local changes to the following files would be overwritten by merge:\n  %s"),
 				      sb.buf);
 				strbuf_release(&sb);
-				return 2;
+				ret = 2;
+				goto done;
 			}
 
 			/* See if it is really trivial. */
-- 
2.39.1.1392.g63e6d408230


^ permalink raw reply related	[flat|nested] 193+ messages in thread

* [PATCH v6 15/19] grep.c: refactor free_grep_patterns()
  2023-02-02  9:52         ` [PATCH v6 00/19] leak fixes: various simple leak fixes Ævar Arnfjörð Bjarmason
                             ` (13 preceding siblings ...)
  2023-02-02  9:52           ` [PATCH v6 14/19] builtin/merge.c: free "&buf" on "Your local changes..." error Ævar Arnfjörð Bjarmason
@ 2023-02-02  9:52           ` Ævar Arnfjörð Bjarmason
  2023-02-02  9:52           ` [PATCH v6 16/19] grep API: plug memory leaks by freeing "header_list" Ævar Arnfjörð Bjarmason
                             ` (4 subsequent siblings)
  19 siblings, 0 replies; 193+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2023-02-02  9:52 UTC (permalink / raw)
  To: git
  Cc: René Scharfe, Junio C Hamano, Eric Sunshine, Elijah Newren,
	Ævar Arnfjörð Bjarmason

Refactor the free_grep_patterns() function to split out the freeing of
the "struct grep_pat" it contains. Right now we're only freeing the
"pattern_list", but we should be freeing another member of the same
type, which we'll do in the subsequent commit.

Let's also replace the "return" if we don't have an
"opt->pattern_expression" with a conditional call of
free_pattern_expr().

Before db84376f981 (grep.c: remove "extended" in favor of
"pattern_expression", fix segfault, 2022-10-11) the pattern here was:

	if (!x)
		return;
	free_pattern_expr(y);

While at it, instead of:

	if (!x)
		return;
	free_pattern_expr(x);

Let's instead do:

	if (x)
		free_pattern_expr(x);

This will make it easier to free additional members from
free_grep_patterns() in the future.

Helped-by: Elijah Newren <newren@gmail.com>
Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 grep.c | 14 +++++++++-----
 1 file changed, 9 insertions(+), 5 deletions(-)

diff --git a/grep.c b/grep.c
index 1687f65b64f..f8708e1fd20 100644
--- a/grep.c
+++ b/grep.c
@@ -769,11 +769,11 @@ static void free_pattern_expr(struct grep_expr *x)
 	free(x);
 }
 
-void free_grep_patterns(struct grep_opt *opt)
+static void free_grep_pat(struct grep_pat *pattern)
 {
 	struct grep_pat *p, *n;
 
-	for (p = opt->pattern_list; p; p = n) {
+	for (p = pattern; p; p = n) {
 		n = p->next;
 		switch (p->token) {
 		case GREP_PATTERN: /* atom */
@@ -790,10 +790,14 @@ void free_grep_patterns(struct grep_opt *opt)
 		}
 		free(p);
 	}
+}
 
-	if (!opt->pattern_expression)
-		return;
-	free_pattern_expr(opt->pattern_expression);
+void free_grep_patterns(struct grep_opt *opt)
+{
+	free_grep_pat(opt->pattern_list);
+
+	if (opt->pattern_expression)
+		free_pattern_expr(opt->pattern_expression);
 }
 
 static const char *end_of_line(const char *cp, unsigned long *left)
-- 
2.39.1.1392.g63e6d408230


^ permalink raw reply related	[flat|nested] 193+ messages in thread

* [PATCH v6 16/19] grep API: plug memory leaks by freeing "header_list"
  2023-02-02  9:52         ` [PATCH v6 00/19] leak fixes: various simple leak fixes Ævar Arnfjörð Bjarmason
                             ` (14 preceding siblings ...)
  2023-02-02  9:52           ` [PATCH v6 15/19] grep.c: refactor free_grep_patterns() Ævar Arnfjörð Bjarmason
@ 2023-02-02  9:52           ` Ævar Arnfjörð Bjarmason
  2023-02-02  9:52           ` [PATCH v6 17/19] receive-pack: free() the "ref_name" in "struct command" Ævar Arnfjörð Bjarmason
                             ` (3 subsequent siblings)
  19 siblings, 0 replies; 193+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2023-02-02  9:52 UTC (permalink / raw)
  To: git
  Cc: René Scharfe, Junio C Hamano, Eric Sunshine, Elijah Newren,
	Ævar Arnfjörð Bjarmason

When the "header_list" struct member was added in [1], freeing this
field was neglected. Fix that now, so that commands like

	./git -P log -1 --color=always --author=A origin/master

will run leak-free.

1. 80235ba79ef ("log --author=me --grep=it" should find intersection,
   not union, 2010-01-17)

Helped-by: Elijah Newren <newren@gmail.com>
Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 grep.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/grep.c b/grep.c
index f8708e1fd20..92ece4b7fa3 100644
--- a/grep.c
+++ b/grep.c
@@ -795,6 +795,7 @@ static void free_grep_pat(struct grep_pat *pattern)
 void free_grep_patterns(struct grep_opt *opt)
 {
 	free_grep_pat(opt->pattern_list);
+	free_grep_pat(opt->header_list);
 
 	if (opt->pattern_expression)
 		free_pattern_expr(opt->pattern_expression);
-- 
2.39.1.1392.g63e6d408230


^ permalink raw reply related	[flat|nested] 193+ messages in thread

* [PATCH v6 17/19] receive-pack: free() the "ref_name" in "struct command"
  2023-02-02  9:52         ` [PATCH v6 00/19] leak fixes: various simple leak fixes Ævar Arnfjörð Bjarmason
                             ` (15 preceding siblings ...)
  2023-02-02  9:52           ` [PATCH v6 16/19] grep API: plug memory leaks by freeing "header_list" Ævar Arnfjörð Bjarmason
@ 2023-02-02  9:52           ` Ævar Arnfjörð Bjarmason
  2023-02-02 21:55             ` Junio C Hamano
  2023-02-02  9:52           ` [PATCH v6 18/19] push: refactor refspec_append_mapped() for subsequent leak-fix Ævar Arnfjörð Bjarmason
                             ` (2 subsequent siblings)
  19 siblings, 1 reply; 193+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2023-02-02  9:52 UTC (permalink / raw)
  To: git
  Cc: René Scharfe, Junio C Hamano, Eric Sunshine, Elijah Newren,
	Ævar Arnfjörð Bjarmason

Fix a memory leak that's been with us since this code was introduced
in 575f497456e (Add first cut at "git-receive-pack", 2005-06-29). See
eb1af2df0b1 (git-receive-pack: start parsing ref update commands,
2005-06-29) for the later change that refactored the code to add the
"ref_name" member.

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 builtin/receive-pack.c                 | 10 ++++++++++
 t/t5405-send-pack-rewind.sh            |  1 +
 t/t5406-remote-rejects.sh              |  1 +
 t/t5507-remote-environment.sh          |  2 ++
 t/t5522-pull-symlink.sh                |  1 +
 t/t5527-fetch-odd-refs.sh              |  1 +
 t/t5560-http-backend-noserver.sh       |  1 +
 t/t5561-http-backend.sh                |  1 +
 t/t5562-http-backend-content-length.sh |  2 ++
 t/t5705-session-id-in-capabilities.sh  |  1 +
 10 files changed, 21 insertions(+)

diff --git a/builtin/receive-pack.c b/builtin/receive-pack.c
index a90af303630..451bad776c6 100644
--- a/builtin/receive-pack.c
+++ b/builtin/receive-pack.c
@@ -2032,6 +2032,15 @@ static struct command **queue_command(struct command **tail,
 	return &cmd->next;
 }
 
+static void free_commands(struct command *commands)
+{
+	while (commands) {
+		struct command *next = commands->next;
+		free(commands);
+		commands = next;
+	}
+}
+
 static void queue_commands_from_cert(struct command **tail,
 				     struct strbuf *push_cert)
 {
@@ -2569,6 +2578,7 @@ int cmd_receive_pack(int argc, const char **argv, const char *prefix)
 		run_receive_hook(commands, "post-receive", 1,
 				 &push_options);
 		run_update_post_hook(commands);
+		free_commands(commands);
 		string_list_clear(&push_options, 0);
 		if (auto_gc) {
 			struct child_process proc = CHILD_PROCESS_INIT;
diff --git a/t/t5405-send-pack-rewind.sh b/t/t5405-send-pack-rewind.sh
index 11f03239a06..1686ac13aa6 100755
--- a/t/t5405-send-pack-rewind.sh
+++ b/t/t5405-send-pack-rewind.sh
@@ -5,6 +5,7 @@ test_description='forced push to replace commit we do not have'
 GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
 export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
 
+TEST_PASSES_SANITIZE_LEAK=true
 . ./test-lib.sh
 
 test_expect_success setup '
diff --git a/t/t5406-remote-rejects.sh b/t/t5406-remote-rejects.sh
index dcbeb420827..d6a99466338 100755
--- a/t/t5406-remote-rejects.sh
+++ b/t/t5406-remote-rejects.sh
@@ -2,6 +2,7 @@
 
 test_description='remote push rejects are reported by client'
 
+TEST_PASSES_SANITIZE_LEAK=true
 . ./test-lib.sh
 
 test_expect_success 'setup' '