git.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 00/21] Memory leak fixes (pt.9)
@ 2024-10-11  5:32 Patrick Steinhardt
  2024-10-11  5:32 ` [PATCH 01/21] builtin/ls-remote: plug leaking server options Patrick Steinhardt
                   ` (23 more replies)
  0 siblings, 24 replies; 100+ messages in thread
From: Patrick Steinhardt @ 2024-10-11  5:32 UTC (permalink / raw)
  To: git

Hi,

here's another round of memory leak fixes. With this series we're down
to 10 test suites which are failing with the leak sanitizer. There are
two patch series in flight [1][2] that fix three more test suites, so in
total we're down to 7 test suites that we'll still have to fix up. So:
we're almost done!

Patrick

[1]: <20240826083052.1542228-1-toon@iotcl.com>
[2]: <cover.1726556195.git.ps@pks.im>

Patrick Steinhardt (21):
  builtin/ls-remote: plug leaking server options
  t/helper: fix leaks in "reach" test tool
  grep: fix leak in `grep_splice_or()`
  builtin/grep: fix leak with `--max-count=0`
  revision: fix leaking bloom filters
  diff-lib: fix leaking diffopts in `do_diff_cache()`
  pretty: clear signature check
  upload-pack: fix leaking URI protocols
  builtin/commit: fix leaking change data contents
  trailer: fix leaking trailer values
  builtin/commit: fix leaking cleanup config
  transport-helper: fix leaking import/export marks
  builtin/tag: fix leaking key ID on failure to sign
  combine-diff: fix leaking lost lines
  dir: release untracked cache data
  sparse-index: correctly free EWAH contents
  t/helper: stop re-initialization of `the_repository`
  t/helper: fix leaking buffer in "dump-untracked-cache"
  dir: fix leak when parsing "status.showUntrackedFiles"
  builtin/merge: release outbut buffer after performing merge
  list-objects-filter-options: work around reported leak on error

 builtin/commit.c                          | 26 +++++++++++++++++------
 builtin/grep.c                            | 13 +++++++++---
 builtin/ls-remote.c                       |  1 +
 builtin/merge.c                           |  1 +
 builtin/tag.c                             |  2 +-
 combine-diff.c                            |  2 +-
 diff-lib.c                                |  1 +
 dir.c                                     | 12 +++++++++--
 grep.c                                    |  1 +
 list-objects-filter-options.c             | 17 ++++++---------
 pretty.c                                  |  1 +
 revision.c                                |  5 +++++
 sparse-index.c                            |  7 ++++--
 t/helper/test-dump-untracked-cache.c      |  2 ++
 t/helper/test-reach.c                     | 10 +++++++++
 t/helper/test-read-cache.c                |  2 --
 t/t4038-diff-combined.sh                  |  1 +
 t/t4202-log.sh                            |  1 +
 t/t4216-log-bloom.sh                      |  1 +
 t/t5702-protocol-v2.sh                    |  1 +
 t/t5801-remote-helpers.sh                 |  1 +
 t/t6112-rev-list-filters-objects.sh       |  1 +
 t/t6424-merge-unrelated-index-changes.sh  |  1 +
 t/t6600-test-reach.sh                     |  1 +
 t/t7004-tag.sh                            |  1 +
 t/t7031-verify-tag-signed-ssh.sh          |  1 +
 t/t7063-status-untracked-cache.sh         |  1 +
 t/t7500-commit-template-squash-signoff.sh |  1 +
 t/t7502-commit-porcelain.sh               |  1 +
 t/t7510-signed-commit.sh                  |  1 +
 t/t7513-interpret-trailers.sh             |  1 +
 t/t7519-status-fsmonitor.sh               |  1 +
 t/t7528-signed-commit-ssh.sh              |  1 +
 t/t7610-mergetool.sh                      |  1 +
 t/t7810-grep.sh                           |  1 +
 trailer.c                                 | 18 +++++++++++-----
 transport-helper.c                        |  2 ++
 upload-pack.c                             |  1 +
 38 files changed, 111 insertions(+), 32 deletions(-)

-- 
2.47.0.dirty


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

* [PATCH 01/21] builtin/ls-remote: plug leaking server options
  2024-10-11  5:32 [PATCH 00/21] Memory leak fixes (pt.9) Patrick Steinhardt
@ 2024-10-11  5:32 ` Patrick Steinhardt
  2024-10-11  5:32 ` [PATCH 02/21] t/helper: fix leaks in "reach" test tool Patrick Steinhardt
                   ` (22 subsequent siblings)
  23 siblings, 0 replies; 100+ messages in thread
From: Patrick Steinhardt @ 2024-10-11  5:32 UTC (permalink / raw)
  To: git

The server options populated via `OPT_STRING_LIST()` is never cleared,
causing a memory leak. Plug it.

This leak is exposed by t5702, but plugging it alone does not make the
whole test suite pass.

Signed-off-by: Patrick Steinhardt <ps@pks.im>
---
 builtin/ls-remote.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/builtin/ls-remote.c b/builtin/ls-remote.c
index f723b3bf3bb..f333821b994 100644
--- a/builtin/ls-remote.c
+++ b/builtin/ls-remote.c
@@ -166,6 +166,7 @@ int cmd_ls_remote(int argc,
 		status = 0; /* we found something */
 	}
 
+	string_list_clear(&server_options, 0);
 	ref_sorting_release(sorting);
 	ref_array_clear(&ref_array);
 	if (transport_disconnect(transport))
-- 
2.47.0.dirty


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

* [PATCH 02/21] t/helper: fix leaks in "reach" test tool
  2024-10-11  5:32 [PATCH 00/21] Memory leak fixes (pt.9) Patrick Steinhardt
  2024-10-11  5:32 ` [PATCH 01/21] builtin/ls-remote: plug leaking server options Patrick Steinhardt
@ 2024-10-11  5:32 ` Patrick Steinhardt
  2024-10-11  5:32 ` [PATCH 03/21] grep: fix leak in `grep_splice_or()` Patrick Steinhardt
                   ` (21 subsequent siblings)
  23 siblings, 0 replies; 100+ messages in thread
From: Patrick Steinhardt @ 2024-10-11  5:32 UTC (permalink / raw)
  To: git

The "reach" test tool doesn't bother to clean up any of its allocated
resources, causing various leaks. Plug them.

Signed-off-by: Patrick Steinhardt <ps@pks.im>
---
 t/helper/test-reach.c | 10 ++++++++++
 t/t6600-test-reach.sh |  1 +
 2 files changed, 11 insertions(+)

diff --git a/t/helper/test-reach.c b/t/helper/test-reach.c
index 995e382863a..84deee604ad 100644
--- a/t/helper/test-reach.c
+++ b/t/helper/test-reach.c
@@ -127,10 +127,12 @@ int cmd__reach(int ac, const char **av)
 			exit(128);
 		printf("%s(A,X):\n", av[1]);
 		print_sorted_commit_ids(list);
+		free_commit_list(list);
 	} else if (!strcmp(av[1], "reduce_heads")) {
 		struct commit_list *list = reduce_heads(X);
 		printf("%s(X):\n", av[1]);
 		print_sorted_commit_ids(list);
+		free_commit_list(list);
 	} else if (!strcmp(av[1], "can_all_from_reach")) {
 		printf("%s(X,Y):%d\n", av[1], can_all_from_reach(X, Y, 1));
 	} else if (!strcmp(av[1], "can_all_from_reach_with_flag")) {
@@ -153,6 +155,7 @@ int cmd__reach(int ac, const char **av)
 			filter.with_commit_tag_algo = 0;
 
 		printf("%s(_,A,X,_):%d\n", av[1], commit_contains(&filter, A, X, &cache));
+		clear_contains_cache(&cache);
 	} else if (!strcmp(av[1], "get_reachable_subset")) {
 		const int reachable_flag = 1;
 		int i, count = 0;
@@ -176,7 +179,14 @@ int cmd__reach(int ac, const char **av)
 			die(_("too many commits marked reachable"));
 
 		print_sorted_commit_ids(list);
+		free_commit_list(list);
 	}
 
+	object_array_clear(&X_obj);
+	strbuf_release(&buf);
+	free_commit_list(X);
+	free_commit_list(Y);
+	free(X_array);
+	free(Y_array);
 	return 0;
 }
diff --git a/t/t6600-test-reach.sh b/t/t6600-test-reach.sh
index 2591f8b8b39..307deefed2c 100755
--- a/t/t6600-test-reach.sh
+++ b/t/t6600-test-reach.sh
@@ -2,6 +2,7 @@
 
 test_description='basic commit reachability tests'
 
+TEST_PASSES_SANITIZE_LEAK=true
 . ./test-lib.sh
 
 # Construct a grid-like commit graph with points (x,y)
-- 
2.47.0.dirty


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

* [PATCH 03/21] grep: fix leak in `grep_splice_or()`
  2024-10-11  5:32 [PATCH 00/21] Memory leak fixes (pt.9) Patrick Steinhardt
  2024-10-11  5:32 ` [PATCH 01/21] builtin/ls-remote: plug leaking server options Patrick Steinhardt
  2024-10-11  5:32 ` [PATCH 02/21] t/helper: fix leaks in "reach" test tool Patrick Steinhardt
@ 2024-10-11  5:32 ` Patrick Steinhardt
  2024-10-11  5:32 ` [PATCH 04/21] builtin/grep: fix leak with `--max-count=0` Patrick Steinhardt
                   ` (20 subsequent siblings)
  23 siblings, 0 replies; 100+ messages in thread
From: Patrick Steinhardt @ 2024-10-11  5:32 UTC (permalink / raw)
  To: git

In `grep_splice_or()` we search for the next `TRUE` node in our tree of
grep exrpessions and replace it with the given new expression. But we
don't free the old node, which causes a memory leak. Plug it.

This leak is exposed by t7810, but plugging it alone isn't sufficient to
make the test suite pass.

Signed-off-by: Patrick Steinhardt <ps@pks.im>
---
 grep.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/grep.c b/grep.c
index 701e58de04e..e9337f32cbf 100644
--- a/grep.c
+++ b/grep.c
@@ -756,6 +756,7 @@ static struct grep_expr *grep_splice_or(struct grep_expr *x, struct grep_expr *y
 		assert(x->node == GREP_NODE_OR);
 		if (x->u.binary.right &&
 		    x->u.binary.right->node == GREP_NODE_TRUE) {
+			free(x->u.binary.right);
 			x->u.binary.right = y;
 			break;
 		}
-- 
2.47.0.dirty


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

* [PATCH 04/21] builtin/grep: fix leak with `--max-count=0`
  2024-10-11  5:32 [PATCH 00/21] Memory leak fixes (pt.9) Patrick Steinhardt
                   ` (2 preceding siblings ...)
  2024-10-11  5:32 ` [PATCH 03/21] grep: fix leak in `grep_splice_or()` Patrick Steinhardt
@ 2024-10-11  5:32 ` Patrick Steinhardt
  2024-10-11  5:32 ` [PATCH 05/21] revision: fix leaking bloom filters Patrick Steinhardt
                   ` (19 subsequent siblings)
  23 siblings, 0 replies; 100+ messages in thread
From: Patrick Steinhardt @ 2024-10-11  5:32 UTC (permalink / raw)
  To: git

When executing with `--max-count=0` we'll return early from git-grep(1)
without performing any cleanup, which causes memory leaks. Plug these.

Signed-off-by: Patrick Steinhardt <ps@pks.im>
---
 builtin/grep.c  | 13 ++++++++++---
 t/t7810-grep.sh |  1 +
 2 files changed, 11 insertions(+), 3 deletions(-)

diff --git a/builtin/grep.c b/builtin/grep.c
index f17d46a06e4..98b85c7fcac 100644
--- a/builtin/grep.c
+++ b/builtin/grep.c
@@ -906,6 +906,7 @@ int cmd_grep(int argc,
 	int dummy;
 	int use_index = 1;
 	int allow_revs;
+	int ret;
 
 	struct option options[] = {
 		OPT_BOOL(0, "cached", &cached,
@@ -1172,8 +1173,10 @@ int cmd_grep(int argc,
 	 * Optimize out the case where the amount of matches is limited to zero.
 	 * We do this to keep results consistent with GNU grep(1).
 	 */
-	if (opt.max_count == 0)
-		return 1;
+	if (opt.max_count == 0) {
+		ret = 1;
+		goto out;
+	}
 
 	if (show_in_pager) {
 		if (num_threads > 1)
@@ -1267,10 +1270,14 @@ int cmd_grep(int argc,
 		hit |= wait_all();
 	if (hit && show_in_pager)
 		run_pager(&opt, prefix);
+
+	ret = !hit;
+
+out:
 	clear_pathspec(&pathspec);
 	string_list_clear(&path_list, 0);
 	free_grep_patterns(&opt);
 	object_array_clear(&list);
 	free_repos();
-	return !hit;
+	return ret;
 }
diff --git a/t/t7810-grep.sh b/t/t7810-grep.sh
index af2cf2f78ab..9e7681f0831 100755
--- a/t/t7810-grep.sh
+++ b/t/t7810-grep.sh
@@ -9,6 +9,7 @@ test_description='git grep various.
 GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
 export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
 
+TEST_PASSES_SANITIZE_LEAK=true
 . ./test-lib.sh
 
 test_invalid_grep_expression() {
-- 
2.47.0.dirty


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

* [PATCH 05/21] revision: fix leaking bloom filters
  2024-10-11  5:32 [PATCH 00/21] Memory leak fixes (pt.9) Patrick Steinhardt
                   ` (3 preceding siblings ...)
  2024-10-11  5:32 ` [PATCH 04/21] builtin/grep: fix leak with `--max-count=0` Patrick Steinhardt
@ 2024-10-11  5:32 ` Patrick Steinhardt
  2024-10-11  5:32 ` [PATCH 06/21] diff-lib: fix leaking diffopts in `do_diff_cache()` Patrick Steinhardt
                   ` (18 subsequent siblings)
  23 siblings, 0 replies; 100+ messages in thread
From: Patrick Steinhardt @ 2024-10-11  5:32 UTC (permalink / raw)
  To: git

The memory allocated by `prepare_to_use_bloom_filter()` is not released
by `release_revisions()`, causing a memory leak. Plug it.

Signed-off-by: Patrick Steinhardt <ps@pks.im>
---
 revision.c           | 5 +++++
 t/t4216-log-bloom.sh | 1 +
 2 files changed, 6 insertions(+)

diff --git a/revision.c b/revision.c
index f5f5b84f2b0..8df75b82249 100644
--- a/revision.c
+++ b/revision.c
@@ -3227,6 +3227,11 @@ void release_revisions(struct rev_info *revs)
 	clear_decoration(&revs->treesame, free);
 	line_log_free(revs);
 	oidset_clear(&revs->missing_commits);
+
+	for (int i = 0; i < revs->bloom_keys_nr; i++)
+		clear_bloom_key(&revs->bloom_keys[i]);
+	FREE_AND_NULL(revs->bloom_keys);
+	revs->bloom_keys_nr = 0;
 }
 
 static void add_child(struct rev_info *revs, struct commit *parent, struct commit *child)
diff --git a/t/t4216-log-bloom.sh b/t/t4216-log-bloom.sh
index 3f163dc3969..8d22338f6aa 100755
--- a/t/t4216-log-bloom.sh
+++ b/t/t4216-log-bloom.sh
@@ -4,6 +4,7 @@ test_description='git log for a path with Bloom filters'
 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-chunk.sh
 
-- 
2.47.0.dirty


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

* [PATCH 06/21] diff-lib: fix leaking diffopts in `do_diff_cache()`
  2024-10-11  5:32 [PATCH 00/21] Memory leak fixes (pt.9) Patrick Steinhardt
                   ` (4 preceding siblings ...)
  2024-10-11  5:32 ` [PATCH 05/21] revision: fix leaking bloom filters Patrick Steinhardt
@ 2024-10-11  5:32 ` Patrick Steinhardt
  2024-10-21  9:46   ` Kristoffer Haugsbakk
  2024-10-11  5:32 ` [PATCH 07/21] pretty: clear signature check Patrick Steinhardt
                   ` (17 subsequent siblings)
  23 siblings, 1 reply; 100+ messages in thread
From: Patrick Steinhardt @ 2024-10-11  5:32 UTC (permalink / raw)
  To: git

In `do_diff_cache()` we initialize a new `rev_info` and then overwrite
its `diffopt` with a user-provided set of options. This can leak memory
because `repo_init_revisions()` may end up allocating memory for the
`diffopt` itself depending on the configuration. And as that field is
overwritten we won't ever free that.

Plug the memory leak by releasing the diffopts before we overwrite them.

Signed-off-by: Patrick Steinhardt <ps@pks.im>
---
 diff-lib.c           | 1 +
 t/t7610-mergetool.sh | 1 +
 2 files changed, 2 insertions(+)

diff --git a/diff-lib.c b/diff-lib.c
index 6b14b959629..3cf353946f5 100644
--- a/diff-lib.c
+++ b/diff-lib.c
@@ -661,6 +661,7 @@ int do_diff_cache(const struct object_id *tree_oid, struct diff_options *opt)
 
 	repo_init_revisions(opt->repo, &revs, NULL);
 	copy_pathspec(&revs.prune_data, &opt->pathspec);
+	diff_free(&revs.diffopt);
 	revs.diffopt = *opt;
 	revs.diffopt.no_free = 1;
 
diff --git a/t/t7610-mergetool.sh b/t/t7610-mergetool.sh
index 22b3a85b3e9..5c5e79e9905 100755
--- a/t/t7610-mergetool.sh
+++ b/t/t7610-mergetool.sh
@@ -10,6 +10,7 @@ Testing basic merge tool invocation'
 GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
 export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
 
+TEST_PASSES_SANITIZE_LEAK=true
 . ./test-lib.sh
 
 # All the mergetool test work by checking out a temporary branch based
-- 
2.47.0.dirty


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

* [PATCH 07/21] pretty: clear signature check
  2024-10-11  5:32 [PATCH 00/21] Memory leak fixes (pt.9) Patrick Steinhardt
                   ` (5 preceding siblings ...)
  2024-10-11  5:32 ` [PATCH 06/21] diff-lib: fix leaking diffopts in `do_diff_cache()` Patrick Steinhardt
@ 2024-10-11  5:32 ` Patrick Steinhardt
  2024-10-18 12:02   ` Toon Claes
  2024-10-11  5:32 ` [PATCH 08/21] upload-pack: fix leaking URI protocols Patrick Steinhardt
                   ` (16 subsequent siblings)
  23 siblings, 1 reply; 100+ messages in thread
From: Patrick Steinhardt @ 2024-10-11  5:32 UTC (permalink / raw)
  To: git

The signature check in of the formatting context is never getting
released. Fix this to plug the resulting memory leak.

Signed-off-by: Patrick Steinhardt <ps@pks.im>
---
 pretty.c                         | 1 +
 t/t4202-log.sh                   | 1 +
 t/t7031-verify-tag-signed-ssh.sh | 1 +
 t/t7510-signed-commit.sh         | 1 +
 t/t7528-signed-commit-ssh.sh     | 1 +
 5 files changed, 5 insertions(+)

diff --git a/pretty.c b/pretty.c
index 6403e268900..098378720a4 100644
--- a/pretty.c
+++ b/pretty.c
@@ -2032,6 +2032,7 @@ void repo_format_commit_message(struct repository *r,
 
 	free(context.commit_encoding);
 	repo_unuse_commit_buffer(r, commit, context.message);
+	signature_check_clear(&context.signature_check);
 }
 
 static void pp_header(struct pretty_print_context *pp,
diff --git a/t/t4202-log.sh b/t/t4202-log.sh
index 51f7beb59f8..35bec4089a3 100755
--- a/t/t4202-log.sh
+++ b/t/t4202-log.sh
@@ -5,6 +5,7 @@ test_description='git log'
 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"
 . "$TEST_DIRECTORY/lib-terminal.sh"
diff --git a/t/t7031-verify-tag-signed-ssh.sh b/t/t7031-verify-tag-signed-ssh.sh
index 20913b37134..2ee62c07293 100755
--- a/t/t7031-verify-tag-signed-ssh.sh
+++ b/t/t7031-verify-tag-signed-ssh.sh
@@ -4,6 +4,7 @@ test_description='signed tag 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/t7510-signed-commit.sh b/t/t7510-signed-commit.sh
index 0d2dd29fe6a..eb229082e40 100755
--- a/t/t7510-signed-commit.sh
+++ b/t/t7510-signed-commit.sh
@@ -4,6 +4,7 @@ test_description='signed commit tests'
 GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
 export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
 
+TEST_PASSES_SANITIZE_LEAK=true
 . ./test-lib.sh
 GNUPGHOME_NOT_USED=$GNUPGHOME
 . "$TEST_DIRECTORY/lib-gpg.sh"
diff --git a/t/t7528-signed-commit-ssh.sh b/t/t7528-signed-commit-ssh.sh
index 065f7806362..68e18856b66 100755
--- a/t/t7528-signed-commit-ssh.sh
+++ b/t/t7528-signed-commit-ssh.sh
@@ -4,6 +4,7 @@ test_description='ssh signed commit tests'
 GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
 export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
 
+TEST_PASSES_SANITIZE_LEAK=true
 . ./test-lib.sh
 GNUPGHOME_NOT_USED=$GNUPGHOME
 . "$TEST_DIRECTORY/lib-gpg.sh"
-- 
2.47.0.dirty


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

* [PATCH 08/21] upload-pack: fix leaking URI protocols
  2024-10-11  5:32 [PATCH 00/21] Memory leak fixes (pt.9) Patrick Steinhardt
                   ` (6 preceding siblings ...)
  2024-10-11  5:32 ` [PATCH 07/21] pretty: clear signature check Patrick Steinhardt
@ 2024-10-11  5:32 ` Patrick Steinhardt
  2024-10-11  5:32 ` [PATCH 09/21] builtin/commit: fix leaking change data contents Patrick Steinhardt
                   ` (15 subsequent siblings)
  23 siblings, 0 replies; 100+ messages in thread
From: Patrick Steinhardt @ 2024-10-11  5:32 UTC (permalink / raw)
  To: git

We don't clear `struct upload_pack::uri_protocols`, which causes a
memory leak. Fix this.

Signed-off-by: Patrick Steinhardt <ps@pks.im>
---
 t/t5702-protocol-v2.sh | 1 +
 upload-pack.c          | 1 +
 2 files changed, 2 insertions(+)

diff --git a/t/t5702-protocol-v2.sh b/t/t5702-protocol-v2.sh
index 1ef540f73d3..ed55a2f7f95 100755
--- a/t/t5702-protocol-v2.sh
+++ b/t/t5702-protocol-v2.sh
@@ -7,6 +7,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 protocol v2 with 'git://' transport
diff --git a/upload-pack.c b/upload-pack.c
index 6d6e0f9f980..b4a59c3518b 100644
--- a/upload-pack.c
+++ b/upload-pack.c
@@ -166,6 +166,7 @@ static void upload_pack_data_clear(struct upload_pack_data *data)
 	object_array_clear(&data->extra_edge_obj);
 	list_objects_filter_release(&data->filter_options);
 	string_list_clear(&data->allowed_filters, 0);
+	string_list_clear(&data->uri_protocols, 0);
 
 	free((char *)data->pack_objects_hook);
 }
-- 
2.47.0.dirty


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

* [PATCH 09/21] builtin/commit: fix leaking change data contents
  2024-10-11  5:32 [PATCH 00/21] Memory leak fixes (pt.9) Patrick Steinhardt
                   ` (7 preceding siblings ...)
  2024-10-11  5:32 ` [PATCH 08/21] upload-pack: fix leaking URI protocols Patrick Steinhardt
@ 2024-10-11  5:32 ` Patrick Steinhardt
  2024-10-11  5:32 ` [PATCH 10/21] trailer: fix leaking trailer values Patrick Steinhardt
                   ` (14 subsequent siblings)
  23 siblings, 0 replies; 100+ messages in thread
From: Patrick Steinhardt @ 2024-10-11  5:32 UTC (permalink / raw)
  To: git

While we free the worktree change data, we never free its contents. Fix
this.

Signed-off-by: Patrick Steinhardt <ps@pks.im>
---
 builtin/commit.c                          | 9 ++++++++-
 t/t7500-commit-template-squash-signoff.sh | 1 +
 2 files changed, 9 insertions(+), 1 deletion(-)

diff --git a/builtin/commit.c b/builtin/commit.c
index 8db4e9df0c9..18a55bd1b91 100644
--- a/builtin/commit.c
+++ b/builtin/commit.c
@@ -728,6 +728,13 @@ static void prepare_amend_commit(struct commit *commit, struct strbuf *sb,
 	repo_unuse_commit_buffer(the_repository, commit, buffer);
 }
 
+static void change_data_free(void *util, const char *str UNUSED)
+{
+	struct wt_status_change_data *d = util;
+	free(d->rename_source);
+	free(d);
+}
+
 static int prepare_to_commit(const char *index_file, const char *prefix,
 			     struct commit *current_head,
 			     struct wt_status *s,
@@ -991,7 +998,7 @@ static int prepare_to_commit(const char *index_file, const char *prefix,
 		s->use_color = 0;
 		committable = run_status(s->fp, index_file, prefix, 1, s);
 		s->use_color = saved_color_setting;
-		string_list_clear(&s->change, 1);
+		string_list_clear_func(&s->change, change_data_free);
 	} else {
 		struct object_id oid;
 		const char *parent = "HEAD";
diff --git a/t/t7500-commit-template-squash-signoff.sh b/t/t7500-commit-template-squash-signoff.sh
index 4dca8d97a77..379d3ed3413 100755
--- a/t/t7500-commit-template-squash-signoff.sh
+++ b/t/t7500-commit-template-squash-signoff.sh
@@ -7,6 +7,7 @@ test_description='git commit
 
 Tests for template, signoff, squash and -F functions.'
 
+TEST_PASSES_SANITIZE_LEAK=true
 . ./test-lib.sh
 
 . "$TEST_DIRECTORY"/lib-rebase.sh
-- 
2.47.0.dirty


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

* [PATCH 10/21] trailer: fix leaking trailer values
  2024-10-11  5:32 [PATCH 00/21] Memory leak fixes (pt.9) Patrick Steinhardt
                   ` (8 preceding siblings ...)
  2024-10-11  5:32 ` [PATCH 09/21] builtin/commit: fix leaking change data contents Patrick Steinhardt
@ 2024-10-11  5:32 ` Patrick Steinhardt
  2024-10-18 12:03   ` Toon Claes
  2024-10-11  5:32 ` [PATCH 11/21] builtin/commit: fix leaking cleanup config Patrick Steinhardt
                   ` (13 subsequent siblings)
  23 siblings, 1 reply; 100+ messages in thread
From: Patrick Steinhardt @ 2024-10-11  5:32 UTC (permalink / raw)
  To: git

Fix leaking trailer values when replacing the value with a command or
when the token value is empty.

Signed-off-by: Patrick Steinhardt <ps@pks.im>
---
 t/t7513-interpret-trailers.sh |  1 +
 trailer.c                     | 18 +++++++++++++-----
 2 files changed, 14 insertions(+), 5 deletions(-)

diff --git a/t/t7513-interpret-trailers.sh b/t/t7513-interpret-trailers.sh
index 0f7d8938d98..38d6ccaa001 100755
--- a/t/t7513-interpret-trailers.sh
+++ b/t/t7513-interpret-trailers.sh
@@ -5,6 +5,7 @@
 
 test_description='git interpret-trailers'
 
+TEST_PASSES_SANITIZE_LEAK=true
 . ./test-lib.sh
 
 # When we want one trailing space at the end of each line, let's use sed
diff --git a/trailer.c b/trailer.c
index 682d74505bf..5c0bfb735a9 100644
--- a/trailer.c
+++ b/trailer.c
@@ -249,17 +249,23 @@ static char *apply_command(struct conf_info *conf, const char *arg)
 static void apply_item_command(struct trailer_item *in_tok, struct arg_item *arg_tok)
 {
 	if (arg_tok->conf.command || arg_tok->conf.cmd) {
-		const char *arg;
+		char *value_to_free = NULL;
+		char *arg;
+
 		if (arg_tok->value && arg_tok->value[0]) {
-			arg = arg_tok->value;
+			arg = (char *)arg_tok->value;
 		} else {
 			if (in_tok && in_tok->value)
 				arg = xstrdup(in_tok->value);
 			else
 				arg = xstrdup("");
+			value_to_free = arg_tok->value;
 		}
+
 		arg_tok->value = apply_command(&arg_tok->conf, arg);
-		free((char *)arg);
+
+		free(value_to_free);
+		free(arg);
 	}
 }
 
@@ -1114,6 +1120,7 @@ void format_trailers(const struct process_trailer_options *opts,
 		if (item->token) {
 			struct strbuf tok = STRBUF_INIT;
 			struct strbuf val = STRBUF_INIT;
+
 			strbuf_addstr(&tok, item->token);
 			strbuf_addstr(&val, item->value);
 
@@ -1124,7 +1131,7 @@ void format_trailers(const struct process_trailer_options *opts,
 			 * corresponding value).
 			 */
 			if (opts->trim_empty && !strlen(item->value))
-				continue;
+				goto next;
 
 			if (!opts->filter || opts->filter(&tok, opts->filter_data)) {
 				if (opts->separator && out->len != origlen)
@@ -1145,9 +1152,10 @@ void format_trailers(const struct process_trailer_options *opts,
 				if (!opts->separator)
 					strbuf_addch(out, '\n');
 			}
+
+next:
 			strbuf_release(&tok);
 			strbuf_release(&val);
-
 		} else if (!opts->only_trailers) {
 			if (opts->separator && out->len != origlen) {
 				strbuf_addbuf(out, opts->separator);
-- 
2.47.0.dirty


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

* [PATCH 11/21] builtin/commit: fix leaking cleanup config
  2024-10-11  5:32 [PATCH 00/21] Memory leak fixes (pt.9) Patrick Steinhardt
                   ` (9 preceding siblings ...)
  2024-10-11  5:32 ` [PATCH 10/21] trailer: fix leaking trailer values Patrick Steinhardt
@ 2024-10-11  5:32 ` Patrick Steinhardt
  2024-10-11  5:32 ` [PATCH 12/21] transport-helper: fix leaking import/export marks Patrick Steinhardt
                   ` (12 subsequent siblings)
  23 siblings, 0 replies; 100+ messages in thread
From: Patrick Steinhardt @ 2024-10-11  5:32 UTC (permalink / raw)
  To: git

The cleanup string set by the config is leaking when it is being
overridden by an option. Fix this by tracking these via two separate
variables such that we can free the old value.

Signed-off-by: Patrick Steinhardt <ps@pks.im>
---
 builtin/commit.c            | 17 ++++++++++++-----
 t/t7502-commit-porcelain.sh |  1 +
 2 files changed, 13 insertions(+), 5 deletions(-)

diff --git a/builtin/commit.c b/builtin/commit.c
index 18a55bd1b91..71d674138c9 100644
--- a/builtin/commit.c
+++ b/builtin/commit.c
@@ -135,7 +135,7 @@ static struct strvec trailer_args = STRVEC_INIT;
  * is specified explicitly.
  */
 static enum commit_msg_cleanup_mode cleanup_mode;
-static char *cleanup_arg;
+static char *cleanup_config;
 
 static enum commit_whence whence;
 static int use_editor = 1, include_status = 1;
@@ -1387,8 +1387,6 @@ static int parse_and_validate_options(int argc, const char *argv[],
 	if (0 <= edit_flag)
 		use_editor = edit_flag;
 
-	cleanup_mode = get_cleanup_mode(cleanup_arg, use_editor);
-
 	handle_untracked_files_arg(s);
 
 	if (all && argc > 0)
@@ -1636,8 +1634,10 @@ static int git_commit_config(const char *k, const char *v,
 		include_status = git_config_bool(k, v);
 		return 0;
 	}
-	if (!strcmp(k, "commit.cleanup"))
-		return git_config_string(&cleanup_arg, k, v);
+	if (!strcmp(k, "commit.cleanup")) {
+		FREE_AND_NULL(cleanup_config);
+		return git_config_string(&cleanup_config, k, v);
+	}
 	if (!strcmp(k, "commit.gpgsign")) {
 		sign_commit = git_config_bool(k, v) ? "" : NULL;
 		return 0;
@@ -1658,6 +1658,7 @@ int cmd_commit(int argc,
 	       struct repository *repo UNUSED)
 {
 	static struct wt_status s;
+	static const char *cleanup_arg = NULL;
 	static struct option builtin_commit_options[] = {
 		OPT__QUIET(&quiet, N_("suppress summary after successful commit")),
 		OPT__VERBOSE(&verbose, N_("show diff in commit message template")),
@@ -1757,6 +1758,12 @@ int cmd_commit(int argc,
 	if (verbose == -1)
 		verbose = (config_commit_verbose < 0) ? 0 : config_commit_verbose;
 
+	if (cleanup_arg) {
+		free(cleanup_config);
+		cleanup_config = xstrdup(cleanup_arg);
+	}
+	cleanup_mode = get_cleanup_mode(cleanup_config, use_editor);
+
 	if (dry_run)
 		return dry_run_commit(argv, prefix, current_head, &s);
 	index_file = prepare_index(argv, prefix, current_head, 0);
diff --git a/t/t7502-commit-porcelain.sh b/t/t7502-commit-porcelain.sh
index b37e2018a74..84f1ff52b67 100755
--- a/t/t7502-commit-porcelain.sh
+++ b/t/t7502-commit-porcelain.sh
@@ -5,6 +5,7 @@ test_description='git commit porcelain-ish'
 GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
 export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
 
+TEST_PASSES_SANITIZE_LEAK=true
 . ./test-lib.sh
 
 commit_msg_is () {
-- 
2.47.0.dirty


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

* [PATCH 12/21] transport-helper: fix leaking import/export marks
  2024-10-11  5:32 [PATCH 00/21] Memory leak fixes (pt.9) Patrick Steinhardt
                   ` (10 preceding siblings ...)
  2024-10-11  5:32 ` [PATCH 11/21] builtin/commit: fix leaking cleanup config Patrick Steinhardt
@ 2024-10-11  5:32 ` Patrick Steinhardt
  2024-10-11  5:32 ` [PATCH 13/21] builtin/tag: fix leaking key ID on failure to sign Patrick Steinhardt
                   ` (11 subsequent siblings)
  23 siblings, 0 replies; 100+ messages in thread
From: Patrick Steinhardt @ 2024-10-11  5:32 UTC (permalink / raw)
  To: git

Fix leaking import and export marks for transport helpers.

Signed-off-by: Patrick Steinhardt <ps@pks.im>
---
 t/t5801-remote-helpers.sh | 1 +
 transport-helper.c        | 2 ++
 2 files changed, 3 insertions(+)

diff --git a/t/t5801-remote-helpers.sh b/t/t5801-remote-helpers.sh
index d21877150ed..d4882288a30 100755
--- a/t/t5801-remote-helpers.sh
+++ b/t/t5801-remote-helpers.sh
@@ -8,6 +8,7 @@ test_description='Test remote-helper import and export commands'
 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/transport-helper.c b/transport-helper.c
index 013ec79dc9c..bc27653cdee 100644
--- a/transport-helper.c
+++ b/transport-helper.c
@@ -399,6 +399,8 @@ static int release_helper(struct transport *transport)
 	int res = 0;
 	struct helper_data *data = transport->data;
 	refspec_clear(&data->rs);
+	free(data->import_marks);
+	free(data->export_marks);
 	res = disconnect_helper(transport);
 	free(transport->data);
 	return res;
-- 
2.47.0.dirty


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

* [PATCH 13/21] builtin/tag: fix leaking key ID on failure to sign
  2024-10-11  5:32 [PATCH 00/21] Memory leak fixes (pt.9) Patrick Steinhardt
                   ` (11 preceding siblings ...)
  2024-10-11  5:32 ` [PATCH 12/21] transport-helper: fix leaking import/export marks Patrick Steinhardt
@ 2024-10-11  5:32 ` Patrick Steinhardt
  2024-10-11  5:32 ` [PATCH 14/21] combine-diff: fix leaking lost lines Patrick Steinhardt
                   ` (10 subsequent siblings)
  23 siblings, 0 replies; 100+ messages in thread
From: Patrick Steinhardt @ 2024-10-11  5:32 UTC (permalink / raw)
  To: git

We do not free the key ID when signing a tag fails. Do so by using
the common exit path.

Signed-off-by: Patrick Steinhardt <ps@pks.im>
---
 builtin/tag.c  | 2 +-
 t/t7004-tag.sh | 1 +
 2 files changed, 2 insertions(+), 1 deletion(-)

diff --git a/builtin/tag.c b/builtin/tag.c
index 93d10d59157..c37c0a68fda 100644
--- a/builtin/tag.c
+++ b/builtin/tag.c
@@ -164,7 +164,7 @@ static int do_sign(struct strbuf *buffer, struct object_id **compat_oid,
 	int ret = -1;
 
 	if (sign_buffer(buffer, &sig, keyid))
-		return -1;
+		goto out;
 
 	if (compat) {
 		const struct git_hash_algo *algo = the_repository->hash_algo;
diff --git a/t/t7004-tag.sh b/t/t7004-tag.sh
index b1316e62f46..42b3327e69b 100755
--- a/t/t7004-tag.sh
+++ b/t/t7004-tag.sh
@@ -10,6 +10,7 @@ Tests for operations with tags.'
 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
 . "$TEST_DIRECTORY"/lib-terminal.sh
-- 
2.47.0.dirty


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

* [PATCH 14/21] combine-diff: fix leaking lost lines
  2024-10-11  5:32 [PATCH 00/21] Memory leak fixes (pt.9) Patrick Steinhardt
                   ` (12 preceding siblings ...)
  2024-10-11  5:32 ` [PATCH 13/21] builtin/tag: fix leaking key ID on failure to sign Patrick Steinhardt
@ 2024-10-11  5:32 ` Patrick Steinhardt
  2024-10-11  5:32 ` [PATCH 15/21] dir: release untracked cache data Patrick Steinhardt
                   ` (9 subsequent siblings)
  23 siblings, 0 replies; 100+ messages in thread
From: Patrick Steinhardt @ 2024-10-11  5:32 UTC (permalink / raw)
  To: git

The `cnt` variable tracks the number of lines in a patch diff. It can
happen though that there are no newlines, in which case we'd still end
up allocating our array of `sline`s. In fact, we always allocate it with
`cnt + 2` entries. But when we loop through the array to clear it at the
end of this function we only loop until `lno < cnt`, and thus we may not
end up releasing whatever the two extra `sline`s contain.

Plug this memory leak.

Signed-off-by: Patrick Steinhardt <ps@pks.im>
---
 combine-diff.c           | 2 +-
 t/t4038-diff-combined.sh | 1 +
 2 files changed, 2 insertions(+), 1 deletion(-)

diff --git a/combine-diff.c b/combine-diff.c
index f6b624dc288..3c6d9507fec 100644
--- a/combine-diff.c
+++ b/combine-diff.c
@@ -1220,7 +1220,7 @@ static void show_patch_diff(struct combine_diff_path *elem, int num_parent,
 	}
 	free(result);
 
-	for (lno = 0; lno < cnt; lno++) {
+	for (lno = 0; lno < cnt + 2; lno++) {
 		if (sline[lno].lost) {
 			struct lline *ll = sline[lno].lost;
 			while (ll) {
diff --git a/t/t4038-diff-combined.sh b/t/t4038-diff-combined.sh
index 2ce26e585c9..00190802d83 100755
--- a/t/t4038-diff-combined.sh
+++ b/t/t4038-diff-combined.sh
@@ -5,6 +5,7 @@ test_description='combined diff'
 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-diff.sh
 
-- 
2.47.0.dirty


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

* [PATCH 15/21] dir: release untracked cache data
  2024-10-11  5:32 [PATCH 00/21] Memory leak fixes (pt.9) Patrick Steinhardt
                   ` (13 preceding siblings ...)
  2024-10-11  5:32 ` [PATCH 14/21] combine-diff: fix leaking lost lines Patrick Steinhardt
@ 2024-10-11  5:32 ` Patrick Steinhardt
  2024-10-11  5:32 ` [PATCH 16/21] sparse-index: correctly free EWAH contents Patrick Steinhardt
                   ` (8 subsequent siblings)
  23 siblings, 0 replies; 100+ messages in thread
From: Patrick Steinhardt @ 2024-10-11  5:32 UTC (permalink / raw)
  To: git

There are several cases where we invalidate untracked cache directory
entries where we do not free the underlying data, but reset the number
of entries. This causes us to leak memory because `free_untracked()`
will not iterate over any potential entries which we still had in the
array.

Fix this issue by freeing old entries. The leak is exposed by t7519, but
plugging it alone does not make the whole test suite pass.

Signed-off-by: Patrick Steinhardt <ps@pks.im>
---
 dir.c | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/dir.c b/dir.c
index e3ddd5b5296..cb9782fa11f 100644
--- a/dir.c
+++ b/dir.c
@@ -1056,6 +1056,8 @@ static void do_invalidate_gitignore(struct untracked_cache_dir *dir)
 {
 	int i;
 	dir->valid = 0;
+	for (size_t i = 0; i < dir->untracked_nr; i++)
+		free(dir->untracked[i]);
 	dir->untracked_nr = 0;
 	for (i = 0; i < dir->dirs_nr; i++)
 		do_invalidate_gitignore(dir->dirs[i]);
@@ -1083,6 +1085,8 @@ static void invalidate_directory(struct untracked_cache *uc,
 		uc->dir_invalidated++;
 
 	dir->valid = 0;
+	for (size_t i = 0; i < dir->untracked_nr; i++)
+		free(dir->untracked[i]);
 	dir->untracked_nr = 0;
 	for (i = 0; i < dir->dirs_nr; i++)
 		dir->dirs[i]->recurse = 0;
@@ -3573,6 +3577,8 @@ static void write_one_dir(struct untracked_cache_dir *untracked,
 	 * for safety..
 	 */
 	if (!untracked->valid) {
+		for (size_t i = 0; i < untracked->untracked_nr; i++)
+			free(untracked->untracked[i]);
 		untracked->untracked_nr = 0;
 		untracked->check_only = 0;
 	}
@@ -3905,6 +3911,8 @@ static void invalidate_one_directory(struct untracked_cache *uc,
 {
 	uc->dir_invalidated++;
 	ucd->valid = 0;
+	for (size_t i = 0; i < ucd->untracked_nr; i++)
+		free(ucd->untracked[i]);
 	ucd->untracked_nr = 0;
 }
 
-- 
2.47.0.dirty


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

* [PATCH 16/21] sparse-index: correctly free EWAH contents
  2024-10-11  5:32 [PATCH 00/21] Memory leak fixes (pt.9) Patrick Steinhardt
                   ` (14 preceding siblings ...)
  2024-10-11  5:32 ` [PATCH 15/21] dir: release untracked cache data Patrick Steinhardt
@ 2024-10-11  5:32 ` Patrick Steinhardt
  2024-10-11  5:32 ` [PATCH 17/21] t/helper: stop re-initialization of `the_repository` Patrick Steinhardt
                   ` (7 subsequent siblings)
  23 siblings, 0 replies; 100+ messages in thread
From: Patrick Steinhardt @ 2024-10-11  5:32 UTC (permalink / raw)
  To: git

While we free the `fsmonitor_dirty` member of `struct index_state`, we
do not free the contents of that EWAH. Do so by using `ewah_free()`
instead of `FREE_AND_NULL()`.

This leak is exposed by t7519, but plugging it alone does not make the
test suite pass.

Signed-off-by: Patrick Steinhardt <ps@pks.im>
---
 sparse-index.c | 7 +++++--
 1 file changed, 5 insertions(+), 2 deletions(-)

diff --git a/sparse-index.c b/sparse-index.c
index 3d7f2164e25..2107840bfc5 100644
--- a/sparse-index.c
+++ b/sparse-index.c
@@ -2,6 +2,7 @@
 
 #include "git-compat-util.h"
 #include "environment.h"
+#include "ewah/ewok.h"
 #include "gettext.h"
 #include "name-hash.h"
 #include "read-cache-ll.h"
@@ -242,7 +243,8 @@ int convert_to_sparse(struct index_state *istate, int flags)
 	cache_tree_update(istate, 0);
 
 	istate->fsmonitor_has_run_once = 0;
-	FREE_AND_NULL(istate->fsmonitor_dirty);
+	ewah_free(istate->fsmonitor_dirty);
+	istate->fsmonitor_dirty = NULL;
 	FREE_AND_NULL(istate->fsmonitor_last_update);
 
 	istate->sparse_index = INDEX_COLLAPSED;
@@ -438,7 +440,8 @@ void expand_index(struct index_state *istate, struct pattern_list *pl)
 	istate->cache_nr = full->cache_nr;
 	istate->cache_alloc = full->cache_alloc;
 	istate->fsmonitor_has_run_once = 0;
-	FREE_AND_NULL(istate->fsmonitor_dirty);
+	ewah_free(istate->fsmonitor_dirty);
+	istate->fsmonitor_dirty = NULL;
 	FREE_AND_NULL(istate->fsmonitor_last_update);
 
 	strbuf_release(&base);
-- 
2.47.0.dirty


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

* [PATCH 17/21] t/helper: stop re-initialization of `the_repository`
  2024-10-11  5:32 [PATCH 00/21] Memory leak fixes (pt.9) Patrick Steinhardt
                   ` (15 preceding siblings ...)
  2024-10-11  5:32 ` [PATCH 16/21] sparse-index: correctly free EWAH contents Patrick Steinhardt
@ 2024-10-11  5:32 ` Patrick Steinhardt
  2024-10-11  5:33 ` [PATCH 18/21] t/helper: fix leaking buffer in "dump-untracked-cache" Patrick Steinhardt
                   ` (6 subsequent siblings)
  23 siblings, 0 replies; 100+ messages in thread
From: Patrick Steinhardt @ 2024-10-11  5:32 UTC (permalink / raw)
  To: git

While "common-main.c" already initializes `the_repository` for us, we do
so a second time in the "read-cache" test helper. This causes a memory
leak because the old repository's contents isn't released.

Stop calling `initialize_repository()` to plug this leak.

Signed-off-by: Patrick Steinhardt <ps@pks.im>
---
 t/helper/test-read-cache.c  | 2 --
 t/t7519-status-fsmonitor.sh | 1 +
 2 files changed, 1 insertion(+), 2 deletions(-)

diff --git a/t/helper/test-read-cache.c b/t/helper/test-read-cache.c
index d285c656bd3..e277dde8e71 100644
--- a/t/helper/test-read-cache.c
+++ b/t/helper/test-read-cache.c
@@ -11,8 +11,6 @@ int cmd__read_cache(int argc, const char **argv)
 	int i, cnt = 1;
 	const char *name = NULL;
 
-	initialize_repository(the_repository);
-
 	if (argc > 1 && skip_prefix(argv[1], "--print-and-refresh=", &name)) {
 		argc--;
 		argv++;
diff --git a/t/t7519-status-fsmonitor.sh b/t/t7519-status-fsmonitor.sh
index 7ee69ecdd4a..0f88a58a819 100755
--- a/t/t7519-status-fsmonitor.sh
+++ b/t/t7519-status-fsmonitor.sh
@@ -2,6 +2,7 @@
 
 test_description='git status with file system watcher'
 
+TEST_PASSES_SANITIZE_LEAK=true
 . ./test-lib.sh
 
 # Note, after "git reset --hard HEAD" no extensions exist other than 'TREE'
-- 
2.47.0.dirty


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

* [PATCH 18/21] t/helper: fix leaking buffer in "dump-untracked-cache"
  2024-10-11  5:32 [PATCH 00/21] Memory leak fixes (pt.9) Patrick Steinhardt
                   ` (16 preceding siblings ...)
  2024-10-11  5:32 ` [PATCH 17/21] t/helper: stop re-initialization of `the_repository` Patrick Steinhardt
@ 2024-10-11  5:33 ` Patrick Steinhardt
  2024-10-11  5:33 ` [PATCH 19/21] dir: fix leak when parsing "status.showUntrackedFiles" Patrick Steinhardt
                   ` (5 subsequent siblings)
  23 siblings, 0 replies; 100+ messages in thread
From: Patrick Steinhardt @ 2024-10-11  5:33 UTC (permalink / raw)
  To: git

We never release the local `struct strbuf base` buffer, thus leaking
memory. Fix this leak.

This leak is exposed by t7063, but plugging it alone does not make the
whole test suite pass.

Signed-off-by: Patrick Steinhardt <ps@pks.im>
---
 t/helper/test-dump-untracked-cache.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/t/helper/test-dump-untracked-cache.c b/t/helper/test-dump-untracked-cache.c
index 4f010d53249..b2e70837a90 100644
--- a/t/helper/test-dump-untracked-cache.c
+++ b/t/helper/test-dump-untracked-cache.c
@@ -68,5 +68,7 @@ int cmd__dump_untracked_cache(int ac UNUSED, const char **av UNUSED)
 	printf("flags %08x\n", uc->dir_flags);
 	if (uc->root)
 		dump(uc->root, &base);
+
+	strbuf_release(&base);
 	return 0;
 }
-- 
2.47.0.dirty


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

* [PATCH 19/21] dir: fix leak when parsing "status.showUntrackedFiles"
  2024-10-11  5:32 [PATCH 00/21] Memory leak fixes (pt.9) Patrick Steinhardt
                   ` (17 preceding siblings ...)
  2024-10-11  5:33 ` [PATCH 18/21] t/helper: fix leaking buffer in "dump-untracked-cache" Patrick Steinhardt
@ 2024-10-11  5:33 ` Patrick Steinhardt
  2024-10-11  5:33 ` [PATCH 20/21] builtin/merge: release outbut buffer after performing merge Patrick Steinhardt
                   ` (4 subsequent siblings)
  23 siblings, 0 replies; 100+ messages in thread
From: Patrick Steinhardt @ 2024-10-11  5:33 UTC (permalink / raw)
  To: git

We use `repo_config_get_string()` to read "status.showUntrackedFiles"
from the config subsystem. This function allocates the result, but we
never free the result after parsing it.

The value never leaves the scope of the calling function, so refactor it
to instead use `repo_config_get_string_tmp()`, which does not hand over
ownership to the caller.

Signed-off-by: Patrick Steinhardt <ps@pks.im>
---
 dir.c                             | 4 ++--
 t/t7063-status-untracked-cache.sh | 1 +
 2 files changed, 3 insertions(+), 2 deletions(-)

diff --git a/dir.c b/dir.c
index cb9782fa11f..7f35a3e3175 100644
--- a/dir.c
+++ b/dir.c
@@ -2872,14 +2872,14 @@ static void set_untracked_ident(struct untracked_cache *uc)
 static unsigned new_untracked_cache_flags(struct index_state *istate)
 {
 	struct repository *repo = istate->repo;
-	char *val;
+	const char *val;
 
 	/*
 	 * This logic is coordinated with the setting of these flags in
 	 * wt-status.c#wt_status_collect_untracked(), and the evaluation
 	 * of the config setting in commit.c#git_status_config()
 	 */
-	if (!repo_config_get_string(repo, "status.showuntrackedfiles", &val) &&
+	if (!repo_config_get_string_tmp(repo, "status.showuntrackedfiles", &val) &&
 	    !strcmp(val, "all"))
 		return 0;
 
diff --git a/t/t7063-status-untracked-cache.sh b/t/t7063-status-untracked-cache.sh
index 8929ef481f9..13fea7931cd 100755
--- a/t/t7063-status-untracked-cache.sh
+++ b/t/t7063-status-untracked-cache.sh
@@ -5,6 +5,7 @@ test_description='test untracked cache'
 GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
 export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
 
+TEST_PASSES_SANITIZE_LEAK=true
 . ./test-lib.sh
 
 # On some filesystems (e.g. FreeBSD's ext2 and ufs) directory mtime
-- 
2.47.0.dirty


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

* [PATCH 20/21] builtin/merge: release outbut buffer after performing merge
  2024-10-11  5:32 [PATCH 00/21] Memory leak fixes (pt.9) Patrick Steinhardt
                   ` (18 preceding siblings ...)
  2024-10-11  5:33 ` [PATCH 19/21] dir: fix leak when parsing "status.showUntrackedFiles" Patrick Steinhardt
@ 2024-10-11  5:33 ` Patrick Steinhardt
  2024-10-18 12:03   ` Toon Claes
  2024-10-11  5:33 ` [PATCH 21/21] list-objects-filter-options: work around reported leak on error Patrick Steinhardt
                   ` (3 subsequent siblings)
  23 siblings, 1 reply; 100+ messages in thread
From: Patrick Steinhardt @ 2024-10-11  5:33 UTC (permalink / raw)
  To: git

The `obuf` member of `struct merge_options` is used to buffer output in
some cases. In order to not discard its allocated memory we only release
its contents in `merge_finalize()` when we're not currently recursing
into a subtree.

This results in some situations where we seemingly do not release the
buffer reliably. We thus have calls to `strbuf_release()` for this
buffer scattered across the codebase. But we're missing one callsite in
git-merge(1), which causes a memory leak.

We should ideally refactor this interface so that callers don't have to
know about any such internals. But for now, paper over the issue by
adding one more `strbuf_release()` call.

Signed-off-by: Patrick Steinhardt <ps@pks.im>
---
 builtin/merge.c                          | 1 +
 t/t6424-merge-unrelated-index-changes.sh | 1 +
 2 files changed, 2 insertions(+)

diff --git a/builtin/merge.c b/builtin/merge.c
index 84d0f3604bc..51038eaca84 100644
--- a/builtin/merge.c
+++ b/builtin/merge.c
@@ -754,6 +754,7 @@ static int try_merge_strategy(const char *strategy, struct commit_list *common,
 			clean = merge_recursive(&o, head, remoteheads->item,
 						reversed, &result);
 		free_commit_list(reversed);
+		strbuf_release(&o.obuf);
 
 		if (clean < 0) {
 			rollback_lock_file(&lock);
diff --git a/t/t6424-merge-unrelated-index-changes.sh b/t/t6424-merge-unrelated-index-changes.sh
index 7677c5f08d0..a7ea8acb845 100755
--- a/t/t6424-merge-unrelated-index-changes.sh
+++ b/t/t6424-merge-unrelated-index-changes.sh
@@ -2,6 +2,7 @@
 
 test_description="merges with unrelated index changes"
 
+TEST_PASSES_SANITIZE_LEAK=true
 . ./test-lib.sh
 
 # Testcase for some simple merges
-- 
2.47.0.dirty


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

* [PATCH 21/21] list-objects-filter-options: work around reported leak on error
  2024-10-11  5:32 [PATCH 00/21] Memory leak fixes (pt.9) Patrick Steinhardt
                   ` (19 preceding siblings ...)
  2024-10-11  5:33 ` [PATCH 20/21] builtin/merge: release outbut buffer after performing merge Patrick Steinhardt
@ 2024-10-11  5:33 ` Patrick Steinhardt
  2024-10-18 12:04   ` Toon Claes
  2024-10-18 21:30 ` [PATCH 00/21] Memory leak fixes (pt.9) Taylor Blau
                   ` (2 subsequent siblings)
  23 siblings, 1 reply; 100+ messages in thread
From: Patrick Steinhardt @ 2024-10-11  5:33 UTC (permalink / raw)
  To: git

This one is a little bit more curious. In t6112, we have a test that
exercises the `git rev-list --filter` option with invalid filters. We
execute git-rev-list(1) via `test_must_fail`, which means that we check
for leaks even though Git exits with an error code. This causes the
following leak:

    Direct leak of 27 byte(s) in 1 object(s) allocated from:
        #0 0x5555555e6946 in realloc.part.0 lsan_interceptors.cpp.o
        #1 0x5555558fb4b6 in xrealloc wrapper.c:137:8
        #2 0x5555558b6e06 in strbuf_grow strbuf.c:112:2
        #3 0x5555558b7550 in strbuf_add strbuf.c:311:2
        #4 0x5555557c1a88 in strbuf_addstr strbuf.h:310:2
        #5 0x5555557c1d4c in parse_list_objects_filter list-objects-filter-options.c:261:3
        #6 0x555555885ead in handle_revision_pseudo_opt revision.c:2899:3
        #7 0x555555884e20 in setup_revisions revision.c:3014:11
        #8 0x5555556c4b42 in cmd_rev_list builtin/rev-list.c:588:9
        #9 0x5555555ec5e3 in run_builtin git.c:483:11
        #10 0x5555555eb1e4 in handle_builtin git.c:749:13
        #11 0x5555555ec001 in run_argv git.c:819:4
        #12 0x5555555eaf94 in cmd_main git.c:954:19
        #13 0x5555556fd569 in main common-main.c:64:11
        #14 0x7ffff7ca714d in __libc_start_call_main (.../lib/libc.so.6+0x2a14d)
        #15 0x7ffff7ca7208 in __libc_start_main@GLIBC_2.2.5 (.../libc.so.6+0x2a208)
        #16 0x5555555ad064 in _start (git+0x59064)

This leak is valid, as we call `die()` and do not clean up the memory at
all. But what's curious is that this is the only leak reported, because
we don't clean up any other allocated memory, either, and I have no idea
why the leak sanitizer treats this buffer specially.

In any case, we can work around the leak by shuffling things around a
bit. Instead of calling `gently_parse_list_objects_filter()` and dying
after we have modified the filter spec, we simply do so beforehand. Like
this we don't allocate the buffer in the error case, which makes the
reported leak go away.

It's not pretty, but it manages to make t6112 leak free.

Signed-off-by: Patrick Steinhardt <ps@pks.im>
---
 list-objects-filter-options.c       | 17 +++++++----------
 t/t6112-rev-list-filters-objects.sh |  1 +
 2 files changed, 8 insertions(+), 10 deletions(-)

diff --git a/list-objects-filter-options.c b/list-objects-filter-options.c
index 00611107d20..fa72e81e4ad 100644
--- a/list-objects-filter-options.c
+++ b/list-objects-filter-options.c
@@ -252,16 +252,14 @@ void parse_list_objects_filter(
 	const char *arg)
 {
 	struct strbuf errbuf = STRBUF_INIT;
-	int parse_error;
 
 	if (!filter_options->filter_spec.buf)
 		BUG("filter_options not properly initialized");
 
 	if (!filter_options->choice) {
+		if (gently_parse_list_objects_filter(filter_options, arg, &errbuf))
+			die("%s", errbuf.buf);
 		strbuf_addstr(&filter_options->filter_spec, arg);
-
-		parse_error = gently_parse_list_objects_filter(
-			filter_options, arg, &errbuf);
 	} else {
 		struct list_objects_filter_options *sub;
 
@@ -271,18 +269,17 @@ void parse_list_objects_filter(
 		 */
 		transform_to_combine_type(filter_options);
 
-		strbuf_addch(&filter_options->filter_spec, '+');
-		filter_spec_append_urlencode(filter_options, arg);
 		ALLOC_GROW_BY(filter_options->sub, filter_options->sub_nr, 1,
 			      filter_options->sub_alloc);
 		sub = &filter_options->sub[filter_options->sub_nr - 1];
 
 		list_objects_filter_init(sub);
-		parse_error = gently_parse_list_objects_filter(sub, arg,
-							       &errbuf);
+		if (gently_parse_list_objects_filter(sub, arg, &errbuf))
+			die("%s", errbuf.buf);
+
+		strbuf_addch(&filter_options->filter_spec, '+');
+		filter_spec_append_urlencode(filter_options, arg);
 	}
-	if (parse_error)
-		die("%s", errbuf.buf);
 }
 
 int opt_parse_list_objects_filter(const struct option *opt,
diff --git a/t/t6112-rev-list-filters-objects.sh b/t/t6112-rev-list-filters-objects.sh
index 0387f35a326..71e38491fa8 100755
--- a/t/t6112-rev-list-filters-objects.sh
+++ b/t/t6112-rev-list-filters-objects.sh
@@ -5,6 +5,7 @@ test_description='git rev-list 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 the blob:none filter.
-- 
2.47.0.dirty


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

* Re: [PATCH 07/21] pretty: clear signature check
  2024-10-11  5:32 ` [PATCH 07/21] pretty: clear signature check Patrick Steinhardt
@ 2024-10-18 12:02   ` Toon Claes
  2024-10-21  8:44     ` Patrick Steinhardt
  0 siblings, 1 reply; 100+ messages in thread
From: Toon Claes @ 2024-10-18 12:02 UTC (permalink / raw)
  To: Patrick Steinhardt, git

Patrick Steinhardt <ps@pks.im> writes:

> The signature check in of the formatting context is never getting
> released. Fix this to plug the resulting memory leak.
>
> Signed-off-by: Patrick Steinhardt <ps@pks.im>
> ---
>  pretty.c                         | 1 +
>  t/t4202-log.sh                   | 1 +
>  t/t7031-verify-tag-signed-ssh.sh | 1 +
>  t/t7510-signed-commit.sh         | 1 +
>  t/t7528-signed-commit-ssh.sh     | 1 +
>  5 files changed, 5 insertions(+)
>
> diff --git a/pretty.c b/pretty.c
> index 6403e268900..098378720a4 100644
> --- a/pretty.c
> +++ b/pretty.c
> @@ -2032,6 +2032,7 @@ void repo_format_commit_message(struct repository *r,
>  
>  	free(context.commit_encoding);
>  	repo_unuse_commit_buffer(r, commit, context.message);
> +	signature_check_clear(&context.signature_check);

I was having a very hard time finding where this gets allocated, and to
be honest, I still don't know for sure. I think in
check_commit_signature() which is called by format_commit_one().
In "[PATCH 20/21] builtin/merge: release outbut buffer after performing
merge" you mention it's not obvious to the caller they need know about
memory they need to clean up, isn't that case here as well?

--
Toon

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

* Re: [PATCH 10/21] trailer: fix leaking trailer values
  2024-10-11  5:32 ` [PATCH 10/21] trailer: fix leaking trailer values Patrick Steinhardt
@ 2024-10-18 12:03   ` Toon Claes
  2024-10-21  8:44     ` Patrick Steinhardt
  0 siblings, 1 reply; 100+ messages in thread
From: Toon Claes @ 2024-10-18 12:03 UTC (permalink / raw)
  To: Patrick Steinhardt, git

Patrick Steinhardt <ps@pks.im> writes:

> Fix leaking trailer values when replacing the value with a command or
> when the token value is empty.
>
> Signed-off-by: Patrick Steinhardt <ps@pks.im>
> ---
>
> diff --git a/trailer.c b/trailer.c
> index 682d74505bf..5c0bfb735a9 100644
> --- a/trailer.c
> +++ b/trailer.c
> @@ -1124,7 +1131,7 @@ void format_trailers(const struct process_trailer_options *opts,
>  			 * corresponding value).
>  			 */
>  			if (opts->trim_empty && !strlen(item->value))
> -				continue;
> +				goto next;

While this is technically correct, I found it rather hard to understand
what's happening. What do you think about instead turning the `if` below
in an `else if` ?

>  
>  			if (!opts->filter || opts->filter(&tok, opts->filter_data)) {
>  				if (opts->separator && out->len != origlen)
> @@ -1145,9 +1152,10 @@ void format_trailers(const struct process_trailer_options *opts,
>  				if (!opts->separator)
>  					strbuf_addch(out, '\n');
>  			}
> +
> +next:
>  			strbuf_release(&tok);
>  			strbuf_release(&val);
> -
>  		} else if (!opts->only_trailers) {
>  			if (opts->separator && out->len != origlen) {
>  				strbuf_addbuf(out, opts->separator);
> -- 
> 2.47.0.dirty

--
Toon

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

* Re: [PATCH 20/21] builtin/merge: release outbut buffer after performing merge
  2024-10-11  5:33 ` [PATCH 20/21] builtin/merge: release outbut buffer after performing merge Patrick Steinhardt
@ 2024-10-18 12:03   ` Toon Claes
  2024-10-21  8:45     ` Patrick Steinhardt
  0 siblings, 1 reply; 100+ messages in thread
From: Toon Claes @ 2024-10-18 12:03 UTC (permalink / raw)
  To: Patrick Steinhardt, git

Patrick Steinhardt <ps@pks.im> writes:

> The `obuf` member of `struct merge_options` is used to buffer output in
> some cases. In order to not discard its allocated memory we only release
> its contents in `merge_finalize()` when we're not currently recursing
> into a subtree.
>
> This results in some situations where we seemingly do not release the
> buffer reliably. We thus have calls to `strbuf_release()` for this
> buffer scattered across the codebase. But we're missing one callsite in
> git-merge(1), which causes a memory leak.
>
> We should ideally refactor this interface so that callers don't have to
> know about any such internals. But for now, paper over the issue by
> adding one more `strbuf_release()` call.

Shall we mark this as #leftoverbits?

--
Toon

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

* Re: [PATCH 21/21] list-objects-filter-options: work around reported leak on error
  2024-10-11  5:33 ` [PATCH 21/21] list-objects-filter-options: work around reported leak on error Patrick Steinhardt
@ 2024-10-18 12:04   ` Toon Claes
  2024-10-21  8:45     ` Patrick Steinhardt
  0 siblings, 1 reply; 100+ messages in thread
From: Toon Claes @ 2024-10-18 12:04 UTC (permalink / raw)
  To: Patrick Steinhardt, git

Patrick Steinhardt <ps@pks.im> writes:

> This one is a little bit more curious. In t6112, we have a test that
> exercises the `git rev-list --filter` option with invalid filters. We
> execute git-rev-list(1) via `test_must_fail`, which means that we check
> for leaks even though Git exits with an error code. This causes the
> following leak:
>
>     Direct leak of 27 byte(s) in 1 object(s) allocated from:
>         #0 0x5555555e6946 in realloc.part.0 lsan_interceptors.cpp.o
>         #1 0x5555558fb4b6 in xrealloc wrapper.c:137:8
>         #2 0x5555558b6e06 in strbuf_grow strbuf.c:112:2
>         #3 0x5555558b7550 in strbuf_add strbuf.c:311:2
>         #4 0x5555557c1a88 in strbuf_addstr strbuf.h:310:2
>         #5 0x5555557c1d4c in parse_list_objects_filter list-objects-filter-options.c:261:3
>         #6 0x555555885ead in handle_revision_pseudo_opt revision.c:2899:3
>         #7 0x555555884e20 in setup_revisions revision.c:3014:11
>         #8 0x5555556c4b42 in cmd_rev_list builtin/rev-list.c:588:9
>         #9 0x5555555ec5e3 in run_builtin git.c:483:11
>         #10 0x5555555eb1e4 in handle_builtin git.c:749:13
>         #11 0x5555555ec001 in run_argv git.c:819:4
>         #12 0x5555555eaf94 in cmd_main git.c:954:19
>         #13 0x5555556fd569 in main common-main.c:64:11
>         #14 0x7ffff7ca714d in __libc_start_call_main (.../lib/libc.so.6+0x2a14d)
>         #15 0x7ffff7ca7208 in __libc_start_main@GLIBC_2.2.5 (.../libc.so.6+0x2a208)
>         #16 0x5555555ad064 in _start (git+0x59064)
>
> This leak is valid, as we call `die()` and do not clean up the memory at
> all. But what's curious is that this is the only leak reported, because
> we don't clean up any other allocated memory, either, and I have no idea
> why the leak sanitizer treats this buffer specially.
>
> In any case, we can work around the leak by shuffling things around a
> bit. Instead of calling `gently_parse_list_objects_filter()` and dying
> after we have modified the filter spec, we simply do so beforehand. Like
> this we don't allocate the buffer in the error case, which makes the
> reported leak go away.
>
> It's not pretty, but it manages to make t6112 leak free.
>
> Signed-off-by: Patrick Steinhardt <ps@pks.im>
> ---
>  list-objects-filter-options.c       | 17 +++++++----------
>  t/t6112-rev-list-filters-objects.sh |  1 +
>  2 files changed, 8 insertions(+), 10 deletions(-)
>
> diff --git a/list-objects-filter-options.c b/list-objects-filter-options.c
> index 00611107d20..fa72e81e4ad 100644
> --- a/list-objects-filter-options.c
> +++ b/list-objects-filter-options.c
> @@ -252,16 +252,14 @@ void parse_list_objects_filter(
>  	const char *arg)
>  {
>  	struct strbuf errbuf = STRBUF_INIT;
> -	int parse_error;
>  
>  	if (!filter_options->filter_spec.buf)
>  		BUG("filter_options not properly initialized");
>  
>  	if (!filter_options->choice) {
> +		if (gently_parse_list_objects_filter(filter_options, arg, &errbuf))
> +			die("%s", errbuf.buf);
>  		strbuf_addstr(&filter_options->filter_spec, arg);
> -
> -		parse_error = gently_parse_list_objects_filter(
> -			filter_options, arg, &errbuf);
>  	} else {
>  		struct list_objects_filter_options *sub;
>  
> @@ -271,18 +269,17 @@ void parse_list_objects_filter(
>  		 */
>  		transform_to_combine_type(filter_options);
>  
> -		strbuf_addch(&filter_options->filter_spec, '+');
> -		filter_spec_append_urlencode(filter_options, arg);
>  		ALLOC_GROW_BY(filter_options->sub, filter_options->sub_nr, 1,
>  			      filter_options->sub_alloc);
>  		sub = &filter_options->sub[filter_options->sub_nr - 1];
>  
>  		list_objects_filter_init(sub);
> -		parse_error = gently_parse_list_objects_filter(sub, arg,
> -							       &errbuf);
> +		if (gently_parse_list_objects_filter(sub, arg, &errbuf))
> +			die("%s", errbuf.buf);

Do we actually have a test hitting this code path? I wanted to figure
out why `filter_options->sub` wasn't leaky (I assume that's what you're
talking about in your commit message), but I wasn't able to reproduce a
scenario where we should die here.

--
Toon

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

* Re: [PATCH 00/21] Memory leak fixes (pt.9)
  2024-10-11  5:32 [PATCH 00/21] Memory leak fixes (pt.9) Patrick Steinhardt
                   ` (20 preceding siblings ...)
  2024-10-11  5:33 ` [PATCH 21/21] list-objects-filter-options: work around reported leak on error Patrick Steinhardt
@ 2024-10-18 21:30 ` Taylor Blau
  2024-10-21  8:45   ` Patrick Steinhardt
  2024-10-21  9:27 ` [PATCH v2 00/22] " Patrick Steinhardt
  2024-11-05  6:16 ` [PATCH v3 " Patrick Steinhardt
  23 siblings, 1 reply; 100+ messages in thread
From: Taylor Blau @ 2024-10-18 21:30 UTC (permalink / raw)
  To: Patrick Steinhardt; +Cc: git

On Fri, Oct 11, 2024 at 07:32:04AM +0200, Patrick Steinhardt wrote:
> Hi,
>
> here's another round of memory leak fixes. With this series we're down
> to 10 test suites which are failing with the leak sanitizer. There are
> two patch series in flight [1][2] that fix three more test suites, so in
> total we're down to 7 test suites that we'll still have to fix up. So:
> we're almost done!

I was just looking through Toon's responses lower down in the thread,
and realized that I never picked this one up.

I think that makes sense... since this came on 11 October, which is when
Junio signed off for vacation. I think that we each assumed that the
other would (or had) pick it up.

In any case, this is now in my tree as 'ps/leakfixes-part-9'. Sorry for
the wait.

Thanks,
Taylor

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

* Re: [PATCH 07/21] pretty: clear signature check
  2024-10-18 12:02   ` Toon Claes
@ 2024-10-21  8:44     ` Patrick Steinhardt
  0 siblings, 0 replies; 100+ messages in thread
From: Patrick Steinhardt @ 2024-10-21  8:44 UTC (permalink / raw)
  To: Toon Claes; +Cc: git

On Fri, Oct 18, 2024 at 02:02:48PM +0200, Toon Claes wrote:
> Patrick Steinhardt <ps@pks.im> writes:
> 
> > The signature check in of the formatting context is never getting
> > released. Fix this to plug the resulting memory leak.
> >
> > Signed-off-by: Patrick Steinhardt <ps@pks.im>
> > ---
> >  pretty.c                         | 1 +
> >  t/t4202-log.sh                   | 1 +
> >  t/t7031-verify-tag-signed-ssh.sh | 1 +
> >  t/t7510-signed-commit.sh         | 1 +
> >  t/t7528-signed-commit-ssh.sh     | 1 +
> >  5 files changed, 5 insertions(+)
> >
> > diff --git a/pretty.c b/pretty.c
> > index 6403e268900..098378720a4 100644
> > --- a/pretty.c
> > +++ b/pretty.c
> > @@ -2032,6 +2032,7 @@ void repo_format_commit_message(struct repository *r,
> >  
> >  	free(context.commit_encoding);
> >  	repo_unuse_commit_buffer(r, commit, context.message);
> > +	signature_check_clear(&context.signature_check);
> 
> I was having a very hard time finding where this gets allocated, and to
> be honest, I still don't know for sure. I think in
> check_commit_signature() which is called by format_commit_one().
> In "[PATCH 20/21] builtin/merge: release outbut buffer after performing
> merge" you mention it's not obvious to the caller they need know about
> memory they need to clean up, isn't that case here as well?

Well, I think it's clearer in this context, but hidden by the fact that
we pass around a wrapper-structure. But that's not really the problem of
the `struct signature_check` subsystem, but rather of "pretty.c".

In any case, the callchain is:

  - `format_commit_one()`
  - `check_commit_signature()`
  - `check_signature()`
  - `verify_signed_buffer()`, which is a function pointer depending on
    whether we verify a GPG, x509 or SSH signature.

From my point of view, that callchain isn't all that important in this
context. All we need to know is that we allocate the signature check
struct on our stack, and as it may get populated we have to clean it up,
as well.

Patrick

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

* Re: [PATCH 10/21] trailer: fix leaking trailer values
  2024-10-18 12:03   ` Toon Claes
@ 2024-10-21  8:44     ` Patrick Steinhardt
  0 siblings, 0 replies; 100+ messages in thread
From: Patrick Steinhardt @ 2024-10-21  8:44 UTC (permalink / raw)
  To: Toon Claes; +Cc: git

On Fri, Oct 18, 2024 at 02:03:26PM +0200, Toon Claes wrote:
> Patrick Steinhardt <ps@pks.im> writes:
> 
> > Fix leaking trailer values when replacing the value with a command or
> > when the token value is empty.
> >
> > Signed-off-by: Patrick Steinhardt <ps@pks.im>
> > ---
> >
> > diff --git a/trailer.c b/trailer.c
> > index 682d74505bf..5c0bfb735a9 100644
> > --- a/trailer.c
> > +++ b/trailer.c
> > @@ -1124,7 +1131,7 @@ void format_trailers(const struct process_trailer_options *opts,
> >  			 * corresponding value).
> >  			 */
> >  			if (opts->trim_empty && !strlen(item->value))
> > -				continue;
> > +				goto next;
> 
> While this is technically correct, I found it rather hard to understand
> what's happening. What do you think about instead turning the `if` below
> in an `else if` ?

An even better idea is to lift the buffers outside of the loop. Like this
we don't have to reallocate them on every iteration and can easily
release them once at the end of the function.

Patrick

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

* Re: [PATCH 20/21] builtin/merge: release outbut buffer after performing merge
  2024-10-18 12:03   ` Toon Claes
@ 2024-10-21  8:45     ` Patrick Steinhardt
  0 siblings, 0 replies; 100+ messages in thread
From: Patrick Steinhardt @ 2024-10-21  8:45 UTC (permalink / raw)
  To: Toon Claes; +Cc: git

On Fri, Oct 18, 2024 at 02:03:48PM +0200, Toon Claes wrote:
> Patrick Steinhardt <ps@pks.im> writes:
> 
> > The `obuf` member of `struct merge_options` is used to buffer output in
> > some cases. In order to not discard its allocated memory we only release
> > its contents in `merge_finalize()` when we're not currently recursing
> > into a subtree.
> >
> > This results in some situations where we seemingly do not release the
> > buffer reliably. We thus have calls to `strbuf_release()` for this
> > buffer scattered across the codebase. But we're missing one callsite in
> > git-merge(1), which causes a memory leak.
> >
> > We should ideally refactor this interface so that callers don't have to
> > know about any such internals. But for now, paper over the issue by
> > adding one more `strbuf_release()` call.
> 
> Shall we mark this as #leftoverbits?

I guess it is now marked as such :)

Patrick

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

* Re: [PATCH 21/21] list-objects-filter-options: work around reported leak on error
  2024-10-18 12:04   ` Toon Claes
@ 2024-10-21  8:45     ` Patrick Steinhardt
  0 siblings, 0 replies; 100+ messages in thread
From: Patrick Steinhardt @ 2024-10-21  8:45 UTC (permalink / raw)
  To: Toon Claes; +Cc: git

On Fri, Oct 18, 2024 at 02:04:18PM +0200, Toon Claes wrote:
> Patrick Steinhardt <ps@pks.im> writes:
> > diff --git a/list-objects-filter-options.c b/list-objects-filter-options.c
> > index 00611107d20..fa72e81e4ad 100644
> > --- a/list-objects-filter-options.c
> > +++ b/list-objects-filter-options.c
> > @@ -252,16 +252,14 @@ void parse_list_objects_filter(
> >  	const char *arg)
> >  {
> >  	struct strbuf errbuf = STRBUF_INIT;
> > -	int parse_error;
> >  
> >  	if (!filter_options->filter_spec.buf)
> >  		BUG("filter_options not properly initialized");
> >  
> >  	if (!filter_options->choice) {
> > +		if (gently_parse_list_objects_filter(filter_options, arg, &errbuf))
> > +			die("%s", errbuf.buf);
> >  		strbuf_addstr(&filter_options->filter_spec, arg);
> > -
> > -		parse_error = gently_parse_list_objects_filter(
> > -			filter_options, arg, &errbuf);
> >  	} else {
> >  		struct list_objects_filter_options *sub;
> >  
> > @@ -271,18 +269,17 @@ void parse_list_objects_filter(
> >  		 */
> >  		transform_to_combine_type(filter_options);
> >  
> > -		strbuf_addch(&filter_options->filter_spec, '+');
> > -		filter_spec_append_urlencode(filter_options, arg);
> >  		ALLOC_GROW_BY(filter_options->sub, filter_options->sub_nr, 1,
> >  			      filter_options->sub_alloc);
> >  		sub = &filter_options->sub[filter_options->sub_nr - 1];
> >  
> >  		list_objects_filter_init(sub);
> > -		parse_error = gently_parse_list_objects_filter(sub, arg,
> > -							       &errbuf);
> > +		if (gently_parse_list_objects_filter(sub, arg, &errbuf))
> > +			die("%s", errbuf.buf);
> 
> Do we actually have a test hitting this code path? I wanted to figure
> out why `filter_options->sub` wasn't leaky (I assume that's what you're
> talking about in your commit message), but I wasn't able to reproduce a
> scenario where we should die here.

You only refer to the second hunk, right? I couldn't find any code paths
hitting this, so this is more of a "Let's massage this code in the same
way" change. I don't want the next person to go through the same rabbit
hole as I had to go through :)

Patrick

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

* Re: [PATCH 00/21] Memory leak fixes (pt.9)
  2024-10-18 21:30 ` [PATCH 00/21] Memory leak fixes (pt.9) Taylor Blau
@ 2024-10-21  8:45   ` Patrick Steinhardt
  0 siblings, 0 replies; 100+ messages in thread
From: Patrick Steinhardt @ 2024-10-21  8:45 UTC (permalink / raw)
  To: Taylor Blau; +Cc: git

On Fri, Oct 18, 2024 at 05:30:36PM -0400, Taylor Blau wrote:
> On Fri, Oct 11, 2024 at 07:32:04AM +0200, Patrick Steinhardt wrote:
> > Hi,
> >
> > here's another round of memory leak fixes. With this series we're down
> > to 10 test suites which are failing with the leak sanitizer. There are
> > two patch series in flight [1][2] that fix three more test suites, so in
> > total we're down to 7 test suites that we'll still have to fix up. So:
> > we're almost done!
> 
> I was just looking through Toon's responses lower down in the thread,
> and realized that I never picked this one up.
> 
> I think that makes sense... since this came on 11 October, which is when
> Junio signed off for vacation. I think that we each assumed that the
> other would (or had) pick it up.
> 
> In any case, this is now in my tree as 'ps/leakfixes-part-9'. Sorry for
> the wait.

No worries, I'm happy that you keep things moving in the first place.
Thanks!

Patrick

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

* [PATCH v2 00/22] Memory leak fixes (pt.9)
  2024-10-11  5:32 [PATCH 00/21] Memory leak fixes (pt.9) Patrick Steinhardt
                   ` (21 preceding siblings ...)
  2024-10-18 21:30 ` [PATCH 00/21] Memory leak fixes (pt.9) Taylor Blau
@ 2024-10-21  9:27 ` Patrick Steinhardt
  2024-10-21  9:28   ` [PATCH v2 01/22] builtin/ls-remote: plug leaking server options Patrick Steinhardt
                     ` (23 more replies)
  2024-11-05  6:16 ` [PATCH v3 " Patrick Steinhardt
  23 siblings, 24 replies; 100+ messages in thread
From: Patrick Steinhardt @ 2024-10-21  9:27 UTC (permalink / raw)
  To: git; +Cc: Taylor Blau, Toon Claes

Hi,

this is the second version of my 9th series of memory leak fixes.

Changes compared to v1:

  - Split up the trailer fixes into two separate patches so that we can
    explain them standalone.

  - Adapt the second trailer memory leak fix to instead pull up the
    strbufs out of the loop such that we can reuse them. This makes the
    code flow more naturally and optimizes the loop.

Thanks!

Patrick

Patrick Steinhardt (22):
  builtin/ls-remote: plug leaking server options
  t/helper: fix leaks in "reach" test tool
  grep: fix leak in `grep_splice_or()`
  builtin/grep: fix leak with `--max-count=0`
  revision: fix leaking bloom filters
  diff-lib: fix leaking diffopts in `do_diff_cache()`
  pretty: clear signature check
  upload-pack: fix leaking URI protocols
  builtin/commit: fix leaking change data contents
  trailer: fix leaking trailer values
  trailer: fix leaking strbufs when formatting trailers
  builtin/commit: fix leaking cleanup config
  transport-helper: fix leaking import/export marks
  builtin/tag: fix leaking key ID on failure to sign
  combine-diff: fix leaking lost lines
  dir: release untracked cache data
  sparse-index: correctly free EWAH contents
  t/helper: stop re-initialization of `the_repository`
  t/helper: fix leaking buffer in "dump-untracked-cache"
  dir: fix leak when parsing "status.showUntrackedFiles"
  builtin/merge: release outbut buffer after performing merge
  list-objects-filter-options: work around reported leak on error

 builtin/commit.c                          | 26 +++++++++++++++++------
 builtin/grep.c                            | 13 +++++++++---
 builtin/ls-remote.c                       |  1 +
 builtin/merge.c                           |  1 +
 builtin/tag.c                             |  2 +-
 combine-diff.c                            |  2 +-
 diff-lib.c                                |  1 +
 dir.c                                     | 12 +++++++++--
 grep.c                                    |  1 +
 list-objects-filter-options.c             | 17 ++++++---------
 pretty.c                                  |  1 +
 revision.c                                |  5 +++++
 sparse-index.c                            |  7 ++++--
 t/helper/test-dump-untracked-cache.c      |  2 ++
 t/helper/test-reach.c                     | 10 +++++++++
 t/helper/test-read-cache.c                |  2 --
 t/t4038-diff-combined.sh                  |  1 +
 t/t4202-log.sh                            |  1 +
 t/t4216-log-bloom.sh                      |  1 +
 t/t5702-protocol-v2.sh                    |  1 +
 t/t5801-remote-helpers.sh                 |  1 +
 t/t6112-rev-list-filters-objects.sh       |  1 +
 t/t6424-merge-unrelated-index-changes.sh  |  1 +
 t/t6600-test-reach.sh                     |  1 +
 t/t7004-tag.sh                            |  1 +
 t/t7031-verify-tag-signed-ssh.sh          |  1 +
 t/t7063-status-untracked-cache.sh         |  1 +
 t/t7500-commit-template-squash-signoff.sh |  1 +
 t/t7502-commit-porcelain.sh               |  1 +
 t/t7510-signed-commit.sh                  |  1 +
 t/t7513-interpret-trailers.sh             |  1 +
 t/t7519-status-fsmonitor.sh               |  1 +
 t/t7528-signed-commit-ssh.sh              |  1 +
 t/t7610-mergetool.sh                      |  1 +
 t/t7810-grep.sh                           |  1 +
 trailer.c                                 | 25 +++++++++++++++-------
 transport-helper.c                        |  2 ++
 upload-pack.c                             |  1 +
 38 files changed, 115 insertions(+), 35 deletions(-)

Range-diff against v1:
 1:  89b66411354 =  1:  89b66411354 builtin/ls-remote: plug leaking server options
 2:  1c42e194b20 =  2:  1c42e194b20 t/helper: fix leaks in "reach" test tool
 3:  cb4eee37b40 =  3:  cb4eee37b40 grep: fix leak in `grep_splice_or()`
 4:  6b2c8842ef5 =  4:  6b2c8842ef5 builtin/grep: fix leak with `--max-count=0`
 5:  7527b31a28f =  5:  7527b31a28f revision: fix leaking bloom filters
 6:  60af98cb2c7 =  6:  60af98cb2c7 diff-lib: fix leaking diffopts in `do_diff_cache()`
 7:  5d5f6867f91 =  7:  5d5f6867f91 pretty: clear signature check
 8:  0d503e40194 =  8:  0d503e40194 upload-pack: fix leaking URI protocols
 9:  9f967dfe5d5 =  9:  9f967dfe5d5 builtin/commit: fix leaking change data contents
 -:  ----------- > 10:  e3ffd59123f trailer: fix leaking trailer values
10:  ca5370d572d ! 11:  5b851453bce trailer: fix leaking trailer values
    @@ Metadata
     Author: Patrick Steinhardt <ps@pks.im>
     
      ## Commit message ##
    -    trailer: fix leaking trailer values
    +    trailer: fix leaking strbufs when formatting trailers
     
    -    Fix leaking trailer values when replacing the value with a command or
    -    when the token value is empty.
    +    We are populating, but never releasing two string buffers in
    +    `format_trailers()`, causing a memory leak. Plug this leak by lifting
    +    those buffers outside of the loop and releasing them on function return.
    +    This fixes the memory leaks, but also optimizes the loop as we don't
    +    have to reallocate the buffers on every single iteration.
     
         Signed-off-by: Patrick Steinhardt <ps@pks.im>
     
    @@ t/t7513-interpret-trailers.sh
      # When we want one trailing space at the end of each line, let's use sed
     
      ## trailer.c ##
    -@@ trailer.c: static char *apply_command(struct conf_info *conf, const char *arg)
    - static void apply_item_command(struct trailer_item *in_tok, struct arg_item *arg_tok)
    +@@ trailer.c: void format_trailers(const struct process_trailer_options *opts,
    + 		     struct list_head *trailers,
    + 		     struct strbuf *out)
      {
    - 	if (arg_tok->conf.command || arg_tok->conf.cmd) {
    --		const char *arg;
    -+		char *value_to_free = NULL;
    -+		char *arg;
    -+
    - 		if (arg_tok->value && arg_tok->value[0]) {
    --			arg = arg_tok->value;
    -+			arg = (char *)arg_tok->value;
    - 		} else {
    - 			if (in_tok && in_tok->value)
    - 				arg = xstrdup(in_tok->value);
    - 			else
    - 				arg = xstrdup("");
    -+			value_to_free = arg_tok->value;
    - 		}
    -+
    - 		arg_tok->value = apply_command(&arg_tok->conf, arg);
    --		free((char *)arg);
    -+
    -+		free(value_to_free);
    -+		free(arg);
    - 	}
    - }
    ++	struct strbuf tok = STRBUF_INIT;
    ++	struct strbuf val = STRBUF_INIT;
    + 	size_t origlen = out->len;
    + 	struct list_head *pos;
    + 	struct trailer_item *item;
      
    -@@ trailer.c: void format_trailers(const struct process_trailer_options *opts,
    - 		if (item->token) {
    - 			struct strbuf tok = STRBUF_INIT;
    - 			struct strbuf val = STRBUF_INIT;
     +
    + 	list_for_each(pos, trailers) {
    + 		item = list_entry(pos, struct trailer_item, list);
    + 		if (item->token) {
    +-			struct strbuf tok = STRBUF_INIT;
    +-			struct strbuf val = STRBUF_INIT;
    ++			strbuf_reset(&tok);
      			strbuf_addstr(&tok, item->token);
    ++			strbuf_reset(&val);
      			strbuf_addstr(&val, item->value);
      
    -@@ trailer.c: void format_trailers(const struct process_trailer_options *opts,
    - 			 * corresponding value).
    - 			 */
    - 			if (opts->trim_empty && !strlen(item->value))
    --				continue;
    -+				goto next;
    - 
    - 			if (!opts->filter || opts->filter(&tok, opts->filter_data)) {
    - 				if (opts->separator && out->len != origlen)
    + 			/*
     @@ trailer.c: void format_trailers(const struct process_trailer_options *opts,
      				if (!opts->separator)
      					strbuf_addch(out, '\n');
      			}
    -+
    -+next:
    - 			strbuf_release(&tok);
    - 			strbuf_release(&val);
    +-			strbuf_release(&tok);
    +-			strbuf_release(&val);
     -
      		} else if (!opts->only_trailers) {
      			if (opts->separator && out->len != origlen) {
      				strbuf_addbuf(out, opts->separator);
    +@@ trailer.c: void format_trailers(const struct process_trailer_options *opts,
    + 				strbuf_addch(out, '\n');
    + 		}
    + 	}
    ++
    ++	strbuf_release(&tok);
    ++	strbuf_release(&val);
    + }
    + 
    + void format_trailers_from_commit(const struct process_trailer_options *opts,
11:  8ca4344ed86 = 12:  60c3f6146f3 builtin/commit: fix leaking cleanup config
12:  16d969ed7b1 = 13:  ea81cd8db86 transport-helper: fix leaking import/export marks
13:  9e4bc5bf73f = 14:  b700ab9079f builtin/tag: fix leaking key ID on failure to sign
14:  8d305d9b1c8 = 15:  76bbcb3fe30 combine-diff: fix leaking lost lines
15:  f977a033cf4 = 16:  d6b96a4012d dir: release untracked cache data
16:  170cc61edaa = 17:  3aa6bac5079 sparse-index: correctly free EWAH contents
17:  8e10ee844c6 = 18:  132fe750906 t/helper: stop re-initialization of `the_repository`
18:  71fd1c76b8a = 19:  b8b702eeb28 t/helper: fix leaking buffer in "dump-untracked-cache"
19:  8ccc246432d = 20:  ad309ac1b37 dir: fix leak when parsing "status.showUntrackedFiles"
20:  bc2206aa47e = 21:  5e243f9ee53 builtin/merge: release outbut buffer after performing merge
21:  6a2baf0d3e5 = 22:  b75376e3725 list-objects-filter-options: work around reported leak on error
-- 
2.47.0.72.gef8ce8f3d4.dirty


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

* [PATCH v2 01/22] builtin/ls-remote: plug leaking server options
  2024-10-21  9:27 ` [PATCH v2 00/22] " Patrick Steinhardt
@ 2024-10-21  9:28   ` Patrick Steinhardt
  2024-11-04 22:10     ` Justin Tobler
  2024-10-21  9:28   ` [PATCH v2 02/22] t/helper: fix leaks in "reach" test tool Patrick Steinhardt
                     ` (22 subsequent siblings)
  23 siblings, 1 reply; 100+ messages in thread
From: Patrick Steinhardt @ 2024-10-21  9:28 UTC (permalink / raw)
  To: git; +Cc: Taylor Blau, Toon Claes

The server options populated via `OPT_STRING_LIST()` is never cleared,
causing a memory leak. Plug it.

This leak is exposed by t5702, but plugging it alone does not make the
whole test suite pass.

Signed-off-by: Patrick Steinhardt <ps@pks.im>
---
 builtin/ls-remote.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/builtin/ls-remote.c b/builtin/ls-remote.c
index f723b3bf3bb..f333821b994 100644
--- a/builtin/ls-remote.c
+++ b/builtin/ls-remote.c
@@ -166,6 +166,7 @@ int cmd_ls_remote(int argc,
 		status = 0; /* we found something */
 	}
 
+	string_list_clear(&server_options, 0);
 	ref_sorting_release(sorting);
 	ref_array_clear(&ref_array);
 	if (transport_disconnect(transport))
-- 
2.47.0.72.gef8ce8f3d4.dirty


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

* [PATCH v2 02/22] t/helper: fix leaks in "reach" test tool
  2024-10-21  9:27 ` [PATCH v2 00/22] " Patrick Steinhardt
  2024-10-21  9:28   ` [PATCH v2 01/22] builtin/ls-remote: plug leaking server options Patrick Steinhardt
@ 2024-10-21  9:28   ` Patrick Steinhardt
  2024-10-21  9:28   ` [PATCH v2 03/22] grep: fix leak in `grep_splice_or()` Patrick Steinhardt
                     ` (21 subsequent siblings)
  23 siblings, 0 replies; 100+ messages in thread
From: Patrick Steinhardt @ 2024-10-21  9:28 UTC (permalink / raw)
  To: git; +Cc: Taylor Blau, Toon Claes

The "reach" test tool doesn't bother to clean up any of its allocated
resources, causing various leaks. Plug them.

Signed-off-by: Patrick Steinhardt <ps@pks.im>
---
 t/helper/test-reach.c | 10 ++++++++++
 t/t6600-test-reach.sh |  1 +
 2 files changed, 11 insertions(+)

diff --git a/t/helper/test-reach.c b/t/helper/test-reach.c
index 995e382863a..84deee604ad 100644
--- a/t/helper/test-reach.c
+++ b/t/helper/test-reach.c
@@ -127,10 +127,12 @@ int cmd__reach(int ac, const char **av)
 			exit(128);
 		printf("%s(A,X):\n", av[1]);
 		print_sorted_commit_ids(list);
+		free_commit_list(list);
 	} else if (!strcmp(av[1], "reduce_heads")) {
 		struct commit_list *list = reduce_heads(X);
 		printf("%s(X):\n", av[1]);
 		print_sorted_commit_ids(list);
+		free_commit_list(list);
 	} else if (!strcmp(av[1], "can_all_from_reach")) {
 		printf("%s(X,Y):%d\n", av[1], can_all_from_reach(X, Y, 1));
 	} else if (!strcmp(av[1], "can_all_from_reach_with_flag")) {
@@ -153,6 +155,7 @@ int cmd__reach(int ac, const char **av)
 			filter.with_commit_tag_algo = 0;
 
 		printf("%s(_,A,X,_):%d\n", av[1], commit_contains(&filter, A, X, &cache));
+		clear_contains_cache(&cache);
 	} else if (!strcmp(av[1], "get_reachable_subset")) {
 		const int reachable_flag = 1;
 		int i, count = 0;
@@ -176,7 +179,14 @@ int cmd__reach(int ac, const char **av)
 			die(_("too many commits marked reachable"));
 
 		print_sorted_commit_ids(list);
+		free_commit_list(list);
 	}
 
+	object_array_clear(&X_obj);
+	strbuf_release(&buf);
+	free_commit_list(X);
+	free_commit_list(Y);
+	free(X_array);
+	free(Y_array);
 	return 0;
 }
diff --git a/t/t6600-test-reach.sh b/t/t6600-test-reach.sh
index 2591f8b8b39..307deefed2c 100755
--- a/t/t6600-test-reach.sh
+++ b/t/t6600-test-reach.sh
@@ -2,6 +2,7 @@
 
 test_description='basic commit reachability tests'
 
+TEST_PASSES_SANITIZE_LEAK=true
 . ./test-lib.sh
 
 # Construct a grid-like commit graph with points (x,y)
-- 
2.47.0.72.gef8ce8f3d4.dirty


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

* [PATCH v2 03/22] grep: fix leak in `grep_splice_or()`
  2024-10-21  9:27 ` [PATCH v2 00/22] " Patrick Steinhardt
  2024-10-21  9:28   ` [PATCH v2 01/22] builtin/ls-remote: plug leaking server options Patrick Steinhardt
  2024-10-21  9:28   ` [PATCH v2 02/22] t/helper: fix leaks in "reach" test tool Patrick Steinhardt
@ 2024-10-21  9:28   ` Patrick Steinhardt
  2024-10-21  9:42     ` Kristoffer Haugsbakk
  2024-10-21  9:28   ` [PATCH v2 04/22] builtin/grep: fix leak with `--max-count=0` Patrick Steinhardt
                     ` (20 subsequent siblings)
  23 siblings, 1 reply; 100+ messages in thread
From: Patrick Steinhardt @ 2024-10-21  9:28 UTC (permalink / raw)
  To: git; +Cc: Taylor Blau, Toon Claes

In `grep_splice_or()` we search for the next `TRUE` node in our tree of
grep exrpessions and replace it with the given new expression. But we
don't free the old node, which causes a memory leak. Plug it.

This leak is exposed by t7810, but plugging it alone isn't sufficient to
make the test suite pass.

Signed-off-by: Patrick Steinhardt <ps@pks.im>
---
 grep.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/grep.c b/grep.c
index 701e58de04e..e9337f32cbf 100644
--- a/grep.c
+++ b/grep.c
@@ -756,6 +756,7 @@ static struct grep_expr *grep_splice_or(struct grep_expr *x, struct grep_expr *y
 		assert(x->node == GREP_NODE_OR);
 		if (x->u.binary.right &&
 		    x->u.binary.right->node == GREP_NODE_TRUE) {
+			free(x->u.binary.right);
 			x->u.binary.right = y;
 			break;
 		}
-- 
2.47.0.72.gef8ce8f3d4.dirty


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

* [PATCH v2 04/22] builtin/grep: fix leak with `--max-count=0`
  2024-10-21  9:27 ` [PATCH v2 00/22] " Patrick Steinhardt
                     ` (2 preceding siblings ...)
  2024-10-21  9:28   ` [PATCH v2 03/22] grep: fix leak in `grep_splice_or()` Patrick Steinhardt
@ 2024-10-21  9:28   ` Patrick Steinhardt
  2024-10-21  9:28   ` [PATCH v2 05/22] revision: fix leaking bloom filters Patrick Steinhardt
                     ` (19 subsequent siblings)
  23 siblings, 0 replies; 100+ messages in thread
From: Patrick Steinhardt @ 2024-10-21  9:28 UTC (permalink / raw)
  To: git; +Cc: Taylor Blau, Toon Claes

When executing with `--max-count=0` we'll return early from git-grep(1)
without performing any cleanup, which causes memory leaks. Plug these.

Signed-off-by: Patrick Steinhardt <ps@pks.im>
---
 builtin/grep.c  | 13 ++++++++++---
 t/t7810-grep.sh |  1 +
 2 files changed, 11 insertions(+), 3 deletions(-)

diff --git a/builtin/grep.c b/builtin/grep.c
index f17d46a06e4..98b85c7fcac 100644
--- a/builtin/grep.c
+++ b/builtin/grep.c
@@ -906,6 +906,7 @@ int cmd_grep(int argc,
 	int dummy;
 	int use_index = 1;
 	int allow_revs;
+	int ret;
 
 	struct option options[] = {
 		OPT_BOOL(0, "cached", &cached,
@@ -1172,8 +1173,10 @@ int cmd_grep(int argc,
 	 * Optimize out the case where the amount of matches is limited to zero.
 	 * We do this to keep results consistent with GNU grep(1).
 	 */
-	if (opt.max_count == 0)
-		return 1;
+	if (opt.max_count == 0) {
+		ret = 1;
+		goto out;
+	}
 
 	if (show_in_pager) {
 		if (num_threads > 1)
@@ -1267,10 +1270,14 @@ int cmd_grep(int argc,
 		hit |= wait_all();
 	if (hit && show_in_pager)
 		run_pager(&opt, prefix);
+
+	ret = !hit;
+
+out:
 	clear_pathspec(&pathspec);
 	string_list_clear(&path_list, 0);
 	free_grep_patterns(&opt);
 	object_array_clear(&list);
 	free_repos();
-	return !hit;
+	return ret;
 }
diff --git a/t/t7810-grep.sh b/t/t7810-grep.sh
index af2cf2f78ab..9e7681f0831 100755
--- a/t/t7810-grep.sh
+++ b/t/t7810-grep.sh
@@ -9,6 +9,7 @@ test_description='git grep various.
 GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
 export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
 
+TEST_PASSES_SANITIZE_LEAK=true
 . ./test-lib.sh
 
 test_invalid_grep_expression() {
-- 
2.47.0.72.gef8ce8f3d4.dirty


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

* [PATCH v2 05/22] revision: fix leaking bloom filters
  2024-10-21  9:27 ` [PATCH v2 00/22] " Patrick Steinhardt
                     ` (3 preceding siblings ...)
  2024-10-21  9:28   ` [PATCH v2 04/22] builtin/grep: fix leak with `--max-count=0` Patrick Steinhardt
@ 2024-10-21  9:28   ` Patrick Steinhardt
  2024-10-21  9:28   ` [PATCH v2 06/22] diff-lib: fix leaking diffopts in `do_diff_cache()` Patrick Steinhardt
                     ` (18 subsequent siblings)
  23 siblings, 0 replies; 100+ messages in thread
From: Patrick Steinhardt @ 2024-10-21  9:28 UTC (permalink / raw)
  To: git; +Cc: Taylor Blau, Toon Claes

The memory allocated by `prepare_to_use_bloom_filter()` is not released
by `release_revisions()`, causing a memory leak. Plug it.

Signed-off-by: Patrick Steinhardt <ps@pks.im>
---
 revision.c           | 5 +++++
 t/t4216-log-bloom.sh | 1 +
 2 files changed, 6 insertions(+)

diff --git a/revision.c b/revision.c
index f5f5b84f2b0..8df75b82249 100644
--- a/revision.c
+++ b/revision.c
@@ -3227,6 +3227,11 @@ void release_revisions(struct rev_info *revs)
 	clear_decoration(&revs->treesame, free);
 	line_log_free(revs);
 	oidset_clear(&revs->missing_commits);
+
+	for (int i = 0; i < revs->bloom_keys_nr; i++)
+		clear_bloom_key(&revs->bloom_keys[i]);
+	FREE_AND_NULL(revs->bloom_keys);
+	revs->bloom_keys_nr = 0;
 }
 
 static void add_child(struct rev_info *revs, struct commit *parent, struct commit *child)
diff --git a/t/t4216-log-bloom.sh b/t/t4216-log-bloom.sh
index 3f163dc3969..8d22338f6aa 100755
--- a/t/t4216-log-bloom.sh
+++ b/t/t4216-log-bloom.sh
@@ -4,6 +4,7 @@ test_description='git log for a path with Bloom filters'
 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-chunk.sh
 
-- 
2.47.0.72.gef8ce8f3d4.dirty


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

* [PATCH v2 06/22] diff-lib: fix leaking diffopts in `do_diff_cache()`
  2024-10-21  9:27 ` [PATCH v2 00/22] " Patrick Steinhardt
                     ` (4 preceding siblings ...)
  2024-10-21  9:28   ` [PATCH v2 05/22] revision: fix leaking bloom filters Patrick Steinhardt
@ 2024-10-21  9:28   ` Patrick Steinhardt
  2024-10-21  9:28   ` [PATCH v2 07/22] pretty: clear signature check Patrick Steinhardt
                     ` (17 subsequent siblings)
  23 siblings, 0 replies; 100+ messages in thread
From: Patrick Steinhardt @ 2024-10-21  9:28 UTC (permalink / raw)
  To: git; +Cc: Taylor Blau, Toon Claes

In `do_diff_cache()` we initialize a new `rev_info` and then overwrite
its `diffopt` with a user-provided set of options. This can leak memory
because `repo_init_revisions()` may end up allocating memory for the
`diffopt` itself depending on the configuration. And as that field is
overwritten we won't ever free that.

Plug the memory leak by releasing the diffopts before we overwrite them.

Signed-off-by: Patrick Steinhardt <ps@pks.im>
---
 diff-lib.c           | 1 +
 t/t7610-mergetool.sh | 1 +
 2 files changed, 2 insertions(+)

diff --git a/diff-lib.c b/diff-lib.c
index 6b14b959629..3cf353946f5 100644
--- a/diff-lib.c
+++ b/diff-lib.c
@@ -661,6 +661,7 @@ int do_diff_cache(const struct object_id *tree_oid, struct diff_options *opt)
 
 	repo_init_revisions(opt->repo, &revs, NULL);
 	copy_pathspec(&revs.prune_data, &opt->pathspec);
+	diff_free(&revs.diffopt);
 	revs.diffopt = *opt;
 	revs.diffopt.no_free = 1;
 
diff --git a/t/t7610-mergetool.sh b/t/t7610-mergetool.sh
index 22b3a85b3e9..5c5e79e9905 100755
--- a/t/t7610-mergetool.sh
+++ b/t/t7610-mergetool.sh
@@ -10,6 +10,7 @@ Testing basic merge tool invocation'
 GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
 export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
 
+TEST_PASSES_SANITIZE_LEAK=true
 . ./test-lib.sh
 
 # All the mergetool test work by checking out a temporary branch based
-- 
2.47.0.72.gef8ce8f3d4.dirty


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

* [PATCH v2 07/22] pretty: clear signature check
  2024-10-21  9:27 ` [PATCH v2 00/22] " Patrick Steinhardt
                     ` (5 preceding siblings ...)
  2024-10-21  9:28   ` [PATCH v2 06/22] diff-lib: fix leaking diffopts in `do_diff_cache()` Patrick Steinhardt
@ 2024-10-21  9:28   ` Patrick Steinhardt
  2024-11-04 22:15     ` Justin Tobler
  2024-10-21  9:28   ` [PATCH v2 08/22] upload-pack: fix leaking URI protocols Patrick Steinhardt
                     ` (16 subsequent siblings)
  23 siblings, 1 reply; 100+ messages in thread
From: Patrick Steinhardt @ 2024-10-21  9:28 UTC (permalink / raw)
  To: git; +Cc: Taylor Blau, Toon Claes

The signature check in of the formatting context is never getting
released. Fix this to plug the resulting memory leak.

Signed-off-by: Patrick Steinhardt <ps@pks.im>
---
 pretty.c                         | 1 +
 t/t4202-log.sh                   | 1 +
 t/t7031-verify-tag-signed-ssh.sh | 1 +
 t/t7510-signed-commit.sh         | 1 +
 t/t7528-signed-commit-ssh.sh     | 1 +
 5 files changed, 5 insertions(+)

diff --git a/pretty.c b/pretty.c
index 6403e268900..098378720a4 100644
--- a/pretty.c
+++ b/pretty.c
@@ -2032,6 +2032,7 @@ void repo_format_commit_message(struct repository *r,
 
 	free(context.commit_encoding);
 	repo_unuse_commit_buffer(r, commit, context.message);
+	signature_check_clear(&context.signature_check);
 }
 
 static void pp_header(struct pretty_print_context *pp,
diff --git a/t/t4202-log.sh b/t/t4202-log.sh
index 51f7beb59f8..35bec4089a3 100755
--- a/t/t4202-log.sh
+++ b/t/t4202-log.sh
@@ -5,6 +5,7 @@ test_description='git log'
 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"
 . "$TEST_DIRECTORY/lib-terminal.sh"
diff --git a/t/t7031-verify-tag-signed-ssh.sh b/t/t7031-verify-tag-signed-ssh.sh
index 20913b37134..2ee62c07293 100755
--- a/t/t7031-verify-tag-signed-ssh.sh
+++ b/t/t7031-verify-tag-signed-ssh.sh
@@ -4,6 +4,7 @@ test_description='signed tag 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/t7510-signed-commit.sh b/t/t7510-signed-commit.sh
index 0d2dd29fe6a..eb229082e40 100755
--- a/t/t7510-signed-commit.sh
+++ b/t/t7510-signed-commit.sh
@@ -4,6 +4,7 @@ test_description='signed commit tests'
 GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
 export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
 
+TEST_PASSES_SANITIZE_LEAK=true
 . ./test-lib.sh
 GNUPGHOME_NOT_USED=$GNUPGHOME
 . "$TEST_DIRECTORY/lib-gpg.sh"
diff --git a/t/t7528-signed-commit-ssh.sh b/t/t7528-signed-commit-ssh.sh
index 065f7806362..68e18856b66 100755
--- a/t/t7528-signed-commit-ssh.sh
+++ b/t/t7528-signed-commit-ssh.sh
@@ -4,6 +4,7 @@ test_description='ssh signed commit tests'
 GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
 export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
 
+TEST_PASSES_SANITIZE_LEAK=true
 . ./test-lib.sh
 GNUPGHOME_NOT_USED=$GNUPGHOME
 . "$TEST_DIRECTORY/lib-gpg.sh"
-- 
2.47.0.72.gef8ce8f3d4.dirty


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

* [PATCH v2 08/22] upload-pack: fix leaking URI protocols
  2024-10-21  9:27 ` [PATCH v2 00/22] " Patrick Steinhardt
                     ` (6 preceding siblings ...)
  2024-10-21  9:28   ` [PATCH v2 07/22] pretty: clear signature check Patrick Steinhardt
@ 2024-10-21  9:28   ` Patrick Steinhardt
  2024-10-21  9:28   ` [PATCH v2 09/22] builtin/commit: fix leaking change data contents Patrick Steinhardt
                     ` (15 subsequent siblings)
  23 siblings, 0 replies; 100+ messages in thread
From: Patrick Steinhardt @ 2024-10-21  9:28 UTC (permalink / raw)
  To: git; +Cc: Taylor Blau, Toon Claes

We don't clear `struct upload_pack::uri_protocols`, which causes a
memory leak. Fix this.

Signed-off-by: Patrick Steinhardt <ps@pks.im>
---
 t/t5702-protocol-v2.sh | 1 +
 upload-pack.c          | 1 +
 2 files changed, 2 insertions(+)

diff --git a/t/t5702-protocol-v2.sh b/t/t5702-protocol-v2.sh
index 1ef540f73d3..ed55a2f7f95 100755
--- a/t/t5702-protocol-v2.sh
+++ b/t/t5702-protocol-v2.sh
@@ -7,6 +7,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 protocol v2 with 'git://' transport
diff --git a/upload-pack.c b/upload-pack.c
index 6d6e0f9f980..b4a59c3518b 100644
--- a/upload-pack.c
+++ b/upload-pack.c
@@ -166,6 +166,7 @@ static void upload_pack_data_clear(struct upload_pack_data *data)
 	object_array_clear(&data->extra_edge_obj);
 	list_objects_filter_release(&data->filter_options);
 	string_list_clear(&data->allowed_filters, 0);
+	string_list_clear(&data->uri_protocols, 0);
 
 	free((char *)data->pack_objects_hook);
 }
-- 
2.47.0.72.gef8ce8f3d4.dirty


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

* [PATCH v2 09/22] builtin/commit: fix leaking change data contents
  2024-10-21  9:27 ` [PATCH v2 00/22] " Patrick Steinhardt
                     ` (7 preceding siblings ...)
  2024-10-21  9:28   ` [PATCH v2 08/22] upload-pack: fix leaking URI protocols Patrick Steinhardt
@ 2024-10-21  9:28   ` Patrick Steinhardt
  2024-11-04 22:21     ` Justin Tobler
  2024-10-21  9:28   ` [PATCH v2 10/22] trailer: fix leaking trailer values Patrick Steinhardt
                     ` (14 subsequent siblings)
  23 siblings, 1 reply; 100+ messages in thread
From: Patrick Steinhardt @ 2024-10-21  9:28 UTC (permalink / raw)
  To: git; +Cc: Taylor Blau, Toon Claes

While we free the worktree change data, we never free its contents. Fix
this.

Signed-off-by: Patrick Steinhardt <ps@pks.im>
---
 builtin/commit.c                          | 9 ++++++++-
 t/t7500-commit-template-squash-signoff.sh | 1 +
 2 files changed, 9 insertions(+), 1 deletion(-)

diff --git a/builtin/commit.c b/builtin/commit.c
index 8db4e9df0c9..18a55bd1b91 100644
--- a/builtin/commit.c
+++ b/builtin/commit.c
@@ -728,6 +728,13 @@ static void prepare_amend_commit(struct commit *commit, struct strbuf *sb,
 	repo_unuse_commit_buffer(the_repository, commit, buffer);
 }
 
+static void change_data_free(void *util, const char *str UNUSED)
+{
+	struct wt_status_change_data *d = util;
+	free(d->rename_source);
+	free(d);
+}
+
 static int prepare_to_commit(const char *index_file, const char *prefix,
 			     struct commit *current_head,
 			     struct wt_status *s,
@@ -991,7 +998,7 @@ static int prepare_to_commit(const char *index_file, const char *prefix,
 		s->use_color = 0;
 		committable = run_status(s->fp, index_file, prefix, 1, s);
 		s->use_color = saved_color_setting;
-		string_list_clear(&s->change, 1);
+		string_list_clear_func(&s->change, change_data_free);
 	} else {
 		struct object_id oid;
 		const char *parent = "HEAD";
diff --git a/t/t7500-commit-template-squash-signoff.sh b/t/t7500-commit-template-squash-signoff.sh
index 4dca8d97a77..379d3ed3413 100755
--- a/t/t7500-commit-template-squash-signoff.sh
+++ b/t/t7500-commit-template-squash-signoff.sh
@@ -7,6 +7,7 @@ test_description='git commit
 
 Tests for template, signoff, squash and -F functions.'
 
+TEST_PASSES_SANITIZE_LEAK=true
 . ./test-lib.sh
 
 . "$TEST_DIRECTORY"/lib-rebase.sh
-- 
2.47.0.72.gef8ce8f3d4.dirty


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

* [PATCH v2 10/22] trailer: fix leaking trailer values
  2024-10-21  9:27 ` [PATCH v2 00/22] " Patrick Steinhardt
                     ` (8 preceding siblings ...)
  2024-10-21  9:28   ` [PATCH v2 09/22] builtin/commit: fix leaking change data contents Patrick Steinhardt
@ 2024-10-21  9:28   ` Patrick Steinhardt
  2024-11-04 22:25     ` Justin Tobler
  2024-10-21  9:28   ` [PATCH v2 11/22] trailer: fix leaking strbufs when formatting trailers Patrick Steinhardt
                     ` (13 subsequent siblings)
  23 siblings, 1 reply; 100+ messages in thread
From: Patrick Steinhardt @ 2024-10-21  9:28 UTC (permalink / raw)
  To: git; +Cc: Taylor Blau, Toon Claes

Fix leaking trailer values when replacing the value with a command or
when the token value is empty.

This leak is exposed by t7513, but plugging it does not make the whole
test suite pass.

Signed-off-by: Patrick Steinhardt <ps@pks.im>
---
 trailer.c | 12 +++++++++---
 1 file changed, 9 insertions(+), 3 deletions(-)

diff --git a/trailer.c b/trailer.c
index 682d74505bf..f1eca6d5d15 100644
--- a/trailer.c
+++ b/trailer.c
@@ -249,17 +249,23 @@ static char *apply_command(struct conf_info *conf, const char *arg)
 static void apply_item_command(struct trailer_item *in_tok, struct arg_item *arg_tok)
 {
 	if (arg_tok->conf.command || arg_tok->conf.cmd) {
-		const char *arg;
+		char *value_to_free = NULL;
+		char *arg;
+
 		if (arg_tok->value && arg_tok->value[0]) {
-			arg = arg_tok->value;
+			arg = (char *)arg_tok->value;
 		} else {
 			if (in_tok && in_tok->value)
 				arg = xstrdup(in_tok->value);
 			else
 				arg = xstrdup("");
+			value_to_free = arg_tok->value;
 		}
+
 		arg_tok->value = apply_command(&arg_tok->conf, arg);
-		free((char *)arg);
+
+		free(value_to_free);
+		free(arg);
 	}
 }
 
-- 
2.47.0.72.gef8ce8f3d4.dirty


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

* [PATCH v2 11/22] trailer: fix leaking strbufs when formatting trailers
  2024-10-21  9:27 ` [PATCH v2 00/22] " Patrick Steinhardt
                     ` (9 preceding siblings ...)
  2024-10-21  9:28   ` [PATCH v2 10/22] trailer: fix leaking trailer values Patrick Steinhardt
@ 2024-10-21  9:28   ` Patrick Steinhardt
  2024-10-21 20:58     ` Taylor Blau
  2024-11-04 22:31     ` Justin Tobler
  2024-10-21  9:28   ` [PATCH v2 12/22] builtin/commit: fix leaking cleanup config Patrick Steinhardt
                     ` (12 subsequent siblings)
  23 siblings, 2 replies; 100+ messages in thread
From: Patrick Steinhardt @ 2024-10-21  9:28 UTC (permalink / raw)
  To: git; +Cc: Taylor Blau, Toon Claes

We are populating, but never releasing two string buffers in
`format_trailers()`, causing a memory leak. Plug this leak by lifting
those buffers outside of the loop and releasing them on function return.
This fixes the memory leaks, but also optimizes the loop as we don't
have to reallocate the buffers on every single iteration.

Signed-off-by: Patrick Steinhardt <ps@pks.im>
---
 t/t7513-interpret-trailers.sh |  1 +
 trailer.c                     | 13 ++++++++-----
 2 files changed, 9 insertions(+), 5 deletions(-)

diff --git a/t/t7513-interpret-trailers.sh b/t/t7513-interpret-trailers.sh
index 0f7d8938d98..38d6ccaa001 100755
--- a/t/t7513-interpret-trailers.sh
+++ b/t/t7513-interpret-trailers.sh
@@ -5,6 +5,7 @@
 
 test_description='git interpret-trailers'
 
+TEST_PASSES_SANITIZE_LEAK=true
 . ./test-lib.sh
 
 # When we want one trailing space at the end of each line, let's use sed
diff --git a/trailer.c b/trailer.c
index f1eca6d5d15..24e4e56fdf8 100644
--- a/trailer.c
+++ b/trailer.c
@@ -1111,16 +1111,19 @@ void format_trailers(const struct process_trailer_options *opts,
 		     struct list_head *trailers,
 		     struct strbuf *out)
 {
+	struct strbuf tok = STRBUF_INIT;
+	struct strbuf val = STRBUF_INIT;
 	size_t origlen = out->len;
 	struct list_head *pos;
 	struct trailer_item *item;
 
+
 	list_for_each(pos, trailers) {
 		item = list_entry(pos, struct trailer_item, list);
 		if (item->token) {
-			struct strbuf tok = STRBUF_INIT;
-			struct strbuf val = STRBUF_INIT;
+			strbuf_reset(&tok);
 			strbuf_addstr(&tok, item->token);
+			strbuf_reset(&val);
 			strbuf_addstr(&val, item->value);
 
 			/*
@@ -1151,9 +1154,6 @@ void format_trailers(const struct process_trailer_options *opts,
 				if (!opts->separator)
 					strbuf_addch(out, '\n');
 			}
-			strbuf_release(&tok);
-			strbuf_release(&val);
-
 		} else if (!opts->only_trailers) {
 			if (opts->separator && out->len != origlen) {
 				strbuf_addbuf(out, opts->separator);
@@ -1165,6 +1165,9 @@ void format_trailers(const struct process_trailer_options *opts,
 				strbuf_addch(out, '\n');
 		}
 	}
+
+	strbuf_release(&tok);
+	strbuf_release(&val);
 }
 
 void format_trailers_from_commit(const struct process_trailer_options *opts,
-- 
2.47.0.72.gef8ce8f3d4.dirty


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

* [PATCH v2 12/22] builtin/commit: fix leaking cleanup config
  2024-10-21  9:27 ` [PATCH v2 00/22] " Patrick Steinhardt
                     ` (10 preceding siblings ...)
  2024-10-21  9:28   ` [PATCH v2 11/22] trailer: fix leaking strbufs when formatting trailers Patrick Steinhardt
@ 2024-10-21  9:28   ` Patrick Steinhardt
  2024-10-21  9:28   ` [PATCH v2 13/22] transport-helper: fix leaking import/export marks Patrick Steinhardt
                     ` (11 subsequent siblings)
  23 siblings, 0 replies; 100+ messages in thread
From: Patrick Steinhardt @ 2024-10-21  9:28 UTC (permalink / raw)
  To: git; +Cc: Taylor Blau, Toon Claes

The cleanup string set by the config is leaking when it is being
overridden by an option. Fix this by tracking these via two separate
variables such that we can free the old value.

Signed-off-by: Patrick Steinhardt <ps@pks.im>
---
 builtin/commit.c            | 17 ++++++++++++-----
 t/t7502-commit-porcelain.sh |  1 +
 2 files changed, 13 insertions(+), 5 deletions(-)

diff --git a/builtin/commit.c b/builtin/commit.c
index 18a55bd1b91..71d674138c9 100644
--- a/builtin/commit.c
+++ b/builtin/commit.c
@@ -135,7 +135,7 @@ static struct strvec trailer_args = STRVEC_INIT;
  * is specified explicitly.
  */
 static enum commit_msg_cleanup_mode cleanup_mode;
-static char *cleanup_arg;
+static char *cleanup_config;
 
 static enum commit_whence whence;
 static int use_editor = 1, include_status = 1;
@@ -1387,8 +1387,6 @@ static int parse_and_validate_options(int argc, const char *argv[],
 	if (0 <= edit_flag)
 		use_editor = edit_flag;
 
-	cleanup_mode = get_cleanup_mode(cleanup_arg, use_editor);
-
 	handle_untracked_files_arg(s);
 
 	if (all && argc > 0)
@@ -1636,8 +1634,10 @@ static int git_commit_config(const char *k, const char *v,
 		include_status = git_config_bool(k, v);
 		return 0;
 	}
-	if (!strcmp(k, "commit.cleanup"))
-		return git_config_string(&cleanup_arg, k, v);
+	if (!strcmp(k, "commit.cleanup")) {
+		FREE_AND_NULL(cleanup_config);
+		return git_config_string(&cleanup_config, k, v);
+	}
 	if (!strcmp(k, "commit.gpgsign")) {
 		sign_commit = git_config_bool(k, v) ? "" : NULL;
 		return 0;
@@ -1658,6 +1658,7 @@ int cmd_commit(int argc,
 	       struct repository *repo UNUSED)
 {
 	static struct wt_status s;
+	static const char *cleanup_arg = NULL;
 	static struct option builtin_commit_options[] = {
 		OPT__QUIET(&quiet, N_("suppress summary after successful commit")),
 		OPT__VERBOSE(&verbose, N_("show diff in commit message template")),
@@ -1757,6 +1758,12 @@ int cmd_commit(int argc,
 	if (verbose == -1)
 		verbose = (config_commit_verbose < 0) ? 0 : config_commit_verbose;
 
+	if (cleanup_arg) {
+		free(cleanup_config);
+		cleanup_config = xstrdup(cleanup_arg);
+	}
+	cleanup_mode = get_cleanup_mode(cleanup_config, use_editor);
+
 	if (dry_run)
 		return dry_run_commit(argv, prefix, current_head, &s);
 	index_file = prepare_index(argv, prefix, current_head, 0);
diff --git a/t/t7502-commit-porcelain.sh b/t/t7502-commit-porcelain.sh
index b37e2018a74..84f1ff52b67 100755
--- a/t/t7502-commit-porcelain.sh
+++ b/t/t7502-commit-porcelain.sh
@@ -5,6 +5,7 @@ test_description='git commit porcelain-ish'
 GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
 export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
 
+TEST_PASSES_SANITIZE_LEAK=true
 . ./test-lib.sh
 
 commit_msg_is () {
-- 
2.47.0.72.gef8ce8f3d4.dirty


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

* [PATCH v2 13/22] transport-helper: fix leaking import/export marks
  2024-10-21  9:27 ` [PATCH v2 00/22] " Patrick Steinhardt
                     ` (11 preceding siblings ...)
  2024-10-21  9:28   ` [PATCH v2 12/22] builtin/commit: fix leaking cleanup config Patrick Steinhardt
@ 2024-10-21  9:28   ` Patrick Steinhardt
  2024-10-21  9:28   ` [PATCH v2 14/22] builtin/tag: fix leaking key ID on failure to sign Patrick Steinhardt
                     ` (10 subsequent siblings)
  23 siblings, 0 replies; 100+ messages in thread
From: Patrick Steinhardt @ 2024-10-21  9:28 UTC (permalink / raw)
  To: git; +Cc: Taylor Blau, Toon Claes

Fix leaking import and export marks for transport helpers.

Signed-off-by: Patrick Steinhardt <ps@pks.im>
---
 t/t5801-remote-helpers.sh | 1 +
 transport-helper.c        | 2 ++
 2 files changed, 3 insertions(+)

diff --git a/t/t5801-remote-helpers.sh b/t/t5801-remote-helpers.sh
index d21877150ed..d4882288a30 100755
--- a/t/t5801-remote-helpers.sh
+++ b/t/t5801-remote-helpers.sh
@@ -8,6 +8,7 @@ test_description='Test remote-helper import and export commands'
 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/transport-helper.c b/transport-helper.c
index 013ec79dc9c..bc27653cdee 100644
--- a/transport-helper.c
+++ b/transport-helper.c
@@ -399,6 +399,8 @@ static int release_helper(struct transport *transport)
 	int res = 0;
 	struct helper_data *data = transport->data;
 	refspec_clear(&data->rs);
+	free(data->import_marks);
+	free(data->export_marks);
 	res = disconnect_helper(transport);
 	free(transport->data);
 	return res;
-- 
2.47.0.72.gef8ce8f3d4.dirty


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

* [PATCH v2 14/22] builtin/tag: fix leaking key ID on failure to sign
  2024-10-21  9:27 ` [PATCH v2 00/22] " Patrick Steinhardt
                     ` (12 preceding siblings ...)
  2024-10-21  9:28   ` [PATCH v2 13/22] transport-helper: fix leaking import/export marks Patrick Steinhardt
@ 2024-10-21  9:28   ` Patrick Steinhardt
  2024-10-21  9:28   ` [PATCH v2 15/22] combine-diff: fix leaking lost lines Patrick Steinhardt
                     ` (9 subsequent siblings)
  23 siblings, 0 replies; 100+ messages in thread
From: Patrick Steinhardt @ 2024-10-21  9:28 UTC (permalink / raw)
  To: git; +Cc: Taylor Blau, Toon Claes

We do not free the key ID when signing a tag fails. Do so by using
the common exit path.

Signed-off-by: Patrick Steinhardt <ps@pks.im>
---
 builtin/tag.c  | 2 +-
 t/t7004-tag.sh | 1 +
 2 files changed, 2 insertions(+), 1 deletion(-)

diff --git a/builtin/tag.c b/builtin/tag.c
index 93d10d59157..c37c0a68fda 100644
--- a/builtin/tag.c
+++ b/builtin/tag.c
@@ -164,7 +164,7 @@ static int do_sign(struct strbuf *buffer, struct object_id **compat_oid,
 	int ret = -1;
 
 	if (sign_buffer(buffer, &sig, keyid))
-		return -1;
+		goto out;
 
 	if (compat) {
 		const struct git_hash_algo *algo = the_repository->hash_algo;
diff --git a/t/t7004-tag.sh b/t/t7004-tag.sh
index b1316e62f46..42b3327e69b 100755
--- a/t/t7004-tag.sh
+++ b/t/t7004-tag.sh
@@ -10,6 +10,7 @@ Tests for operations with tags.'
 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
 . "$TEST_DIRECTORY"/lib-terminal.sh
-- 
2.47.0.72.gef8ce8f3d4.dirty


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

* [PATCH v2 15/22] combine-diff: fix leaking lost lines
  2024-10-21  9:27 ` [PATCH v2 00/22] " Patrick Steinhardt
                     ` (13 preceding siblings ...)
  2024-10-21  9:28   ` [PATCH v2 14/22] builtin/tag: fix leaking key ID on failure to sign Patrick Steinhardt
@ 2024-10-21  9:28   ` Patrick Steinhardt
  2024-11-04 22:43     ` Justin Tobler
  2024-10-21  9:28   ` [PATCH v2 16/22] dir: release untracked cache data Patrick Steinhardt
                     ` (8 subsequent siblings)
  23 siblings, 1 reply; 100+ messages in thread
From: Patrick Steinhardt @ 2024-10-21  9:28 UTC (permalink / raw)
  To: git; +Cc: Taylor Blau, Toon Claes

The `cnt` variable tracks the number of lines in a patch diff. It can
happen though that there are no newlines, in which case we'd still end
up allocating our array of `sline`s. In fact, we always allocate it with
`cnt + 2` entries. But when we loop through the array to clear it at the
end of this function we only loop until `lno < cnt`, and thus we may not
end up releasing whatever the two extra `sline`s contain.

Plug this memory leak.

Signed-off-by: Patrick Steinhardt <ps@pks.im>
---
 combine-diff.c           | 2 +-
 t/t4038-diff-combined.sh | 1 +
 2 files changed, 2 insertions(+), 1 deletion(-)

diff --git a/combine-diff.c b/combine-diff.c
index f6b624dc288..3c6d9507fec 100644
--- a/combine-diff.c
+++ b/combine-diff.c
@@ -1220,7 +1220,7 @@ static void show_patch_diff(struct combine_diff_path *elem, int num_parent,
 	}
 	free(result);
 
-	for (lno = 0; lno < cnt; lno++) {
+	for (lno = 0; lno < cnt + 2; lno++) {
 		if (sline[lno].lost) {
 			struct lline *ll = sline[lno].lost;
 			while (ll) {
diff --git a/t/t4038-diff-combined.sh b/t/t4038-diff-combined.sh
index 2ce26e585c9..00190802d83 100755
--- a/t/t4038-diff-combined.sh
+++ b/t/t4038-diff-combined.sh
@@ -5,6 +5,7 @@ test_description='combined diff'
 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-diff.sh
 
-- 
2.47.0.72.gef8ce8f3d4.dirty


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

* [PATCH v2 16/22] dir: release untracked cache data
  2024-10-21  9:27 ` [PATCH v2 00/22] " Patrick Steinhardt
                     ` (14 preceding siblings ...)
  2024-10-21  9:28   ` [PATCH v2 15/22] combine-diff: fix leaking lost lines Patrick Steinhardt
@ 2024-10-21  9:28   ` Patrick Steinhardt
  2024-10-21  9:28   ` [PATCH v2 17/22] sparse-index: correctly free EWAH contents Patrick Steinhardt
                     ` (7 subsequent siblings)
  23 siblings, 0 replies; 100+ messages in thread
From: Patrick Steinhardt @ 2024-10-21  9:28 UTC (permalink / raw)
  To: git; +Cc: Taylor Blau, Toon Claes

There are several cases where we invalidate untracked cache directory
entries where we do not free the underlying data, but reset the number
of entries. This causes us to leak memory because `free_untracked()`
will not iterate over any potential entries which we still had in the
array.

Fix this issue by freeing old entries. The leak is exposed by t7519, but
plugging it alone does not make the whole test suite pass.

Signed-off-by: Patrick Steinhardt <ps@pks.im>
---
 dir.c | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/dir.c b/dir.c
index e3ddd5b5296..cb9782fa11f 100644
--- a/dir.c
+++ b/dir.c
@@ -1056,6 +1056,8 @@ static void do_invalidate_gitignore(struct untracked_cache_dir *dir)
 {
 	int i;
 	dir->valid = 0;
+	for (size_t i = 0; i < dir->untracked_nr; i++)
+		free(dir->untracked[i]);
 	dir->untracked_nr = 0;
 	for (i = 0; i < dir->dirs_nr; i++)
 		do_invalidate_gitignore(dir->dirs[i]);
@@ -1083,6 +1085,8 @@ static void invalidate_directory(struct untracked_cache *uc,
 		uc->dir_invalidated++;
 
 	dir->valid = 0;
+	for (size_t i = 0; i < dir->untracked_nr; i++)
+		free(dir->untracked[i]);
 	dir->untracked_nr = 0;
 	for (i = 0; i < dir->dirs_nr; i++)
 		dir->dirs[i]->recurse = 0;
@@ -3573,6 +3577,8 @@ static void write_one_dir(struct untracked_cache_dir *untracked,
 	 * for safety..
 	 */
 	if (!untracked->valid) {
+		for (size_t i = 0; i < untracked->untracked_nr; i++)
+			free(untracked->untracked[i]);
 		untracked->untracked_nr = 0;
 		untracked->check_only = 0;
 	}
@@ -3905,6 +3911,8 @@ static void invalidate_one_directory(struct untracked_cache *uc,
 {
 	uc->dir_invalidated++;
 	ucd->valid = 0;
+	for (size_t i = 0; i < ucd->untracked_nr; i++)
+		free(ucd->untracked[i]);
 	ucd->untracked_nr = 0;
 }
 
-- 
2.47.0.72.gef8ce8f3d4.dirty


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

* [PATCH v2 17/22] sparse-index: correctly free EWAH contents
  2024-10-21  9:27 ` [PATCH v2 00/22] " Patrick Steinhardt
                     ` (15 preceding siblings ...)
  2024-10-21  9:28   ` [PATCH v2 16/22] dir: release untracked cache data Patrick Steinhardt
@ 2024-10-21  9:28   ` Patrick Steinhardt
  2024-10-21  9:28   ` [PATCH v2 18/22] t/helper: stop re-initialization of `the_repository` Patrick Steinhardt
                     ` (6 subsequent siblings)
  23 siblings, 0 replies; 100+ messages in thread
From: Patrick Steinhardt @ 2024-10-21  9:28 UTC (permalink / raw)
  To: git; +Cc: Taylor Blau, Toon Claes

While we free the `fsmonitor_dirty` member of `struct index_state`, we
do not free the contents of that EWAH. Do so by using `ewah_free()`
instead of `FREE_AND_NULL()`.

This leak is exposed by t7519, but plugging it alone does not make the
test suite pass.

Signed-off-by: Patrick Steinhardt <ps@pks.im>
---
 sparse-index.c | 7 +++++--
 1 file changed, 5 insertions(+), 2 deletions(-)

diff --git a/sparse-index.c b/sparse-index.c
index 3d7f2164e25..2107840bfc5 100644
--- a/sparse-index.c
+++ b/sparse-index.c
@@ -2,6 +2,7 @@
 
 #include "git-compat-util.h"
 #include "environment.h"
+#include "ewah/ewok.h"
 #include "gettext.h"
 #include "name-hash.h"
 #include "read-cache-ll.h"
@@ -242,7 +243,8 @@ int convert_to_sparse(struct index_state *istate, int flags)
 	cache_tree_update(istate, 0);
 
 	istate->fsmonitor_has_run_once = 0;
-	FREE_AND_NULL(istate->fsmonitor_dirty);
+	ewah_free(istate->fsmonitor_dirty);
+	istate->fsmonitor_dirty = NULL;
 	FREE_AND_NULL(istate->fsmonitor_last_update);
 
 	istate->sparse_index = INDEX_COLLAPSED;
@@ -438,7 +440,8 @@ void expand_index(struct index_state *istate, struct pattern_list *pl)
 	istate->cache_nr = full->cache_nr;
 	istate->cache_alloc = full->cache_alloc;
 	istate->fsmonitor_has_run_once = 0;
-	FREE_AND_NULL(istate->fsmonitor_dirty);
+	ewah_free(istate->fsmonitor_dirty);
+	istate->fsmonitor_dirty = NULL;
 	FREE_AND_NULL(istate->fsmonitor_last_update);
 
 	strbuf_release(&base);
-- 
2.47.0.72.gef8ce8f3d4.dirty


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

* [PATCH v2 18/22] t/helper: stop re-initialization of `the_repository`
  2024-10-21  9:27 ` [PATCH v2 00/22] " Patrick Steinhardt
                     ` (16 preceding siblings ...)
  2024-10-21  9:28   ` [PATCH v2 17/22] sparse-index: correctly free EWAH contents Patrick Steinhardt
@ 2024-10-21  9:28   ` Patrick Steinhardt
  2024-10-21  9:28   ` [PATCH v2 19/22] t/helper: fix leaking buffer in "dump-untracked-cache" Patrick Steinhardt
                     ` (5 subsequent siblings)
  23 siblings, 0 replies; 100+ messages in thread
From: Patrick Steinhardt @ 2024-10-21  9:28 UTC (permalink / raw)
  To: git; +Cc: Taylor Blau, Toon Claes

While "common-main.c" already initializes `the_repository` for us, we do
so a second time in the "read-cache" test helper. This causes a memory
leak because the old repository's contents isn't released.

Stop calling `initialize_repository()` to plug this leak.

Signed-off-by: Patrick Steinhardt <ps@pks.im>
---
 t/helper/test-read-cache.c  | 2 --
 t/t7519-status-fsmonitor.sh | 1 +
 2 files changed, 1 insertion(+), 2 deletions(-)

diff --git a/t/helper/test-read-cache.c b/t/helper/test-read-cache.c
index d285c656bd3..e277dde8e71 100644
--- a/t/helper/test-read-cache.c
+++ b/t/helper/test-read-cache.c
@@ -11,8 +11,6 @@ int cmd__read_cache(int argc, const char **argv)
 	int i, cnt = 1;
 	const char *name = NULL;
 
-	initialize_repository(the_repository);
-
 	if (argc > 1 && skip_prefix(argv[1], "--print-and-refresh=", &name)) {
 		argc--;
 		argv++;
diff --git a/t/t7519-status-fsmonitor.sh b/t/t7519-status-fsmonitor.sh
index 7ee69ecdd4a..0f88a58a819 100755
--- a/t/t7519-status-fsmonitor.sh
+++ b/t/t7519-status-fsmonitor.sh
@@ -2,6 +2,7 @@
 
 test_description='git status with file system watcher'
 
+TEST_PASSES_SANITIZE_LEAK=true
 . ./test-lib.sh
 
 # Note, after "git reset --hard HEAD" no extensions exist other than 'TREE'
-- 
2.47.0.72.gef8ce8f3d4.dirty


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

* [PATCH v2 19/22] t/helper: fix leaking buffer in "dump-untracked-cache"
  2024-10-21  9:27 ` [PATCH v2 00/22] " Patrick Steinhardt
                     ` (17 preceding siblings ...)
  2024-10-21  9:28   ` [PATCH v2 18/22] t/helper: stop re-initialization of `the_repository` Patrick Steinhardt
@ 2024-10-21  9:28   ` Patrick Steinhardt
  2024-10-21  9:29   ` [PATCH v2 20/22] dir: fix leak when parsing "status.showUntrackedFiles" Patrick Steinhardt
                     ` (4 subsequent siblings)
  23 siblings, 0 replies; 100+ messages in thread
From: Patrick Steinhardt @ 2024-10-21  9:28 UTC (permalink / raw)
  To: git; +Cc: Taylor Blau, Toon Claes

We never release the local `struct strbuf base` buffer, thus leaking
memory. Fix this leak.

This leak is exposed by t7063, but plugging it alone does not make the
whole test suite pass.

Signed-off-by: Patrick Steinhardt <ps@pks.im>
---
 t/helper/test-dump-untracked-cache.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/t/helper/test-dump-untracked-cache.c b/t/helper/test-dump-untracked-cache.c
index 4f010d53249..b2e70837a90 100644
--- a/t/helper/test-dump-untracked-cache.c
+++ b/t/helper/test-dump-untracked-cache.c
@@ -68,5 +68,7 @@ int cmd__dump_untracked_cache(int ac UNUSED, const char **av UNUSED)
 	printf("flags %08x\n", uc->dir_flags);
 	if (uc->root)
 		dump(uc->root, &base);
+
+	strbuf_release(&base);
 	return 0;
 }
-- 
2.47.0.72.gef8ce8f3d4.dirty


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

* [PATCH v2 20/22] dir: fix leak when parsing "status.showUntrackedFiles"
  2024-10-21  9:27 ` [PATCH v2 00/22] " Patrick Steinhardt
                     ` (18 preceding siblings ...)
  2024-10-21  9:28   ` [PATCH v2 19/22] t/helper: fix leaking buffer in "dump-untracked-cache" Patrick Steinhardt
@ 2024-10-21  9:29   ` Patrick Steinhardt
  2024-10-21  9:29   ` [PATCH v2 21/22] builtin/merge: release outbut buffer after performing merge Patrick Steinhardt
                     ` (3 subsequent siblings)
  23 siblings, 0 replies; 100+ messages in thread
From: Patrick Steinhardt @ 2024-10-21  9:29 UTC (permalink / raw)
  To: git; +Cc: Taylor Blau, Toon Claes

We use `repo_config_get_string()` to read "status.showUntrackedFiles"
from the config subsystem. This function allocates the result, but we
never free the result after parsing it.

The value never leaves the scope of the calling function, so refactor it
to instead use `repo_config_get_string_tmp()`, which does not hand over
ownership to the caller.

Signed-off-by: Patrick Steinhardt <ps@pks.im>
---
 dir.c                             | 4 ++--
 t/t7063-status-untracked-cache.sh | 1 +
 2 files changed, 3 insertions(+), 2 deletions(-)

diff --git a/dir.c b/dir.c
index cb9782fa11f..7f35a3e3175 100644
--- a/dir.c
+++ b/dir.c
@@ -2872,14 +2872,14 @@ static void set_untracked_ident(struct untracked_cache *uc)
 static unsigned new_untracked_cache_flags(struct index_state *istate)
 {
 	struct repository *repo = istate->repo;
-	char *val;
+	const char *val;
 
 	/*
 	 * This logic is coordinated with the setting of these flags in
 	 * wt-status.c#wt_status_collect_untracked(), and the evaluation
 	 * of the config setting in commit.c#git_status_config()
 	 */
-	if (!repo_config_get_string(repo, "status.showuntrackedfiles", &val) &&
+	if (!repo_config_get_string_tmp(repo, "status.showuntrackedfiles", &val) &&
 	    !strcmp(val, "all"))
 		return 0;
 
diff --git a/t/t7063-status-untracked-cache.sh b/t/t7063-status-untracked-cache.sh
index 8929ef481f9..13fea7931cd 100755
--- a/t/t7063-status-untracked-cache.sh
+++ b/t/t7063-status-untracked-cache.sh
@@ -5,6 +5,7 @@ test_description='test untracked cache'
 GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
 export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
 
+TEST_PASSES_SANITIZE_LEAK=true
 . ./test-lib.sh
 
 # On some filesystems (e.g. FreeBSD's ext2 and ufs) directory mtime
-- 
2.47.0.72.gef8ce8f3d4.dirty


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

* [PATCH v2 21/22] builtin/merge: release outbut buffer after performing merge
  2024-10-21  9:27 ` [PATCH v2 00/22] " Patrick Steinhardt
                     ` (19 preceding siblings ...)
  2024-10-21  9:29   ` [PATCH v2 20/22] dir: fix leak when parsing "status.showUntrackedFiles" Patrick Steinhardt
@ 2024-10-21  9:29   ` Patrick Steinhardt
  2024-10-21  9:41     ` Kristoffer Haugsbakk
  2024-10-21  9:29   ` [PATCH v2 22/22] list-objects-filter-options: work around reported leak on error Patrick Steinhardt
                     ` (2 subsequent siblings)
  23 siblings, 1 reply; 100+ messages in thread
From: Patrick Steinhardt @ 2024-10-21  9:29 UTC (permalink / raw)
  To: git; +Cc: Taylor Blau, Toon Claes

The `obuf` member of `struct merge_options` is used to buffer output in
some cases. In order to not discard its allocated memory we only release
its contents in `merge_finalize()` when we're not currently recursing
into a subtree.

This results in some situations where we seemingly do not release the
buffer reliably. We thus have calls to `strbuf_release()` for this
buffer scattered across the codebase. But we're missing one callsite in
git-merge(1), which causes a memory leak.

We should ideally refactor this interface so that callers don't have to
know about any such internals. But for now, paper over the issue by
adding one more `strbuf_release()` call.

Signed-off-by: Patrick Steinhardt <ps@pks.im>
---
 builtin/merge.c                          | 1 +
 t/t6424-merge-unrelated-index-changes.sh | 1 +
 2 files changed, 2 insertions(+)

diff --git a/builtin/merge.c b/builtin/merge.c
index 84d0f3604bc..51038eaca84 100644
--- a/builtin/merge.c
+++ b/builtin/merge.c
@@ -754,6 +754,7 @@ static int try_merge_strategy(const char *strategy, struct commit_list *common,
 			clean = merge_recursive(&o, head, remoteheads->item,
 						reversed, &result);
 		free_commit_list(reversed);
+		strbuf_release(&o.obuf);
 
 		if (clean < 0) {
 			rollback_lock_file(&lock);
diff --git a/t/t6424-merge-unrelated-index-changes.sh b/t/t6424-merge-unrelated-index-changes.sh
index 7677c5f08d0..a7ea8acb845 100755
--- a/t/t6424-merge-unrelated-index-changes.sh
+++ b/t/t6424-merge-unrelated-index-changes.sh
@@ -2,6 +2,7 @@
 
 test_description="merges with unrelated index changes"
 
+TEST_PASSES_SANITIZE_LEAK=true
 . ./test-lib.sh
 
 # Testcase for some simple merges
-- 
2.47.0.72.gef8ce8f3d4.dirty


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

* [PATCH v2 22/22] list-objects-filter-options: work around reported leak on error
  2024-10-21  9:27 ` [PATCH v2 00/22] " Patrick Steinhardt
                     ` (20 preceding siblings ...)
  2024-10-21  9:29   ` [PATCH v2 21/22] builtin/merge: release outbut buffer after performing merge Patrick Steinhardt
@ 2024-10-21  9:29   ` Patrick Steinhardt
  2024-10-21  9:54   ` [PATCH v2 00/22] Memory leak fixes (pt.9) Kristoffer Haugsbakk
  2024-11-04 22:46   ` Justin Tobler
  23 siblings, 0 replies; 100+ messages in thread
From: Patrick Steinhardt @ 2024-10-21  9:29 UTC (permalink / raw)
  To: git; +Cc: Taylor Blau, Toon Claes

This one is a little bit more curious. In t6112, we have a test that
exercises the `git rev-list --filter` option with invalid filters. We
execute git-rev-list(1) via `test_must_fail`, which means that we check
for leaks even though Git exits with an error code. This causes the
following leak:

    Direct leak of 27 byte(s) in 1 object(s) allocated from:
        #0 0x5555555e6946 in realloc.part.0 lsan_interceptors.cpp.o
        #1 0x5555558fb4b6 in xrealloc wrapper.c:137:8
        #2 0x5555558b6e06 in strbuf_grow strbuf.c:112:2
        #3 0x5555558b7550 in strbuf_add strbuf.c:311:2
        #4 0x5555557c1a88 in strbuf_addstr strbuf.h:310:2
        #5 0x5555557c1d4c in parse_list_objects_filter list-objects-filter-options.c:261:3
        #6 0x555555885ead in handle_revision_pseudo_opt revision.c:2899:3
        #7 0x555555884e20 in setup_revisions revision.c:3014:11
        #8 0x5555556c4b42 in cmd_rev_list builtin/rev-list.c:588:9
        #9 0x5555555ec5e3 in run_builtin git.c:483:11
        #10 0x5555555eb1e4 in handle_builtin git.c:749:13
        #11 0x5555555ec001 in run_argv git.c:819:4
        #12 0x5555555eaf94 in cmd_main git.c:954:19
        #13 0x5555556fd569 in main common-main.c:64:11
        #14 0x7ffff7ca714d in __libc_start_call_main (.../lib/libc.so.6+0x2a14d)
        #15 0x7ffff7ca7208 in __libc_start_main@GLIBC_2.2.5 (.../libc.so.6+0x2a208)
        #16 0x5555555ad064 in _start (git+0x59064)

This leak is valid, as we call `die()` and do not clean up the memory at
all. But what's curious is that this is the only leak reported, because
we don't clean up any other allocated memory, either, and I have no idea
why the leak sanitizer treats this buffer specially.

In any case, we can work around the leak by shuffling things around a
bit. Instead of calling `gently_parse_list_objects_filter()` and dying
after we have modified the filter spec, we simply do so beforehand. Like
this we don't allocate the buffer in the error case, which makes the
reported leak go away.

It's not pretty, but it manages to make t6112 leak free.

Signed-off-by: Patrick Steinhardt <ps@pks.im>
---
 list-objects-filter-options.c       | 17 +++++++----------
 t/t6112-rev-list-filters-objects.sh |  1 +
 2 files changed, 8 insertions(+), 10 deletions(-)

diff --git a/list-objects-filter-options.c b/list-objects-filter-options.c
index 00611107d20..fa72e81e4ad 100644
--- a/list-objects-filter-options.c
+++ b/list-objects-filter-options.c
@@ -252,16 +252,14 @@ void parse_list_objects_filter(
 	const char *arg)
 {
 	struct strbuf errbuf = STRBUF_INIT;
-	int parse_error;
 
 	if (!filter_options->filter_spec.buf)
 		BUG("filter_options not properly initialized");
 
 	if (!filter_options->choice) {
+		if (gently_parse_list_objects_filter(filter_options, arg, &errbuf))
+			die("%s", errbuf.buf);
 		strbuf_addstr(&filter_options->filter_spec, arg);
-
-		parse_error = gently_parse_list_objects_filter(
-			filter_options, arg, &errbuf);
 	} else {
 		struct list_objects_filter_options *sub;
 
@@ -271,18 +269,17 @@ void parse_list_objects_filter(
 		 */
 		transform_to_combine_type(filter_options);
 
-		strbuf_addch(&filter_options->filter_spec, '+');
-		filter_spec_append_urlencode(filter_options, arg);
 		ALLOC_GROW_BY(filter_options->sub, filter_options->sub_nr, 1,
 			      filter_options->sub_alloc);
 		sub = &filter_options->sub[filter_options->sub_nr - 1];
 
 		list_objects_filter_init(sub);
-		parse_error = gently_parse_list_objects_filter(sub, arg,
-							       &errbuf);
+		if (gently_parse_list_objects_filter(sub, arg, &errbuf))
+			die("%s", errbuf.buf);
+
+		strbuf_addch(&filter_options->filter_spec, '+');
+		filter_spec_append_urlencode(filter_options, arg);
 	}
-	if (parse_error)
-		die("%s", errbuf.buf);
 }
 
 int opt_parse_list_objects_filter(const struct option *opt,
diff --git a/t/t6112-rev-list-filters-objects.sh b/t/t6112-rev-list-filters-objects.sh
index 0387f35a326..71e38491fa8 100755
--- a/t/t6112-rev-list-filters-objects.sh
+++ b/t/t6112-rev-list-filters-objects.sh
@@ -5,6 +5,7 @@ test_description='git rev-list 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 the blob:none filter.
-- 
2.47.0.72.gef8ce8f3d4.dirty


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

* Re: [PATCH v2 21/22] builtin/merge: release outbut buffer after performing merge
  2024-10-21  9:29   ` [PATCH v2 21/22] builtin/merge: release outbut buffer after performing merge Patrick Steinhardt
@ 2024-10-21  9:41     ` Kristoffer Haugsbakk
  0 siblings, 0 replies; 100+ messages in thread
From: Kristoffer Haugsbakk @ 2024-10-21  9:41 UTC (permalink / raw)
  To: Patrick Steinhardt, git; +Cc: Taylor Blau, Toon Claes

> Re: [PATCH v2 21/22] builtin/merge: release outbut buffer after performing merge

s/outbut/output/

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

* Re: [PATCH v2 03/22] grep: fix leak in `grep_splice_or()`
  2024-10-21  9:28   ` [PATCH v2 03/22] grep: fix leak in `grep_splice_or()` Patrick Steinhardt
@ 2024-10-21  9:42     ` Kristoffer Haugsbakk
  0 siblings, 0 replies; 100+ messages in thread
From: Kristoffer Haugsbakk @ 2024-10-21  9:42 UTC (permalink / raw)
  To: Patrick Steinhardt, git; +Cc: Taylor Blau, Toon Claes

On Mon, Oct 21, 2024, at 11:28, Patrick Steinhardt wrote:
> In `grep_splice_or()` we search for the next `TRUE` node in our tree of
> grep exrpessions and replace it with the given new expression. But we

s/exrpessions/expressions/

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

* Re: [PATCH 06/21] diff-lib: fix leaking diffopts in `do_diff_cache()`
  2024-10-11  5:32 ` [PATCH 06/21] diff-lib: fix leaking diffopts in `do_diff_cache()` Patrick Steinhardt
@ 2024-10-21  9:46   ` Kristoffer Haugsbakk
  0 siblings, 0 replies; 100+ messages in thread
From: Kristoffer Haugsbakk @ 2024-10-21  9:46 UTC (permalink / raw)
  To: Patrick Steinhardt, git

On Fri, Oct 11, 2024, at 07:32, Patrick Steinhardt wrote:
> In `do_diff_cache()` we initialize a new `rev_info` and then overwrite
> its `diffopt` with a user-provided set of options. This can leak memory
> because `repo_init_revisions()` may end up allocating memory for the
> `diffopt` itself depending on the configuration. And as that field is

s/as that/since that/

“since” communicates causality better.

> overwritten we won't ever free that.

s/free that/free it/

-- 
Kristoffer Haugsbakk

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

* Re: [PATCH v2 00/22] Memory leak fixes (pt.9)
  2024-10-21  9:27 ` [PATCH v2 00/22] " Patrick Steinhardt
                     ` (21 preceding siblings ...)
  2024-10-21  9:29   ` [PATCH v2 22/22] list-objects-filter-options: work around reported leak on error Patrick Steinhardt
@ 2024-10-21  9:54   ` Kristoffer Haugsbakk
  2024-10-21 10:36     ` Patrick Steinhardt
  2024-11-04 22:46   ` Justin Tobler
  23 siblings, 1 reply; 100+ messages in thread
From: Kristoffer Haugsbakk @ 2024-10-21  9:54 UTC (permalink / raw)
  To: Patrick Steinhardt, git; +Cc: Taylor Blau, Toon Claes

On Mon, Oct 21, 2024, at 11:27, Patrick Steinhardt wrote:
> Hi,
>
> this is the second version of my 9th series of memory leak fixes.

I can’t even imagine the amount of effort it takes to plug all these
leaks in parallel with the stuff that everyone else is doing in the
code.  Nice work.  :)

Of course all the comments that I left just now are nitpicks.

-- 
Kristoffer Haugsbakk

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

* Re: [PATCH v2 00/22] Memory leak fixes (pt.9)
  2024-10-21  9:54   ` [PATCH v2 00/22] Memory leak fixes (pt.9) Kristoffer Haugsbakk
@ 2024-10-21 10:36     ` Patrick Steinhardt
  2024-10-25  7:49       ` Toon Claes
  0 siblings, 1 reply; 100+ messages in thread
From: Patrick Steinhardt @ 2024-10-21 10:36 UTC (permalink / raw)
  To: Kristoffer Haugsbakk; +Cc: git, Taylor Blau, Toon Claes

On Mon, Oct 21, 2024 at 11:54:52AM +0200, Kristoffer Haugsbakk wrote:
> On Mon, Oct 21, 2024, at 11:27, Patrick Steinhardt wrote:
> > Hi,
> >
> > this is the second version of my 9th series of memory leak fixes.
> 
> I can’t even imagine the amount of effort it takes to plug all these
> leaks in parallel with the stuff that everyone else is doing in the
> code.  Nice work.  :)
> 
> Of course all the comments that I left just now are nitpicks.

Thanks! I've queued all fixes locally, but will wait a bit before
sending them out so that other reviewers have a chance to chime in
first.

Patrick

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

* Re: [PATCH v2 11/22] trailer: fix leaking strbufs when formatting trailers
  2024-10-21  9:28   ` [PATCH v2 11/22] trailer: fix leaking strbufs when formatting trailers Patrick Steinhardt
@ 2024-10-21 20:58     ` Taylor Blau
  2024-11-04 22:31     ` Justin Tobler
  1 sibling, 0 replies; 100+ messages in thread
From: Taylor Blau @ 2024-10-21 20:58 UTC (permalink / raw)
  To: Patrick Steinhardt; +Cc: git, Toon Claes

On Mon, Oct 21, 2024 at 11:28:35AM +0200, Patrick Steinhardt wrote:
> We are populating, but never releasing two string buffers in
> `format_trailers()`, causing a memory leak. Plug this leak by lifting
> those buffers outside of the loop and releasing them on function return.
> This fixes the memory leaks, but also optimizes the loop as we don't
> have to reallocate the buffers on every single iteration.
>
> Signed-off-by: Patrick Steinhardt <ps@pks.im>
> ---
>  t/t7513-interpret-trailers.sh |  1 +
>  trailer.c                     | 13 ++++++++-----
>  2 files changed, 9 insertions(+), 5 deletions(-)
>
> diff --git a/t/t7513-interpret-trailers.sh b/t/t7513-interpret-trailers.sh
> index 0f7d8938d98..38d6ccaa001 100755
> --- a/t/t7513-interpret-trailers.sh
> +++ b/t/t7513-interpret-trailers.sh
> @@ -5,6 +5,7 @@
>
>  test_description='git interpret-trailers'
>
> +TEST_PASSES_SANITIZE_LEAK=true
>  . ./test-lib.sh
>
>  # When we want one trailing space at the end of each line, let's use sed
> diff --git a/trailer.c b/trailer.c
> index f1eca6d5d15..24e4e56fdf8 100644
> --- a/trailer.c
> +++ b/trailer.c
> @@ -1111,16 +1111,19 @@ void format_trailers(const struct process_trailer_options *opts,
>  		     struct list_head *trailers,
>  		     struct strbuf *out)
>  {
> +	struct strbuf tok = STRBUF_INIT;
> +	struct strbuf val = STRBUF_INIT;
>  	size_t origlen = out->len;
>  	struct list_head *pos;
>  	struct trailer_item *item;
>
> +
>  	list_for_each(pos, trailers) {
>  		item = list_entry(pos, struct trailer_item, list);
>  		if (item->token) {
> -			struct strbuf tok = STRBUF_INIT;
> -			struct strbuf val = STRBUF_INIT;
> +			strbuf_reset(&tok);
>  			strbuf_addstr(&tok, item->token);
> +			strbuf_reset(&val);
>  			strbuf_addstr(&val, item->value);

I have a vague preference towards writing this as:

        strbuf_reset(&tok);
        strbuf_reset(&val);
        strbuf_addstr(&tok, item->token);
        strbuf_addstr(&val, item->value);

to make clear(er) to the reader that, OK, we are resetting both of these
buffers before using them at the beginning of the loop. To me it reads a
little clearer seeing both strbuf_reset() calls one right after the
other.

I don't feel all that strongly about it, but I also see that you have a
couple of small changes you're sitting on from Kristoffer's review, so I
figured I'd throw it out there anyway as we are expecting a new round to
address those.

Thanks,
Taylor

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

* Re: [PATCH v2 00/22] Memory leak fixes (pt.9)
  2024-10-21 10:36     ` Patrick Steinhardt
@ 2024-10-25  7:49       ` Toon Claes
  0 siblings, 0 replies; 100+ messages in thread
From: Toon Claes @ 2024-10-25  7:49 UTC (permalink / raw)
  To: Patrick Steinhardt, Kristoffer Haugsbakk; +Cc: git, Taylor Blau

Patrick Steinhardt <ps@pks.im> writes:

> Thanks! I've queued all fixes locally, but will wait a bit before
> sending them out so that other reviewers have a chance to chime in
> first.

I've got nothing more to add.

--
Toon

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

* Re: [PATCH v2 01/22] builtin/ls-remote: plug leaking server options
  2024-10-21  9:28   ` [PATCH v2 01/22] builtin/ls-remote: plug leaking server options Patrick Steinhardt
@ 2024-11-04 22:10     ` Justin Tobler
  2024-11-04 22:18       ` Kristoffer Haugsbakk
  0 siblings, 1 reply; 100+ messages in thread
From: Justin Tobler @ 2024-11-04 22:10 UTC (permalink / raw)
  To: Patrick Steinhardt; +Cc: git, Taylor Blau, Toon Claes

On 24/10/21 11:28AM, Patrick Steinhardt wrote:
> The server options populated via `OPT_STRING_LIST()` is never cleared,

s/is/are/

> causing a memory leak. Plug it.
> 
> This leak is exposed by t5702, but plugging it alone does not make the
> whole test suite pass.
> 
> Signed-off-by: Patrick Steinhardt <ps@pks.im>

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

* Re: [PATCH v2 07/22] pretty: clear signature check
  2024-10-21  9:28   ` [PATCH v2 07/22] pretty: clear signature check Patrick Steinhardt
@ 2024-11-04 22:15     ` Justin Tobler
  0 siblings, 0 replies; 100+ messages in thread
From: Justin Tobler @ 2024-11-04 22:15 UTC (permalink / raw)
  To: Patrick Steinhardt; +Cc: git, Taylor Blau, Toon Claes

On 24/10/21 11:28AM, Patrick Steinhardt wrote:
> The signature check in of the formatting context is never getting

s/in of/in/

> released. Fix this to plug the resulting memory leak.
> 
> Signed-off-by: Patrick Steinhardt <ps@pks.im>
> ---
>  pretty.c                         | 1 +
>  t/t4202-log.sh                   | 1 +
>  t/t7031-verify-tag-signed-ssh.sh | 1 +
>  t/t7510-signed-commit.sh         | 1 +
>  t/t7528-signed-commit-ssh.sh     | 1 +
>  5 files changed, 5 insertions(+)
> 
> diff --git a/pretty.c b/pretty.c
> index 6403e268900..098378720a4 100644
> --- a/pretty.c
> +++ b/pretty.c
> @@ -2032,6 +2032,7 @@ void repo_format_commit_message(struct repository *r,
>  
>  	free(context.commit_encoding);
>  	repo_unuse_commit_buffer(r, commit, context.message);
> +	signature_check_clear(&context.signature_check);

Initially I was thinking it might be nice to see the
`format_commit_context` cleanup extracted to its own function, but being
that it only has a single use internal to "pretty.c" it probably isn't
worth it.

>  }
>  
>  static void pp_header(struct pretty_print_context *pp,

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

* Re: [PATCH v2 01/22] builtin/ls-remote: plug leaking server options
  2024-11-04 22:10     ` Justin Tobler
@ 2024-11-04 22:18       ` Kristoffer Haugsbakk
  0 siblings, 0 replies; 100+ messages in thread
From: Kristoffer Haugsbakk @ 2024-11-04 22:18 UTC (permalink / raw)
  To: Justin Tobler, Patrick Steinhardt; +Cc: git, Taylor Blau, Toon Claes

On Mon, Nov 4, 2024, at 23:10, Justin Tobler wrote:
> On 24/10/21 11:28AM, Patrick Steinhardt wrote:
>> The server options populated via `OPT_STRING_LIST()` is never cleared,
>
> s/is/are/

I guess “is” was chosen because “the list is”.

   The [list] populated via `OPT_STRING_LIST()` is never cleared,

-- 
Kristoffer Haugsbakk

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

* Re: [PATCH v2 09/22] builtin/commit: fix leaking change data contents
  2024-10-21  9:28   ` [PATCH v2 09/22] builtin/commit: fix leaking change data contents Patrick Steinhardt
@ 2024-11-04 22:21     ` Justin Tobler
  0 siblings, 0 replies; 100+ messages in thread
From: Justin Tobler @ 2024-11-04 22:21 UTC (permalink / raw)
  To: Patrick Steinhardt; +Cc: git, Taylor Blau, Toon Claes

On 24/10/21 11:28AM, Patrick Steinhardt wrote:
> While we free the worktree change data, we never free its contents. Fix
> this.

Ah, so this worktree change data was part of the string list and was
being freed, but it also had memory allocations itself that were not.
Makes sense :)

> 
> Signed-off-by: Patrick Steinhardt <ps@pks.im>
> ---
>  builtin/commit.c                          | 9 ++++++++-
>  t/t7500-commit-template-squash-signoff.sh | 1 +
>  2 files changed, 9 insertions(+), 1 deletion(-)
> 
> diff --git a/builtin/commit.c b/builtin/commit.c
> index 8db4e9df0c9..18a55bd1b91 100644
> --- a/builtin/commit.c
> +++ b/builtin/commit.c
> @@ -728,6 +728,13 @@ static void prepare_amend_commit(struct commit *commit, struct strbuf *sb,
>  	repo_unuse_commit_buffer(the_repository, commit, buffer);
>  }
>  
> +static void change_data_free(void *util, const char *str UNUSED)
> +{
> +	struct wt_status_change_data *d = util;
> +	free(d->rename_source);
> +	free(d);
> +}
> +
>  static int prepare_to_commit(const char *index_file, const char *prefix,
>  			     struct commit *current_head,
>  			     struct wt_status *s,
> @@ -991,7 +998,7 @@ static int prepare_to_commit(const char *index_file, const char *prefix,
>  		s->use_color = 0;
>  		committable = run_status(s->fp, index_file, prefix, 1, s);
>  		s->use_color = saved_color_setting;
> -		string_list_clear(&s->change, 1);
> +		string_list_clear_func(&s->change, change_data_free);
>  	} else {
>  		struct object_id oid;
>  		const char *parent = "HEAD";
> diff --git a/t/t7500-commit-template-squash-signoff.sh b/t/t7500-commit-template-squash-signoff.sh
> index 4dca8d97a77..379d3ed3413 100755
> --- a/t/t7500-commit-template-squash-signoff.sh
> +++ b/t/t7500-commit-template-squash-signoff.sh
> @@ -7,6 +7,7 @@ test_description='git commit
>  
>  Tests for template, signoff, squash and -F functions.'
>  
> +TEST_PASSES_SANITIZE_LEAK=true
>  . ./test-lib.sh
>  
>  . "$TEST_DIRECTORY"/lib-rebase.sh
> -- 
> 2.47.0.72.gef8ce8f3d4.dirty
> 
> 

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

* Re: [PATCH v2 10/22] trailer: fix leaking trailer values
  2024-10-21  9:28   ` [PATCH v2 10/22] trailer: fix leaking trailer values Patrick Steinhardt
@ 2024-11-04 22:25     ` Justin Tobler
  2024-11-05  5:54       ` Patrick Steinhardt
  0 siblings, 1 reply; 100+ messages in thread
From: Justin Tobler @ 2024-11-04 22:25 UTC (permalink / raw)
  To: Patrick Steinhardt; +Cc: git, Taylor Blau, Toon Claes

On 24/10/21 11:28AM, Patrick Steinhardt wrote:
> Fix leaking trailer values when replacing the value with a command or
> when the token value is empty.
> 
> This leak is exposed by t7513, but plugging it does not make the whole
> test suite pass.
> 
> Signed-off-by: Patrick Steinhardt <ps@pks.im>
> ---
>  trailer.c | 12 +++++++++---
>  1 file changed, 9 insertions(+), 3 deletions(-)
> 
> diff --git a/trailer.c b/trailer.c
> index 682d74505bf..f1eca6d5d15 100644
> --- a/trailer.c
> +++ b/trailer.c
> @@ -249,17 +249,23 @@ static char *apply_command(struct conf_info *conf, const char *arg)
>  static void apply_item_command(struct trailer_item *in_tok, struct arg_item *arg_tok)
>  {
>  	if (arg_tok->conf.command || arg_tok->conf.cmd) {
> -		const char *arg;
> +		char *value_to_free = NULL;
> +		char *arg;
> +
>  		if (arg_tok->value && arg_tok->value[0]) {
> -			arg = arg_tok->value;
> +			arg = (char *)arg_tok->value;

Naive question, is this cast not redundant? From looking at `struct
arg_item`, `value` already looks to be this type.

>  		} else {
>  			if (in_tok && in_tok->value)
>  				arg = xstrdup(in_tok->value);
>  			else
>  				arg = xstrdup("");
> +			value_to_free = arg_tok->value;
>  		}
> +
>  		arg_tok->value = apply_command(&arg_tok->conf, arg);
> -		free((char *)arg);
> +
> +		free(value_to_free);
> +		free(arg);
>  	}
>  }
>  
> -- 
> 2.47.0.72.gef8ce8f3d4.dirty
> 
> 

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

* Re: [PATCH v2 11/22] trailer: fix leaking strbufs when formatting trailers
  2024-10-21  9:28   ` [PATCH v2 11/22] trailer: fix leaking strbufs when formatting trailers Patrick Steinhardt
  2024-10-21 20:58     ` Taylor Blau
@ 2024-11-04 22:31     ` Justin Tobler
  2024-11-05  5:54       ` Patrick Steinhardt
  1 sibling, 1 reply; 100+ messages in thread
From: Justin Tobler @ 2024-11-04 22:31 UTC (permalink / raw)
  To: Patrick Steinhardt; +Cc: git, Taylor Blau, Toon Claes

On 24/10/21 11:28AM, Patrick Steinhardt wrote:
> We are populating, but never releasing two string buffers in
> `format_trailers()`, causing a memory leak. Plug this leak by lifting
> those buffers outside of the loop and releasing them on function return.
> This fixes the memory leaks, but also optimizes the loop as we don't
> have to reallocate the buffers on every single iteration.

I see that we were previously calling `strbuf_release()` inside of the
loop. In practice were these never hit? Or just sometimes skipped my the
"continue" in the loop? The commit message makes it sound like the
former.


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

* Re: [PATCH v2 15/22] combine-diff: fix leaking lost lines
  2024-10-21  9:28   ` [PATCH v2 15/22] combine-diff: fix leaking lost lines Patrick Steinhardt
@ 2024-11-04 22:43     ` Justin Tobler
  2024-11-05  5:55       ` Patrick Steinhardt
  0 siblings, 1 reply; 100+ messages in thread
From: Justin Tobler @ 2024-11-04 22:43 UTC (permalink / raw)
  To: Patrick Steinhardt; +Cc: git, Taylor Blau, Toon Claes

On 24/10/21 11:28AM, Patrick Steinhardt wrote:
> The `cnt` variable tracks the number of lines in a patch diff. It can
> happen though that there are no newlines, in which case we'd still end
> up allocating our array of `sline`s. In fact, we always allocate it with
> `cnt + 2` entries. But when we loop through the array to clear it at the
> end of this function we only loop until `lno < cnt`, and thus we may not
> end up releasing whatever the two extra `sline`s contain.
> 
> Plug this memory leak.
> 
> Signed-off-by: Patrick Steinhardt <ps@pks.im>
> ---
>  combine-diff.c           | 2 +-
>  t/t4038-diff-combined.sh | 1 +
>  2 files changed, 2 insertions(+), 1 deletion(-)
> 
> diff --git a/combine-diff.c b/combine-diff.c
> index f6b624dc288..3c6d9507fec 100644
> --- a/combine-diff.c
> +++ b/combine-diff.c
> @@ -1220,7 +1220,7 @@ static void show_patch_diff(struct combine_diff_path *elem, int num_parent,
>  	}
>  	free(result);
>  
> -	for (lno = 0; lno < cnt; lno++) {
> +	for (lno = 0; lno < cnt + 2; lno++) {

From looking only at the code, its not very obvious to me where the "+2"
comes from. Not really worth a reroll, but it might be nice to leave a
note with some context.

>  		if (sline[lno].lost) {
>  			struct lline *ll = sline[lno].lost;
>  			while (ll) {
> diff --git a/t/t4038-diff-combined.sh b/t/t4038-diff-combined.sh
> index 2ce26e585c9..00190802d83 100755
> --- a/t/t4038-diff-combined.sh
> +++ b/t/t4038-diff-combined.sh
> @@ -5,6 +5,7 @@ test_description='combined diff'
>  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-diff.sh
>  
> -- 
> 2.47.0.72.gef8ce8f3d4.dirty
> 
> 

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

* Re: [PATCH v2 00/22] Memory leak fixes (pt.9)
  2024-10-21  9:27 ` [PATCH v2 00/22] " Patrick Steinhardt
                     ` (22 preceding siblings ...)
  2024-10-21  9:54   ` [PATCH v2 00/22] Memory leak fixes (pt.9) Kristoffer Haugsbakk
@ 2024-11-04 22:46   ` Justin Tobler
  2024-11-05  5:55     ` Patrick Steinhardt
  23 siblings, 1 reply; 100+ messages in thread
From: Justin Tobler @ 2024-11-04 22:46 UTC (permalink / raw)
  To: Patrick Steinhardt; +Cc: git, Taylor Blau, Toon Claes

On 24/10/21 11:27AM, Patrick Steinhardt wrote:
> Hi,
> 
> this is the second version of my 9th series of memory leak fixes.
> 
> Changes compared to v1:
> 
>   - Split up the trailer fixes into two separate patches so that we can
>     explain them standalone.
> 
>   - Adapt the second trailer memory leak fix to instead pull up the
>     strbufs out of the loop such that we can reuse them. This makes the
>     code flow more naturally and optimizes the loop.
> 
> Thanks!
> 
> Patrick

I've reviewed all the patches in this version and left a few
non-blocking thoughts. Overall, this version looks good to me though. :)

-Justin

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

* Re: [PATCH v2 10/22] trailer: fix leaking trailer values
  2024-11-04 22:25     ` Justin Tobler
@ 2024-11-05  5:54       ` Patrick Steinhardt
  0 siblings, 0 replies; 100+ messages in thread
From: Patrick Steinhardt @ 2024-11-05  5:54 UTC (permalink / raw)
  To: Justin Tobler; +Cc: git, Taylor Blau, Toon Claes

On Mon, Nov 04, 2024 at 04:25:38PM -0600, Justin Tobler wrote:
> On 24/10/21 11:28AM, Patrick Steinhardt wrote:
> > Fix leaking trailer values when replacing the value with a command or
> > when the token value is empty.
> > 
> > This leak is exposed by t7513, but plugging it does not make the whole
> > test suite pass.
> > 
> > Signed-off-by: Patrick Steinhardt <ps@pks.im>
> > ---
> >  trailer.c | 12 +++++++++---
> >  1 file changed, 9 insertions(+), 3 deletions(-)
> > 
> > diff --git a/trailer.c b/trailer.c
> > index 682d74505bf..f1eca6d5d15 100644
> > --- a/trailer.c
> > +++ b/trailer.c
> > @@ -249,17 +249,23 @@ static char *apply_command(struct conf_info *conf, const char *arg)
> >  static void apply_item_command(struct trailer_item *in_tok, struct arg_item *arg_tok)
> >  {
> >  	if (arg_tok->conf.command || arg_tok->conf.cmd) {
> > -		const char *arg;
> > +		char *value_to_free = NULL;
> > +		char *arg;
> > +
> >  		if (arg_tok->value && arg_tok->value[0]) {
> > -			arg = arg_tok->value;
> > +			arg = (char *)arg_tok->value;
> 
> Naive question, is this cast not redundant? From looking at `struct
> arg_item`, `value` already looks to be this type.

Indeed it is, good catch!

Patrick

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

* Re: [PATCH v2 11/22] trailer: fix leaking strbufs when formatting trailers
  2024-11-04 22:31     ` Justin Tobler
@ 2024-11-05  5:54       ` Patrick Steinhardt
  0 siblings, 0 replies; 100+ messages in thread
From: Patrick Steinhardt @ 2024-11-05  5:54 UTC (permalink / raw)
  To: Justin Tobler; +Cc: git, Taylor Blau, Toon Claes

On Mon, Nov 04, 2024 at 04:31:34PM -0600, Justin Tobler wrote:
> On 24/10/21 11:28AM, Patrick Steinhardt wrote:
> > We are populating, but never releasing two string buffers in
> > `format_trailers()`, causing a memory leak. Plug this leak by lifting
> > those buffers outside of the loop and releasing them on function return.
> > This fixes the memory leaks, but also optimizes the loop as we don't
> > have to reallocate the buffers on every single iteration.
> 
> I see that we were previously calling `strbuf_release()` inside of the
> loop. In practice were these never hit? Or just sometimes skipped my the
> "continue" in the loop? The commit message makes it sound like the
> former.

True, "never" is definitely too strong of a wording here. Will adapt,
thanks!

Patrick

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

* Re: [PATCH v2 15/22] combine-diff: fix leaking lost lines
  2024-11-04 22:43     ` Justin Tobler
@ 2024-11-05  5:55       ` Patrick Steinhardt
  0 siblings, 0 replies; 100+ messages in thread
From: Patrick Steinhardt @ 2024-11-05  5:55 UTC (permalink / raw)
  To: Justin Tobler; +Cc: git, Taylor Blau, Toon Claes

On Mon, Nov 04, 2024 at 04:43:38PM -0600, Justin Tobler wrote:
> On 24/10/21 11:28AM, Patrick Steinhardt wrote:
> > The `cnt` variable tracks the number of lines in a patch diff. It can
> > happen though that there are no newlines, in which case we'd still end
> > up allocating our array of `sline`s. In fact, we always allocate it with
> > `cnt + 2` entries. But when we loop through the array to clear it at the
> > end of this function we only loop until `lno < cnt`, and thus we may not
> > end up releasing whatever the two extra `sline`s contain.
> > 
> > Plug this memory leak.
> > 
> > Signed-off-by: Patrick Steinhardt <ps@pks.im>
> > ---
> >  combine-diff.c           | 2 +-
> >  t/t4038-diff-combined.sh | 1 +
> >  2 files changed, 2 insertions(+), 1 deletion(-)
> > 
> > diff --git a/combine-diff.c b/combine-diff.c
> > index f6b624dc288..3c6d9507fec 100644
> > --- a/combine-diff.c
> > +++ b/combine-diff.c
> > @@ -1220,7 +1220,7 @@ static void show_patch_diff(struct combine_diff_path *elem, int num_parent,
> >  	}
> >  	free(result);
> >  
> > -	for (lno = 0; lno < cnt; lno++) {
> > +	for (lno = 0; lno < cnt + 2; lno++) {
> 
> From looking only at the code, its not very obvious to me where the "+2"
> comes from. Not really worth a reroll, but it might be nice to leave a
> note with some context.

The code is quite convoluted and hard to read, agreed. In any case, we
call `CALLOC_ARRAY(sline, st_add(cnt, 2))`, and as a comment further up
mentions:

    /* Even p_lno[cnt+1] is valid -- that is for the end line number for
     * deletion hunk at the end.
     */

This explains the +1. The second +1 seems to never be populated and acts
more like a sentinel value.

I don't really think it makes a ton of sense to explain why the sline
array is overallocated when freeing it, and we already do explain it.
But I'll touch up the commit message a bit and sneak in a fix of the
above comment to be properly formatted, which also gives the necessary
context when reading the diff, only.

Patrick

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

* Re: [PATCH v2 00/22] Memory leak fixes (pt.9)
  2024-11-04 22:46   ` Justin Tobler
@ 2024-11-05  5:55     ` Patrick Steinhardt
  0 siblings, 0 replies; 100+ messages in thread
From: Patrick Steinhardt @ 2024-11-05  5:55 UTC (permalink / raw)
  To: Justin Tobler; +Cc: git, Taylor Blau, Toon Claes

On Mon, Nov 04, 2024 at 04:46:57PM -0600, Justin Tobler wrote:
> On 24/10/21 11:27AM, Patrick Steinhardt wrote:
> > Hi,
> > 
> > this is the second version of my 9th series of memory leak fixes.
> > 
> > Changes compared to v1:
> > 
> >   - Split up the trailer fixes into two separate patches so that we can
> >     explain them standalone.
> > 
> >   - Adapt the second trailer memory leak fix to instead pull up the
> >     strbufs out of the loop such that we can reuse them. This makes the
> >     code flow more naturally and optimizes the loop.
> > 
> > Thanks!
> > 
> > Patrick
> 
> I've reviewed all the patches in this version and left a few
> non-blocking thoughts. Overall, this version looks good to me though. :)

Thanks for your review!

Patrick

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

* [PATCH v3 00/22] Memory leak fixes (pt.9)
  2024-10-11  5:32 [PATCH 00/21] Memory leak fixes (pt.9) Patrick Steinhardt
                   ` (22 preceding siblings ...)
  2024-10-21  9:27 ` [PATCH v2 00/22] " Patrick Steinhardt
@ 2024-11-05  6:16 ` Patrick Steinhardt
  2024-11-05  6:16   ` [PATCH v3 01/22] builtin/ls-remote: plug leaking server options Patrick Steinhardt
                     ` (22 more replies)
  23 siblings, 23 replies; 100+ messages in thread
From: Patrick Steinhardt @ 2024-11-05  6:16 UTC (permalink / raw)
  To: git; +Cc: Taylor Blau, Toon Claes, Kristoffer Haugsbakk, Justin Tobler

Hi,

this is the third revision of my 9th series of memory leak fixes.
Changes compared to v2:

  - Remove an unnecessary cast.

  - Fix a duplicate newline.

  - Polish a couple of commit messages.

Thanks!

Patrick

Patrick Steinhardt (22):
  builtin/ls-remote: plug leaking server options
  t/helper: fix leaks in "reach" test tool
  grep: fix leak in `grep_splice_or()`
  builtin/grep: fix leak with `--max-count=0`
  revision: fix leaking bloom filters
  diff-lib: fix leaking diffopts in `do_diff_cache()`
  pretty: clear signature check
  upload-pack: fix leaking URI protocols
  builtin/commit: fix leaking change data contents
  trailer: fix leaking trailer values
  trailer: fix leaking strbufs when formatting trailers
  builtin/commit: fix leaking cleanup config
  transport-helper: fix leaking import/export marks
  builtin/tag: fix leaking key ID on failure to sign
  combine-diff: fix leaking lost lines
  dir: release untracked cache data
  sparse-index: correctly free EWAH contents
  t/helper: stop re-initialization of `the_repository`
  t/helper: fix leaking buffer in "dump-untracked-cache"
  dir: fix leak when parsing "status.showUntrackedFiles"
  builtin/merge: release output buffer after performing merge
  list-objects-filter-options: work around reported leak on error

 builtin/commit.c                          | 26 +++++++++++++++++------
 builtin/grep.c                            | 13 +++++++++---
 builtin/ls-remote.c                       |  1 +
 builtin/merge.c                           |  1 +
 builtin/tag.c                             |  2 +-
 combine-diff.c                            |  5 +++--
 diff-lib.c                                |  1 +
 dir.c                                     | 12 +++++++++--
 grep.c                                    |  1 +
 list-objects-filter-options.c             | 17 ++++++---------
 pretty.c                                  |  1 +
 revision.c                                |  5 +++++
 sparse-index.c                            |  7 ++++--
 t/helper/test-dump-untracked-cache.c      |  2 ++
 t/helper/test-reach.c                     | 10 +++++++++
 t/helper/test-read-cache.c                |  2 --
 t/t4038-diff-combined.sh                  |  1 +
 t/t4202-log.sh                            |  1 +
 t/t4216-log-bloom.sh                      |  1 +
 t/t5702-protocol-v2.sh                    |  1 +
 t/t5801-remote-helpers.sh                 |  1 +
 t/t6112-rev-list-filters-objects.sh       |  1 +
 t/t6424-merge-unrelated-index-changes.sh  |  1 +
 t/t6600-test-reach.sh                     |  1 +
 t/t7004-tag.sh                            |  1 +
 t/t7031-verify-tag-signed-ssh.sh          |  1 +
 t/t7063-status-untracked-cache.sh         |  1 +
 t/t7500-commit-template-squash-signoff.sh |  1 +
 t/t7502-commit-porcelain.sh               |  1 +
 t/t7510-signed-commit.sh                  |  1 +
 t/t7513-interpret-trailers.sh             |  1 +
 t/t7519-status-fsmonitor.sh               |  1 +
 t/t7528-signed-commit-ssh.sh              |  1 +
 t/t7610-mergetool.sh                      |  1 +
 t/t7810-grep.sh                           |  1 +
 trailer.c                                 | 22 +++++++++++++------
 transport-helper.c                        |  2 ++
 upload-pack.c                             |  1 +
 38 files changed, 115 insertions(+), 35 deletions(-)

Range-diff against v2:
 1:  89b66411354 !  1:  fbb9e68e2f2 builtin/ls-remote: plug leaking server options
    @@ Metadata
      ## Commit message ##
         builtin/ls-remote: plug leaking server options
     
    -    The server options populated via `OPT_STRING_LIST()` is never cleared,
    -    causing a memory leak. Plug it.
    +    The list of server options populated via `OPT_STRING_LIST()` is never
    +    cleared, causing a memory leak. Plug it.
     
         This leak is exposed by t5702, but plugging it alone does not make the
         whole test suite pass.
 2:  1c42e194b20 =  2:  17136f4bdb3 t/helper: fix leaks in "reach" test tool
 3:  cb4eee37b40 !  3:  74b21470194 grep: fix leak in `grep_splice_or()`
    @@ Commit message
         grep: fix leak in `grep_splice_or()`
     
         In `grep_splice_or()` we search for the next `TRUE` node in our tree of
    -    grep exrpessions and replace it with the given new expression. But we
    +    grep expressions and replace it with the given new expression. But we
         don't free the old node, which causes a memory leak. Plug it.
     
         This leak is exposed by t7810, but plugging it alone isn't sufficient to
 4:  6b2c8842ef5 =  4:  d716f93169a builtin/grep: fix leak with `--max-count=0`
 5:  7527b31a28f =  5:  aeb8a19d28d revision: fix leaking bloom filters
 6:  60af98cb2c7 !  6:  24d9d9b1358 diff-lib: fix leaking diffopts in `do_diff_cache()`
    @@ Commit message
         In `do_diff_cache()` we initialize a new `rev_info` and then overwrite
         its `diffopt` with a user-provided set of options. This can leak memory
         because `repo_init_revisions()` may end up allocating memory for the
    -    `diffopt` itself depending on the configuration. And as that field is
    -    overwritten we won't ever free that.
    +    `diffopt` itself depending on the configuration. And since that field is
    +    overwritten we won't ever free it.
     
         Plug the memory leak by releasing the diffopts before we overwrite them.
     
 7:  5d5f6867f91 !  7:  58ebef7e757 pretty: clear signature check
    @@ Metadata
      ## Commit message ##
         pretty: clear signature check
     
    -    The signature check in of the formatting context is never getting
    -    released. Fix this to plug the resulting memory leak.
    +    The signature check in the formatting context is never getting released.
    +    Fix this to plug the resulting memory leak.
     
         Signed-off-by: Patrick Steinhardt <ps@pks.im>
     
 8:  0d503e40194 =  8:  c5813079d44 upload-pack: fix leaking URI protocols
 9:  9f967dfe5d5 =  9:  f66fa4e0e25 builtin/commit: fix leaking change data contents
10:  e3ffd59123f ! 10:  dac63bae39e trailer: fix leaking trailer values
    @@ trailer.c: static char *apply_command(struct conf_info *conf, const char *arg)
     +		char *arg;
     +
      		if (arg_tok->value && arg_tok->value[0]) {
    --			arg = arg_tok->value;
    -+			arg = (char *)arg_tok->value;
    + 			arg = arg_tok->value;
      		} else {
    - 			if (in_tok && in_tok->value)
    +@@ trailer.c: static void apply_item_command(struct trailer_item *in_tok, struct arg_item *arg
      				arg = xstrdup(in_tok->value);
      			else
      				arg = xstrdup("");
11:  5b851453bce ! 11:  82269e5d5be trailer: fix leaking strbufs when formatting trailers
    @@ Metadata
      ## Commit message ##
         trailer: fix leaking strbufs when formatting trailers
     
    -    We are populating, but never releasing two string buffers in
    -    `format_trailers()`, causing a memory leak. Plug this leak by lifting
    -    those buffers outside of the loop and releasing them on function return.
    -    This fixes the memory leaks, but also optimizes the loop as we don't
    -    have to reallocate the buffers on every single iteration.
    +    When formatting trailer lines we iterate through each of the trailers
    +    and munge their respective token/value pairs according to the trailer
    +    options. When formatting a trailer that has its `item->token` pointer
    +    set we perform the munging in two local buffers. In the case where we
    +    figure out that the value is empty and `trim_empty` is set we just skip
    +    over the trailer item. But the buffers are local to the loop and we
    +    don't release their contents, leading to a memory leak.
    +
    +    Plug this leak by lifting the buffers outside of the loop and releasing
    +    them on function return. This fixes the memory leaks, but also optimizes
    +    the loop as we don't have to reallocate the buffers on every single
    +    iteration.
     
         Signed-off-by: Patrick Steinhardt <ps@pks.im>
     
    @@ trailer.c: void format_trailers(const struct process_trailer_options *opts,
      	size_t origlen = out->len;
      	struct list_head *pos;
      	struct trailer_item *item;
    - 
    -+
    +@@ trailer.c: void format_trailers(const struct process_trailer_options *opts,
      	list_for_each(pos, trailers) {
      		item = list_entry(pos, struct trailer_item, list);
      		if (item->token) {
12:  60c3f6146f3 = 12:  a627e03702e builtin/commit: fix leaking cleanup config
13:  ea81cd8db86 = 13:  40e0c2a2cac transport-helper: fix leaking import/export marks
14:  b700ab9079f = 14:  ffa5d9eae7e builtin/tag: fix leaking key ID on failure to sign
15:  76bbcb3fe30 ! 15:  70dd0cb6933 combine-diff: fix leaking lost lines
    @@ Commit message
         The `cnt` variable tracks the number of lines in a patch diff. It can
         happen though that there are no newlines, in which case we'd still end
         up allocating our array of `sline`s. In fact, we always allocate it with
    -    `cnt + 2` entries. But when we loop through the array to clear it at the
    -    end of this function we only loop until `lno < cnt`, and thus we may not
    -    end up releasing whatever the two extra `sline`s contain.
    +    `cnt + 2` entries: one extra entry for the deletion hunk at the end, and
    +    another entry that we don't seem to ever populate at all but acts as a
    +    kind of sentinel value.
     
    -    Plug this memory leak.
    +    When we loop through the array to clear it at the end of this function
    +    we only loop until `lno < cnt`, and thus we may not end up releasing
    +    whatever the two extra `sline`s contain. While that shouldn't matter for
    +    the sentinel value, it does matter for the extra deletion hunk sline.
    +    Regardless of that, plug this memory leak by releasing both extra
    +    entries, which makes the logic a bit easier to reason about.
    +
    +    While at it, fix the formatting of a local comment, which incidentally
    +    also provides the necessary context for why we overallocate the `sline`
    +    array.
     
         Signed-off-by: Patrick Steinhardt <ps@pks.im>
     
      ## combine-diff.c ##
    +@@ combine-diff.c: static void show_patch_diff(struct combine_diff_path *elem, int num_parent,
    + 	result_file.ptr = result;
    + 	result_file.size = result_size;
    + 
    +-	/* Even p_lno[cnt+1] is valid -- that is for the end line number
    ++	/*
    ++	 * Even p_lno[cnt+1] is valid -- that is for the end line number
    + 	 * for deletion hunk at the end.
    + 	 */
    + 	CALLOC_ARRAY(sline[0].p_lno, st_mult(st_add(cnt, 2), num_parent));
     @@ combine-diff.c: static void show_patch_diff(struct combine_diff_path *elem, int num_parent,
      	}
      	free(result);
16:  d6b96a4012d = 16:  b248f266a91 dir: release untracked cache data
17:  3aa6bac5079 = 17:  76e9a6d5792 sparse-index: correctly free EWAH contents
18:  132fe750906 = 18:  70f16486d77 t/helper: stop re-initialization of `the_repository`
19:  b8b702eeb28 = 19:  f056d31ca50 t/helper: fix leaking buffer in "dump-untracked-cache"
20:  ad309ac1b37 = 20:  714c9286e7a dir: fix leak when parsing "status.showUntrackedFiles"
21:  5e243f9ee53 ! 21:  0ff65c1213b builtin/merge: release outbut buffer after performing merge
    @@ Metadata
     Author: Patrick Steinhardt <ps@pks.im>
     
      ## Commit message ##
    -    builtin/merge: release outbut buffer after performing merge
    +    builtin/merge: release output buffer after performing merge
     
         The `obuf` member of `struct merge_options` is used to buffer output in
         some cases. In order to not discard its allocated memory we only release
22:  b75376e3725 = 22:  d9e122bb5db list-objects-filter-options: work around reported leak on error
-- 
2.47.0.229.g8f8d6eee53.dirty


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

* [PATCH v3 01/22] builtin/ls-remote: plug leaking server options
  2024-11-05  6:16 ` [PATCH v3 " Patrick Steinhardt
@ 2024-11-05  6:16   ` Patrick Steinhardt
  2024-11-05  6:16   ` [PATCH v3 02/22] t/helper: fix leaks in "reach" test tool Patrick Steinhardt
                     ` (21 subsequent siblings)
  22 siblings, 0 replies; 100+ messages in thread
From: Patrick Steinhardt @ 2024-11-05  6:16 UTC (permalink / raw)
  To: git; +Cc: Taylor Blau, Toon Claes, Kristoffer Haugsbakk, Justin Tobler

The list of server options populated via `OPT_STRING_LIST()` is never
cleared, causing a memory leak. Plug it.

This leak is exposed by t5702, but plugging it alone does not make the
whole test suite pass.

Signed-off-by: Patrick Steinhardt <ps@pks.im>
---
 builtin/ls-remote.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/builtin/ls-remote.c b/builtin/ls-remote.c
index f723b3bf3bb..f333821b994 100644
--- a/builtin/ls-remote.c
+++ b/builtin/ls-remote.c
@@ -166,6 +166,7 @@ int cmd_ls_remote(int argc,
 		status = 0; /* we found something */
 	}
 
+	string_list_clear(&server_options, 0);
 	ref_sorting_release(sorting);
 	ref_array_clear(&ref_array);
 	if (transport_disconnect(transport))
-- 
2.47.0.229.g8f8d6eee53.dirty


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

* [PATCH v3 02/22] t/helper: fix leaks in "reach" test tool
  2024-11-05  6:16 ` [PATCH v3 " Patrick Steinhardt
  2024-11-05  6:16   ` [PATCH v3 01/22] builtin/ls-remote: plug leaking server options Patrick Steinhardt
@ 2024-11-05  6:16   ` Patrick Steinhardt
  2024-11-05  6:16   ` [PATCH v3 03/22] grep: fix leak in `grep_splice_or()` Patrick Steinhardt
                     ` (20 subsequent siblings)
  22 siblings, 0 replies; 100+ messages in thread
From: Patrick Steinhardt @ 2024-11-05  6:16 UTC (permalink / raw)
  To: git; +Cc: Taylor Blau, Toon Claes, Kristoffer Haugsbakk, Justin Tobler

The "reach" test tool doesn't bother to clean up any of its allocated
resources, causing various leaks. Plug them.

Signed-off-by: Patrick Steinhardt <ps@pks.im>
---
 t/helper/test-reach.c | 10 ++++++++++
 t/t6600-test-reach.sh |  1 +
 2 files changed, 11 insertions(+)

diff --git a/t/helper/test-reach.c b/t/helper/test-reach.c
index 995e382863a..84deee604ad 100644
--- a/t/helper/test-reach.c
+++ b/t/helper/test-reach.c
@@ -127,10 +127,12 @@ int cmd__reach(int ac, const char **av)
 			exit(128);
 		printf("%s(A,X):\n", av[1]);
 		print_sorted_commit_ids(list);
+		free_commit_list(list);
 	} else if (!strcmp(av[1], "reduce_heads")) {
 		struct commit_list *list = reduce_heads(X);
 		printf("%s(X):\n", av[1]);
 		print_sorted_commit_ids(list);
+		free_commit_list(list);
 	} else if (!strcmp(av[1], "can_all_from_reach")) {
 		printf("%s(X,Y):%d\n", av[1], can_all_from_reach(X, Y, 1));
 	} else if (!strcmp(av[1], "can_all_from_reach_with_flag")) {
@@ -153,6 +155,7 @@ int cmd__reach(int ac, const char **av)
 			filter.with_commit_tag_algo = 0;
 
 		printf("%s(_,A,X,_):%d\n", av[1], commit_contains(&filter, A, X, &cache));
+		clear_contains_cache(&cache);
 	} else if (!strcmp(av[1], "get_reachable_subset")) {
 		const int reachable_flag = 1;
 		int i, count = 0;
@@ -176,7 +179,14 @@ int cmd__reach(int ac, const char **av)
 			die(_("too many commits marked reachable"));
 
 		print_sorted_commit_ids(list);
+		free_commit_list(list);
 	}
 
+	object_array_clear(&X_obj);
+	strbuf_release(&buf);
+	free_commit_list(X);
+	free_commit_list(Y);
+	free(X_array);
+	free(Y_array);
 	return 0;
 }
diff --git a/t/t6600-test-reach.sh b/t/t6600-test-reach.sh
index 2591f8b8b39..307deefed2c 100755
--- a/t/t6600-test-reach.sh
+++ b/t/t6600-test-reach.sh
@@ -2,6 +2,7 @@
 
 test_description='basic commit reachability tests'
 
+TEST_PASSES_SANITIZE_LEAK=true
 . ./test-lib.sh
 
 # Construct a grid-like commit graph with points (x,y)
-- 
2.47.0.229.g8f8d6eee53.dirty


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

* [PATCH v3 03/22] grep: fix leak in `grep_splice_or()`
  2024-11-05  6:16 ` [PATCH v3 " Patrick Steinhardt
  2024-11-05  6:16   ` [PATCH v3 01/22] builtin/ls-remote: plug leaking server options Patrick Steinhardt
  2024-11-05  6:16   ` [PATCH v3 02/22] t/helper: fix leaks in "reach" test tool Patrick Steinhardt
@ 2024-11-05  6:16   ` Patrick Steinhardt
  2024-11-05  6:16   ` [PATCH v3 04/22] builtin/grep: fix leak with `--max-count=0` Patrick Steinhardt
                     ` (19 subsequent siblings)
  22 siblings, 0 replies; 100+ messages in thread
From: Patrick Steinhardt @ 2024-11-05  6:16 UTC (permalink / raw)
  To: git; +Cc: Taylor Blau, Toon Claes, Kristoffer Haugsbakk, Justin Tobler

In `grep_splice_or()` we search for the next `TRUE` node in our tree of
grep expressions and replace it with the given new expression. But we
don't free the old node, which causes a memory leak. Plug it.

This leak is exposed by t7810, but plugging it alone isn't sufficient to
make the test suite pass.

Signed-off-by: Patrick Steinhardt <ps@pks.im>
---
 grep.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/grep.c b/grep.c
index 701e58de04e..e9337f32cbf 100644
--- a/grep.c
+++ b/grep.c
@@ -756,6 +756,7 @@ static struct grep_expr *grep_splice_or(struct grep_expr *x, struct grep_expr *y
 		assert(x->node == GREP_NODE_OR);
 		if (x->u.binary.right &&
 		    x->u.binary.right->node == GREP_NODE_TRUE) {
+			free(x->u.binary.right);
 			x->u.binary.right = y;
 			break;
 		}
-- 
2.47.0.229.g8f8d6eee53.dirty


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

* [PATCH v3 04/22] builtin/grep: fix leak with `--max-count=0`
  2024-11-05  6:16 ` [PATCH v3 " Patrick Steinhardt
                     ` (2 preceding siblings ...)
  2024-11-05  6:16   ` [PATCH v3 03/22] grep: fix leak in `grep_splice_or()` Patrick Steinhardt
@ 2024-11-05  6:16   ` Patrick Steinhardt
  2024-11-05  6:16   ` [PATCH v3 05/22] revision: fix leaking bloom filters Patrick Steinhardt
                     ` (18 subsequent siblings)
  22 siblings, 0 replies; 100+ messages in thread
From: Patrick Steinhardt @ 2024-11-05  6:16 UTC (permalink / raw)
  To: git; +Cc: Taylor Blau, Toon Claes, Kristoffer Haugsbakk, Justin Tobler

When executing with `--max-count=0` we'll return early from git-grep(1)
without performing any cleanup, which causes memory leaks. Plug these.

Signed-off-by: Patrick Steinhardt <ps@pks.im>
---
 builtin/grep.c  | 13 ++++++++++---
 t/t7810-grep.sh |  1 +
 2 files changed, 11 insertions(+), 3 deletions(-)

diff --git a/builtin/grep.c b/builtin/grep.c
index f17d46a06e4..98b85c7fcac 100644
--- a/builtin/grep.c
+++ b/builtin/grep.c
@@ -906,6 +906,7 @@ int cmd_grep(int argc,
 	int dummy;
 	int use_index = 1;
 	int allow_revs;
+	int ret;
 
 	struct option options[] = {
 		OPT_BOOL(0, "cached", &cached,
@@ -1172,8 +1173,10 @@ int cmd_grep(int argc,
 	 * Optimize out the case where the amount of matches is limited to zero.
 	 * We do this to keep results consistent with GNU grep(1).
 	 */
-	if (opt.max_count == 0)
-		return 1;
+	if (opt.max_count == 0) {
+		ret = 1;
+		goto out;
+	}
 
 	if (show_in_pager) {
 		if (num_threads > 1)
@@ -1267,10 +1270,14 @@ int cmd_grep(int argc,
 		hit |= wait_all();
 	if (hit && show_in_pager)
 		run_pager(&opt, prefix);
+
+	ret = !hit;
+
+out:
 	clear_pathspec(&pathspec);
 	string_list_clear(&path_list, 0);
 	free_grep_patterns(&opt);
 	object_array_clear(&list);
 	free_repos();
-	return !hit;
+	return ret;
 }
diff --git a/t/t7810-grep.sh b/t/t7810-grep.sh
index af2cf2f78ab..9e7681f0831 100755
--- a/t/t7810-grep.sh
+++ b/t/t7810-grep.sh
@@ -9,6 +9,7 @@ test_description='git grep various.
 GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
 export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
 
+TEST_PASSES_SANITIZE_LEAK=true
 . ./test-lib.sh
 
 test_invalid_grep_expression() {
-- 
2.47.0.229.g8f8d6eee53.dirty


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

* [PATCH v3 05/22] revision: fix leaking bloom filters
  2024-11-05  6:16 ` [PATCH v3 " Patrick Steinhardt
                     ` (3 preceding siblings ...)
  2024-11-05  6:16   ` [PATCH v3 04/22] builtin/grep: fix leak with `--max-count=0` Patrick Steinhardt
@ 2024-11-05  6:16   ` Patrick Steinhardt
  2024-11-05  6:17   ` [PATCH v3 06/22] diff-lib: fix leaking diffopts in `do_diff_cache()` Patrick Steinhardt
                     ` (17 subsequent siblings)
  22 siblings, 0 replies; 100+ messages in thread
From: Patrick Steinhardt @ 2024-11-05  6:16 UTC (permalink / raw)
  To: git; +Cc: Taylor Blau, Toon Claes, Kristoffer Haugsbakk, Justin Tobler

The memory allocated by `prepare_to_use_bloom_filter()` is not released
by `release_revisions()`, causing a memory leak. Plug it.

Signed-off-by: Patrick Steinhardt <ps@pks.im>
---
 revision.c           | 5 +++++
 t/t4216-log-bloom.sh | 1 +
 2 files changed, 6 insertions(+)

diff --git a/revision.c b/revision.c
index f5f5b84f2b0..8df75b82249 100644
--- a/revision.c
+++ b/revision.c
@@ -3227,6 +3227,11 @@ void release_revisions(struct rev_info *revs)
 	clear_decoration(&revs->treesame, free);
 	line_log_free(revs);
 	oidset_clear(&revs->missing_commits);
+
+	for (int i = 0; i < revs->bloom_keys_nr; i++)
+		clear_bloom_key(&revs->bloom_keys[i]);
+	FREE_AND_NULL(revs->bloom_keys);
+	revs->bloom_keys_nr = 0;
 }
 
 static void add_child(struct rev_info *revs, struct commit *parent, struct commit *child)
diff --git a/t/t4216-log-bloom.sh b/t/t4216-log-bloom.sh
index 3f163dc3969..8d22338f6aa 100755
--- a/t/t4216-log-bloom.sh
+++ b/t/t4216-log-bloom.sh
@@ -4,6 +4,7 @@ test_description='git log for a path with Bloom filters'
 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-chunk.sh
 
-- 
2.47.0.229.g8f8d6eee53.dirty


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

* [PATCH v3 06/22] diff-lib: fix leaking diffopts in `do_diff_cache()`
  2024-11-05  6:16 ` [PATCH v3 " Patrick Steinhardt
                     ` (4 preceding siblings ...)
  2024-11-05  6:16   ` [PATCH v3 05/22] revision: fix leaking bloom filters Patrick Steinhardt
@ 2024-11-05  6:17   ` Patrick Steinhardt
  2024-11-05  6:17   ` [PATCH v3 07/22] pretty: clear signature check Patrick Steinhardt
                     ` (16 subsequent siblings)
  22 siblings, 0 replies; 100+ messages in thread
From: Patrick Steinhardt @ 2024-11-05  6:17 UTC (permalink / raw)
  To: git; +Cc: Taylor Blau, Toon Claes, Kristoffer Haugsbakk, Justin Tobler

In `do_diff_cache()` we initialize a new `rev_info` and then overwrite
its `diffopt` with a user-provided set of options. This can leak memory
because `repo_init_revisions()` may end up allocating memory for the
`diffopt` itself depending on the configuration. And since that field is
overwritten we won't ever free it.

Plug the memory leak by releasing the diffopts before we overwrite them.

Signed-off-by: Patrick Steinhardt <ps@pks.im>
---
 diff-lib.c           | 1 +
 t/t7610-mergetool.sh | 1 +
 2 files changed, 2 insertions(+)

diff --git a/diff-lib.c b/diff-lib.c
index 6b14b959629..3cf353946f5 100644
--- a/diff-lib.c
+++ b/diff-lib.c
@@ -661,6 +661,7 @@ int do_diff_cache(const struct object_id *tree_oid, struct diff_options *opt)
 
 	repo_init_revisions(opt->repo, &revs, NULL);
 	copy_pathspec(&revs.prune_data, &opt->pathspec);
+	diff_free(&revs.diffopt);
 	revs.diffopt = *opt;
 	revs.diffopt.no_free = 1;
 
diff --git a/t/t7610-mergetool.sh b/t/t7610-mergetool.sh
index 22b3a85b3e9..5c5e79e9905 100755
--- a/t/t7610-mergetool.sh
+++ b/t/t7610-mergetool.sh
@@ -10,6 +10,7 @@ Testing basic merge tool invocation'
 GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
 export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
 
+TEST_PASSES_SANITIZE_LEAK=true
 . ./test-lib.sh
 
 # All the mergetool test work by checking out a temporary branch based
-- 
2.47.0.229.g8f8d6eee53.dirty


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

* [PATCH v3 07/22] pretty: clear signature check
  2024-11-05  6:16 ` [PATCH v3 " Patrick Steinhardt
                     ` (5 preceding siblings ...)
  2024-11-05  6:17   ` [PATCH v3 06/22] diff-lib: fix leaking diffopts in `do_diff_cache()` Patrick Steinhardt
@ 2024-11-05  6:17   ` Patrick Steinhardt
  2024-11-05  6:17   ` [PATCH v3 08/22] upload-pack: fix leaking URI protocols Patrick Steinhardt
                     ` (15 subsequent siblings)
  22 siblings, 0 replies; 100+ messages in thread
From: Patrick Steinhardt @ 2024-11-05  6:17 UTC (permalink / raw)
  To: git; +Cc: Taylor Blau, Toon Claes, Kristoffer Haugsbakk, Justin Tobler

The signature check in the formatting context is never getting released.
Fix this to plug the resulting memory leak.

Signed-off-by: Patrick Steinhardt <ps@pks.im>
---
 pretty.c                         | 1 +
 t/t4202-log.sh                   | 1 +
 t/t7031-verify-tag-signed-ssh.sh | 1 +
 t/t7510-signed-commit.sh         | 1 +
 t/t7528-signed-commit-ssh.sh     | 1 +
 5 files changed, 5 insertions(+)

diff --git a/pretty.c b/pretty.c
index 6403e268900..098378720a4 100644
--- a/pretty.c
+++ b/pretty.c
@@ -2032,6 +2032,7 @@ void repo_format_commit_message(struct repository *r,
 
 	free(context.commit_encoding);
 	repo_unuse_commit_buffer(r, commit, context.message);
+	signature_check_clear(&context.signature_check);
 }
 
 static void pp_header(struct pretty_print_context *pp,
diff --git a/t/t4202-log.sh b/t/t4202-log.sh
index 51f7beb59f8..35bec4089a3 100755
--- a/t/t4202-log.sh
+++ b/t/t4202-log.sh
@@ -5,6 +5,7 @@ test_description='git log'
 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"
 . "$TEST_DIRECTORY/lib-terminal.sh"
diff --git a/t/t7031-verify-tag-signed-ssh.sh b/t/t7031-verify-tag-signed-ssh.sh
index 20913b37134..2ee62c07293 100755
--- a/t/t7031-verify-tag-signed-ssh.sh
+++ b/t/t7031-verify-tag-signed-ssh.sh
@@ -4,6 +4,7 @@ test_description='signed tag 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/t7510-signed-commit.sh b/t/t7510-signed-commit.sh
index 0d2dd29fe6a..eb229082e40 100755
--- a/t/t7510-signed-commit.sh
+++ b/t/t7510-signed-commit.sh
@@ -4,6 +4,7 @@ test_description='signed commit tests'
 GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
 export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
 
+TEST_PASSES_SANITIZE_LEAK=true
 . ./test-lib.sh
 GNUPGHOME_NOT_USED=$GNUPGHOME
 . "$TEST_DIRECTORY/lib-gpg.sh"
diff --git a/t/t7528-signed-commit-ssh.sh b/t/t7528-signed-commit-ssh.sh
index 065f7806362..68e18856b66 100755
--- a/t/t7528-signed-commit-ssh.sh
+++ b/t/t7528-signed-commit-ssh.sh
@@ -4,6 +4,7 @@ test_description='ssh signed commit tests'
 GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
 export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
 
+TEST_PASSES_SANITIZE_LEAK=true
 . ./test-lib.sh
 GNUPGHOME_NOT_USED=$GNUPGHOME
 . "$TEST_DIRECTORY/lib-gpg.sh"
-- 
2.47.0.229.g8f8d6eee53.dirty


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

* [PATCH v3 08/22] upload-pack: fix leaking URI protocols
  2024-11-05  6:16 ` [PATCH v3 " Patrick Steinhardt
                     ` (6 preceding siblings ...)
  2024-11-05  6:17   ` [PATCH v3 07/22] pretty: clear signature check Patrick Steinhardt
@ 2024-11-05  6:17   ` Patrick Steinhardt
  2024-11-05  6:17   ` [PATCH v3 09/22] builtin/commit: fix leaking change data contents Patrick Steinhardt
                     ` (14 subsequent siblings)
  22 siblings, 0 replies; 100+ messages in thread
From: Patrick Steinhardt @ 2024-11-05  6:17 UTC (permalink / raw)
  To: git; +Cc: Taylor Blau, Toon Claes, Kristoffer Haugsbakk, Justin Tobler

We don't clear `struct upload_pack::uri_protocols`, which causes a
memory leak. Fix this.

Signed-off-by: Patrick Steinhardt <ps@pks.im>
---
 t/t5702-protocol-v2.sh | 1 +
 upload-pack.c          | 1 +
 2 files changed, 2 insertions(+)

diff --git a/t/t5702-protocol-v2.sh b/t/t5702-protocol-v2.sh
index 1ef540f73d3..ed55a2f7f95 100755
--- a/t/t5702-protocol-v2.sh
+++ b/t/t5702-protocol-v2.sh
@@ -7,6 +7,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 protocol v2 with 'git://' transport
diff --git a/upload-pack.c b/upload-pack.c
index 6d6e0f9f980..b4a59c3518b 100644
--- a/upload-pack.c
+++ b/upload-pack.c
@@ -166,6 +166,7 @@ static void upload_pack_data_clear(struct upload_pack_data *data)
 	object_array_clear(&data->extra_edge_obj);
 	list_objects_filter_release(&data->filter_options);
 	string_list_clear(&data->allowed_filters, 0);
+	string_list_clear(&data->uri_protocols, 0);
 
 	free((char *)data->pack_objects_hook);
 }
-- 
2.47.0.229.g8f8d6eee53.dirty


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

* [PATCH v3 09/22] builtin/commit: fix leaking change data contents
  2024-11-05  6:16 ` [PATCH v3 " Patrick Steinhardt
                     ` (7 preceding siblings ...)
  2024-11-05  6:17   ` [PATCH v3 08/22] upload-pack: fix leaking URI protocols Patrick Steinhardt
@ 2024-11-05  6:17   ` Patrick Steinhardt
  2024-11-05  6:17   ` [PATCH v3 10/22] trailer: fix leaking trailer values Patrick Steinhardt
                     ` (13 subsequent siblings)
  22 siblings, 0 replies; 100+ messages in thread
From: Patrick Steinhardt @ 2024-11-05  6:17 UTC (permalink / raw)
  To: git; +Cc: Taylor Blau, Toon Claes, Kristoffer Haugsbakk, Justin Tobler

While we free the worktree change data, we never free its contents. Fix
this.

Signed-off-by: Patrick Steinhardt <ps@pks.im>
---
 builtin/commit.c                          | 9 ++++++++-
 t/t7500-commit-template-squash-signoff.sh | 1 +
 2 files changed, 9 insertions(+), 1 deletion(-)

diff --git a/builtin/commit.c b/builtin/commit.c
index 8db4e9df0c9..18a55bd1b91 100644
--- a/builtin/commit.c
+++ b/builtin/commit.c
@@ -728,6 +728,13 @@ static void prepare_amend_commit(struct commit *commit, struct strbuf *sb,
 	repo_unuse_commit_buffer(the_repository, commit, buffer);
 }
 
+static void change_data_free(void *util, const char *str UNUSED)
+{
+	struct wt_status_change_data *d = util;
+	free(d->rename_source);
+	free(d);
+}
+
 static int prepare_to_commit(const char *index_file, const char *prefix,
 			     struct commit *current_head,
 			     struct wt_status *s,
@@ -991,7 +998,7 @@ static int prepare_to_commit(const char *index_file, const char *prefix,
 		s->use_color = 0;
 		committable = run_status(s->fp, index_file, prefix, 1, s);
 		s->use_color = saved_color_setting;
-		string_list_clear(&s->change, 1);
+		string_list_clear_func(&s->change, change_data_free);
 	} else {
 		struct object_id oid;
 		const char *parent = "HEAD";
diff --git a/t/t7500-commit-template-squash-signoff.sh b/t/t7500-commit-template-squash-signoff.sh
index 4dca8d97a77..379d3ed3413 100755
--- a/t/t7500-commit-template-squash-signoff.sh
+++ b/t/t7500-commit-template-squash-signoff.sh
@@ -7,6 +7,7 @@ test_description='git commit
 
 Tests for template, signoff, squash and -F functions.'
 
+TEST_PASSES_SANITIZE_LEAK=true
 . ./test-lib.sh
 
 . "$TEST_DIRECTORY"/lib-rebase.sh
-- 
2.47.0.229.g8f8d6eee53.dirty


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

* [PATCH v3 10/22] trailer: fix leaking trailer values
  2024-11-05  6:16 ` [PATCH v3 " Patrick Steinhardt
                     ` (8 preceding siblings ...)
  2024-11-05  6:17   ` [PATCH v3 09/22] builtin/commit: fix leaking change data contents Patrick Steinhardt
@ 2024-11-05  6:17   ` Patrick Steinhardt
  2024-11-05  6:17   ` [PATCH v3 11/22] trailer: fix leaking strbufs when formatting trailers Patrick Steinhardt
                     ` (12 subsequent siblings)
  22 siblings, 0 replies; 100+ messages in thread
From: Patrick Steinhardt @ 2024-11-05  6:17 UTC (permalink / raw)
  To: git; +Cc: Taylor Blau, Toon Claes, Kristoffer Haugsbakk, Justin Tobler

Fix leaking trailer values when replacing the value with a command or
when the token value is empty.

This leak is exposed by t7513, but plugging it does not make the whole
test suite pass.

Signed-off-by: Patrick Steinhardt <ps@pks.im>
---
 trailer.c | 10 ++++++++--
 1 file changed, 8 insertions(+), 2 deletions(-)

diff --git a/trailer.c b/trailer.c
index 682d74505bf..6bafe92b326 100644
--- a/trailer.c
+++ b/trailer.c
@@ -249,7 +249,9 @@ static char *apply_command(struct conf_info *conf, const char *arg)
 static void apply_item_command(struct trailer_item *in_tok, struct arg_item *arg_tok)
 {
 	if (arg_tok->conf.command || arg_tok->conf.cmd) {
-		const char *arg;
+		char *value_to_free = NULL;
+		char *arg;
+
 		if (arg_tok->value && arg_tok->value[0]) {
 			arg = arg_tok->value;
 		} else {
@@ -257,9 +259,13 @@ static void apply_item_command(struct trailer_item *in_tok, struct arg_item *arg
 				arg = xstrdup(in_tok->value);
 			else
 				arg = xstrdup("");
+			value_to_free = arg_tok->value;
 		}
+
 		arg_tok->value = apply_command(&arg_tok->conf, arg);
-		free((char *)arg);
+
+		free(value_to_free);
+		free(arg);
 	}
 }
 
-- 
2.47.0.229.g8f8d6eee53.dirty


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

* [PATCH v3 11/22] trailer: fix leaking strbufs when formatting trailers
  2024-11-05  6:16 ` [PATCH v3 " Patrick Steinhardt
                     ` (9 preceding siblings ...)
  2024-11-05  6:17   ` [PATCH v3 10/22] trailer: fix leaking trailer values Patrick Steinhardt
@ 2024-11-05  6:17   ` Patrick Steinhardt
  2024-11-05  6:17   ` [PATCH v3 12/22] builtin/commit: fix leaking cleanup config Patrick Steinhardt
                     ` (11 subsequent siblings)
  22 siblings, 0 replies; 100+ messages in thread
From: Patrick Steinhardt @ 2024-11-05  6:17 UTC (permalink / raw)
  To: git; +Cc: Taylor Blau, Toon Claes, Kristoffer Haugsbakk, Justin Tobler

When formatting trailer lines we iterate through each of the trailers
and munge their respective token/value pairs according to the trailer
options. When formatting a trailer that has its `item->token` pointer
set we perform the munging in two local buffers. In the case where we
figure out that the value is empty and `trim_empty` is set we just skip
over the trailer item. But the buffers are local to the loop and we
don't release their contents, leading to a memory leak.

Plug this leak by lifting the buffers outside of the loop and releasing
them on function return. This fixes the memory leaks, but also optimizes
the loop as we don't have to reallocate the buffers on every single
iteration.

Signed-off-by: Patrick Steinhardt <ps@pks.im>
---
 t/t7513-interpret-trailers.sh |  1 +
 trailer.c                     | 12 +++++++-----
 2 files changed, 8 insertions(+), 5 deletions(-)

diff --git a/t/t7513-interpret-trailers.sh b/t/t7513-interpret-trailers.sh
index 0f7d8938d98..38d6ccaa001 100755
--- a/t/t7513-interpret-trailers.sh
+++ b/t/t7513-interpret-trailers.sh
@@ -5,6 +5,7 @@
 
 test_description='git interpret-trailers'
 
+TEST_PASSES_SANITIZE_LEAK=true
 . ./test-lib.sh
 
 # When we want one trailing space at the end of each line, let's use sed
diff --git a/trailer.c b/trailer.c
index 6bafe92b326..8ba350404d4 100644
--- a/trailer.c
+++ b/trailer.c
@@ -1111,6 +1111,8 @@ void format_trailers(const struct process_trailer_options *opts,
 		     struct list_head *trailers,
 		     struct strbuf *out)
 {
+	struct strbuf tok = STRBUF_INIT;
+	struct strbuf val = STRBUF_INIT;
 	size_t origlen = out->len;
 	struct list_head *pos;
 	struct trailer_item *item;
@@ -1118,9 +1120,9 @@ void format_trailers(const struct process_trailer_options *opts,
 	list_for_each(pos, trailers) {
 		item = list_entry(pos, struct trailer_item, list);
 		if (item->token) {
-			struct strbuf tok = STRBUF_INIT;
-			struct strbuf val = STRBUF_INIT;
+			strbuf_reset(&tok);
 			strbuf_addstr(&tok, item->token);
+			strbuf_reset(&val);
 			strbuf_addstr(&val, item->value);
 
 			/*
@@ -1151,9 +1153,6 @@ void format_trailers(const struct process_trailer_options *opts,
 				if (!opts->separator)
 					strbuf_addch(out, '\n');
 			}
-			strbuf_release(&tok);
-			strbuf_release(&val);
-
 		} else if (!opts->only_trailers) {
 			if (opts->separator && out->len != origlen) {
 				strbuf_addbuf(out, opts->separator);
@@ -1165,6 +1164,9 @@ void format_trailers(const struct process_trailer_options *opts,
 				strbuf_addch(out, '\n');
 		}
 	}
+
+	strbuf_release(&tok);
+	strbuf_release(&val);
 }
 
 void format_trailers_from_commit(const struct process_trailer_options *opts,
-- 
2.47.0.229.g8f8d6eee53.dirty


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

* [PATCH v3 12/22] builtin/commit: fix leaking cleanup config
  2024-11-05  6:16 ` [PATCH v3 " Patrick Steinhardt
                     ` (10 preceding siblings ...)
  2024-11-05  6:17   ` [PATCH v3 11/22] trailer: fix leaking strbufs when formatting trailers Patrick Steinhardt
@ 2024-11-05  6:17   ` Patrick Steinhardt
  2024-11-05  6:17   ` [PATCH v3 13/22] transport-helper: fix leaking import/export marks Patrick Steinhardt
                     ` (10 subsequent siblings)
  22 siblings, 0 replies; 100+ messages in thread
From: Patrick Steinhardt @ 2024-11-05  6:17 UTC (permalink / raw)
  To: git; +Cc: Taylor Blau, Toon Claes, Kristoffer Haugsbakk, Justin Tobler

The cleanup string set by the config is leaking when it is being
overridden by an option. Fix this by tracking these via two separate
variables such that we can free the old value.

Signed-off-by: Patrick Steinhardt <ps@pks.im>
---
 builtin/commit.c            | 17 ++++++++++++-----
 t/t7502-commit-porcelain.sh |  1 +
 2 files changed, 13 insertions(+), 5 deletions(-)

diff --git a/builtin/commit.c b/builtin/commit.c
index 18a55bd1b91..71d674138c9 100644
--- a/builtin/commit.c
+++ b/builtin/commit.c
@@ -135,7 +135,7 @@ static struct strvec trailer_args = STRVEC_INIT;
  * is specified explicitly.
  */
 static enum commit_msg_cleanup_mode cleanup_mode;
-static char *cleanup_arg;
+static char *cleanup_config;
 
 static enum commit_whence whence;
 static int use_editor = 1, include_status = 1;
@@ -1387,8 +1387,6 @@ static int parse_and_validate_options(int argc, const char *argv[],
 	if (0 <= edit_flag)
 		use_editor = edit_flag;
 
-	cleanup_mode = get_cleanup_mode(cleanup_arg, use_editor);
-
 	handle_untracked_files_arg(s);
 
 	if (all && argc > 0)
@@ -1636,8 +1634,10 @@ static int git_commit_config(const char *k, const char *v,
 		include_status = git_config_bool(k, v);
 		return 0;
 	}
-	if (!strcmp(k, "commit.cleanup"))
-		return git_config_string(&cleanup_arg, k, v);
+	if (!strcmp(k, "commit.cleanup")) {
+		FREE_AND_NULL(cleanup_config);
+		return git_config_string(&cleanup_config, k, v);
+	}
 	if (!strcmp(k, "commit.gpgsign")) {
 		sign_commit = git_config_bool(k, v) ? "" : NULL;
 		return 0;
@@ -1658,6 +1658,7 @@ int cmd_commit(int argc,
 	       struct repository *repo UNUSED)
 {
 	static struct wt_status s;
+	static const char *cleanup_arg = NULL;
 	static struct option builtin_commit_options[] = {
 		OPT__QUIET(&quiet, N_("suppress summary after successful commit")),
 		OPT__VERBOSE(&verbose, N_("show diff in commit message template")),
@@ -1757,6 +1758,12 @@ int cmd_commit(int argc,
 	if (verbose == -1)
 		verbose = (config_commit_verbose < 0) ? 0 : config_commit_verbose;
 
+	if (cleanup_arg) {
+		free(cleanup_config);
+		cleanup_config = xstrdup(cleanup_arg);
+	}
+	cleanup_mode = get_cleanup_mode(cleanup_config, use_editor);
+
 	if (dry_run)
 		return dry_run_commit(argv, prefix, current_head, &s);
 	index_file = prepare_index(argv, prefix, current_head, 0);
diff --git a/t/t7502-commit-porcelain.sh b/t/t7502-commit-porcelain.sh
index b37e2018a74..84f1ff52b67 100755
--- a/t/t7502-commit-porcelain.sh
+++ b/t/t7502-commit-porcelain.sh
@@ -5,6 +5,7 @@ test_description='git commit porcelain-ish'
 GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
 export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
 
+TEST_PASSES_SANITIZE_LEAK=true
 . ./test-lib.sh
 
 commit_msg_is () {
-- 
2.47.0.229.g8f8d6eee53.dirty


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

* [PATCH v3 13/22] transport-helper: fix leaking import/export marks
  2024-11-05  6:16 ` [PATCH v3 " Patrick Steinhardt
                     ` (11 preceding siblings ...)
  2024-11-05  6:17   ` [PATCH v3 12/22] builtin/commit: fix leaking cleanup config Patrick Steinhardt
@ 2024-11-05  6:17   ` Patrick Steinhardt
  2024-11-05  6:17   ` [PATCH v3 14/22] builtin/tag: fix leaking key ID on failure to sign Patrick Steinhardt
                     ` (9 subsequent siblings)
  22 siblings, 0 replies; 100+ messages in thread
From: Patrick Steinhardt @ 2024-11-05  6:17 UTC (permalink / raw)
  To: git; +Cc: Taylor Blau, Toon Claes, Kristoffer Haugsbakk, Justin Tobler

Fix leaking import and export marks for transport helpers.

Signed-off-by: Patrick Steinhardt <ps@pks.im>
---
 t/t5801-remote-helpers.sh | 1 +
 transport-helper.c        | 2 ++
 2 files changed, 3 insertions(+)

diff --git a/t/t5801-remote-helpers.sh b/t/t5801-remote-helpers.sh
index d21877150ed..d4882288a30 100755
--- a/t/t5801-remote-helpers.sh
+++ b/t/t5801-remote-helpers.sh
@@ -8,6 +8,7 @@ test_description='Test remote-helper import and export commands'
 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/transport-helper.c b/transport-helper.c
index 013ec79dc9c..bc27653cdee 100644
--- a/transport-helper.c
+++ b/transport-helper.c
@@ -399,6 +399,8 @@ static int release_helper(struct transport *transport)
 	int res = 0;
 	struct helper_data *data = transport->data;
 	refspec_clear(&data->rs);
+	free(data->import_marks);
+	free(data->export_marks);
 	res = disconnect_helper(transport);
 	free(transport->data);
 	return res;
-- 
2.47.0.229.g8f8d6eee53.dirty


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

* [PATCH v3 14/22] builtin/tag: fix leaking key ID on failure to sign
  2024-11-05  6:16 ` [PATCH v3 " Patrick Steinhardt
                     ` (12 preceding siblings ...)
  2024-11-05  6:17   ` [PATCH v3 13/22] transport-helper: fix leaking import/export marks Patrick Steinhardt
@ 2024-11-05  6:17   ` Patrick Steinhardt
  2024-11-05  6:17   ` [PATCH v3 15/22] combine-diff: fix leaking lost lines Patrick Steinhardt
                     ` (8 subsequent siblings)
  22 siblings, 0 replies; 100+ messages in thread
From: Patrick Steinhardt @ 2024-11-05  6:17 UTC (permalink / raw)
  To: git; +Cc: Taylor Blau, Toon Claes, Kristoffer Haugsbakk, Justin Tobler

We do not free the key ID when signing a tag fails. Do so by using
the common exit path.

Signed-off-by: Patrick Steinhardt <ps@pks.im>
---
 builtin/tag.c  | 2 +-
 t/t7004-tag.sh | 1 +
 2 files changed, 2 insertions(+), 1 deletion(-)

diff --git a/builtin/tag.c b/builtin/tag.c
index 93d10d59157..c37c0a68fda 100644
--- a/builtin/tag.c
+++ b/builtin/tag.c
@@ -164,7 +164,7 @@ static int do_sign(struct strbuf *buffer, struct object_id **compat_oid,
 	int ret = -1;
 
 	if (sign_buffer(buffer, &sig, keyid))
-		return -1;
+		goto out;
 
 	if (compat) {
 		const struct git_hash_algo *algo = the_repository->hash_algo;
diff --git a/t/t7004-tag.sh b/t/t7004-tag.sh
index b1316e62f46..42b3327e69b 100755
--- a/t/t7004-tag.sh
+++ b/t/t7004-tag.sh
@@ -10,6 +10,7 @@ Tests for operations with tags.'
 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
 . "$TEST_DIRECTORY"/lib-terminal.sh
-- 
2.47.0.229.g8f8d6eee53.dirty


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

* [PATCH v3 15/22] combine-diff: fix leaking lost lines
  2024-11-05  6:16 ` [PATCH v3 " Patrick Steinhardt
                     ` (13 preceding siblings ...)
  2024-11-05  6:17   ` [PATCH v3 14/22] builtin/tag: fix leaking key ID on failure to sign Patrick Steinhardt
@ 2024-11-05  6:17   ` Patrick Steinhardt
  2024-11-05  6:17   ` [PATCH v3 16/22] dir: release untracked cache data Patrick Steinhardt
                     ` (7 subsequent siblings)
  22 siblings, 0 replies; 100+ messages in thread
From: Patrick Steinhardt @ 2024-11-05  6:17 UTC (permalink / raw)
  To: git; +Cc: Taylor Blau, Toon Claes, Kristoffer Haugsbakk, Justin Tobler

The `cnt` variable tracks the number of lines in a patch diff. It can
happen though that there are no newlines, in which case we'd still end
up allocating our array of `sline`s. In fact, we always allocate it with
`cnt + 2` entries: one extra entry for the deletion hunk at the end, and
another entry that we don't seem to ever populate at all but acts as a
kind of sentinel value.

When we loop through the array to clear it at the end of this function
we only loop until `lno < cnt`, and thus we may not end up releasing
whatever the two extra `sline`s contain. While that shouldn't matter for
the sentinel value, it does matter for the extra deletion hunk sline.
Regardless of that, plug this memory leak by releasing both extra
entries, which makes the logic a bit easier to reason about.

While at it, fix the formatting of a local comment, which incidentally
also provides the necessary context for why we overallocate the `sline`
array.

Signed-off-by: Patrick Steinhardt <ps@pks.im>
---
 combine-diff.c           | 5 +++--
 t/t4038-diff-combined.sh | 1 +
 2 files changed, 4 insertions(+), 2 deletions(-)

diff --git a/combine-diff.c b/combine-diff.c
index f6b624dc288..33d0ed70975 100644
--- a/combine-diff.c
+++ b/combine-diff.c
@@ -1185,7 +1185,8 @@ static void show_patch_diff(struct combine_diff_path *elem, int num_parent,
 	result_file.ptr = result;
 	result_file.size = result_size;
 
-	/* Even p_lno[cnt+1] is valid -- that is for the end line number
+	/*
+	 * Even p_lno[cnt+1] is valid -- that is for the end line number
 	 * for deletion hunk at the end.
 	 */
 	CALLOC_ARRAY(sline[0].p_lno, st_mult(st_add(cnt, 2), num_parent));
@@ -1220,7 +1221,7 @@ static void show_patch_diff(struct combine_diff_path *elem, int num_parent,
 	}
 	free(result);
 
-	for (lno = 0; lno < cnt; lno++) {
+	for (lno = 0; lno < cnt + 2; lno++) {
 		if (sline[lno].lost) {
 			struct lline *ll = sline[lno].lost;
 			while (ll) {
diff --git a/t/t4038-diff-combined.sh b/t/t4038-diff-combined.sh
index 2ce26e585c9..00190802d83 100755
--- a/t/t4038-diff-combined.sh
+++ b/t/t4038-diff-combined.sh
@@ -5,6 +5,7 @@ test_description='combined diff'
 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-diff.sh
 
-- 
2.47.0.229.g8f8d6eee53.dirty


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

* [PATCH v3 16/22] dir: release untracked cache data
  2024-11-05  6:16 ` [PATCH v3 " Patrick Steinhardt
                     ` (14 preceding siblings ...)
  2024-11-05  6:17   ` [PATCH v3 15/22] combine-diff: fix leaking lost lines Patrick Steinhardt
@ 2024-11-05  6:17   ` Patrick Steinhardt
  2024-11-05  6:17   ` [PATCH v3 17/22] sparse-index: correctly free EWAH contents Patrick Steinhardt
                     ` (6 subsequent siblings)
  22 siblings, 0 replies; 100+ messages in thread
From: Patrick Steinhardt @ 2024-11-05  6:17 UTC (permalink / raw)
  To: git; +Cc: Taylor Blau, Toon Claes, Kristoffer Haugsbakk, Justin Tobler

There are several cases where we invalidate untracked cache directory
entries where we do not free the underlying data, but reset the number
of entries. This causes us to leak memory because `free_untracked()`
will not iterate over any potential entries which we still had in the
array.

Fix this issue by freeing old entries. The leak is exposed by t7519, but
plugging it alone does not make the whole test suite pass.

Signed-off-by: Patrick Steinhardt <ps@pks.im>
---
 dir.c | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/dir.c b/dir.c
index e3ddd5b5296..cb9782fa11f 100644
--- a/dir.c
+++ b/dir.c
@@ -1056,6 +1056,8 @@ static void do_invalidate_gitignore(struct untracked_cache_dir *dir)
 {
 	int i;
 	dir->valid = 0;
+	for (size_t i = 0; i < dir->untracked_nr; i++)
+		free(dir->untracked[i]);
 	dir->untracked_nr = 0;
 	for (i = 0; i < dir->dirs_nr; i++)
 		do_invalidate_gitignore(dir->dirs[i]);
@@ -1083,6 +1085,8 @@ static void invalidate_directory(struct untracked_cache *uc,
 		uc->dir_invalidated++;
 
 	dir->valid = 0;
+	for (size_t i = 0; i < dir->untracked_nr; i++)
+		free(dir->untracked[i]);
 	dir->untracked_nr = 0;
 	for (i = 0; i < dir->dirs_nr; i++)
 		dir->dirs[i]->recurse = 0;
@@ -3573,6 +3577,8 @@ static void write_one_dir(struct untracked_cache_dir *untracked,
 	 * for safety..
 	 */
 	if (!untracked->valid) {
+		for (size_t i = 0; i < untracked->untracked_nr; i++)
+			free(untracked->untracked[i]);
 		untracked->untracked_nr = 0;
 		untracked->check_only = 0;
 	}
@@ -3905,6 +3911,8 @@ static void invalidate_one_directory(struct untracked_cache *uc,
 {
 	uc->dir_invalidated++;
 	ucd->valid = 0;
+	for (size_t i = 0; i < ucd->untracked_nr; i++)
+		free(ucd->untracked[i]);
 	ucd->untracked_nr = 0;
 }
 
-- 
2.47.0.229.g8f8d6eee53.dirty


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

* [PATCH v3 17/22] sparse-index: correctly free EWAH contents
  2024-11-05  6:16 ` [PATCH v3 " Patrick Steinhardt
                     ` (15 preceding siblings ...)
  2024-11-05  6:17   ` [PATCH v3 16/22] dir: release untracked cache data Patrick Steinhardt
@ 2024-11-05  6:17   ` Patrick Steinhardt
  2024-11-05  6:17   ` [PATCH v3 18/22] t/helper: stop re-initialization of `the_repository` Patrick Steinhardt
                     ` (5 subsequent siblings)
  22 siblings, 0 replies; 100+ messages in thread
From: Patrick Steinhardt @ 2024-11-05  6:17 UTC (permalink / raw)
  To: git; +Cc: Taylor Blau, Toon Claes, Kristoffer Haugsbakk, Justin Tobler

While we free the `fsmonitor_dirty` member of `struct index_state`, we
do not free the contents of that EWAH. Do so by using `ewah_free()`
instead of `FREE_AND_NULL()`.

This leak is exposed by t7519, but plugging it alone does not make the
test suite pass.

Signed-off-by: Patrick Steinhardt <ps@pks.im>
---
 sparse-index.c | 7 +++++--
 1 file changed, 5 insertions(+), 2 deletions(-)

diff --git a/sparse-index.c b/sparse-index.c
index 3d7f2164e25..2107840bfc5 100644
--- a/sparse-index.c
+++ b/sparse-index.c
@@ -2,6 +2,7 @@
 
 #include "git-compat-util.h"
 #include "environment.h"
+#include "ewah/ewok.h"
 #include "gettext.h"
 #include "name-hash.h"
 #include "read-cache-ll.h"
@@ -242,7 +243,8 @@ int convert_to_sparse(struct index_state *istate, int flags)
 	cache_tree_update(istate, 0);
 
 	istate->fsmonitor_has_run_once = 0;
-	FREE_AND_NULL(istate->fsmonitor_dirty);
+	ewah_free(istate->fsmonitor_dirty);
+	istate->fsmonitor_dirty = NULL;
 	FREE_AND_NULL(istate->fsmonitor_last_update);
 
 	istate->sparse_index = INDEX_COLLAPSED;
@@ -438,7 +440,8 @@ void expand_index(struct index_state *istate, struct pattern_list *pl)
 	istate->cache_nr = full->cache_nr;
 	istate->cache_alloc = full->cache_alloc;
 	istate->fsmonitor_has_run_once = 0;
-	FREE_AND_NULL(istate->fsmonitor_dirty);
+	ewah_free(istate->fsmonitor_dirty);
+	istate->fsmonitor_dirty = NULL;
 	FREE_AND_NULL(istate->fsmonitor_last_update);
 
 	strbuf_release(&base);
-- 
2.47.0.229.g8f8d6eee53.dirty


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

* [PATCH v3 18/22] t/helper: stop re-initialization of `the_repository`
  2024-11-05  6:16 ` [PATCH v3 " Patrick Steinhardt
                     ` (16 preceding siblings ...)
  2024-11-05  6:17   ` [PATCH v3 17/22] sparse-index: correctly free EWAH contents Patrick Steinhardt
@ 2024-11-05  6:17   ` Patrick Steinhardt
  2024-11-05  6:17   ` [PATCH v3 19/22] t/helper: fix leaking buffer in "dump-untracked-cache" Patrick Steinhardt
                     ` (4 subsequent siblings)
  22 siblings, 0 replies; 100+ messages in thread
From: Patrick Steinhardt @ 2024-11-05  6:17 UTC (permalink / raw)
  To: git; +Cc: Taylor Blau, Toon Claes, Kristoffer Haugsbakk, Justin Tobler

While "common-main.c" already initializes `the_repository` for us, we do
so a second time in the "read-cache" test helper. This causes a memory
leak because the old repository's contents isn't released.

Stop calling `initialize_repository()` to plug this leak.

Signed-off-by: Patrick Steinhardt <ps@pks.im>
---
 t/helper/test-read-cache.c  | 2 --
 t/t7519-status-fsmonitor.sh | 1 +
 2 files changed, 1 insertion(+), 2 deletions(-)

diff --git a/t/helper/test-read-cache.c b/t/helper/test-read-cache.c
index d285c656bd3..e277dde8e71 100644
--- a/t/helper/test-read-cache.c
+++ b/t/helper/test-read-cache.c
@@ -11,8 +11,6 @@ int cmd__read_cache(int argc, const char **argv)
 	int i, cnt = 1;
 	const char *name = NULL;
 
-	initialize_repository(the_repository);
-
 	if (argc > 1 && skip_prefix(argv[1], "--print-and-refresh=", &name)) {
 		argc--;
 		argv++;
diff --git a/t/t7519-status-fsmonitor.sh b/t/t7519-status-fsmonitor.sh
index 7ee69ecdd4a..0f88a58a819 100755
--- a/t/t7519-status-fsmonitor.sh
+++ b/t/t7519-status-fsmonitor.sh
@@ -2,6 +2,7 @@
 
 test_description='git status with file system watcher'
 
+TEST_PASSES_SANITIZE_LEAK=true
 . ./test-lib.sh
 
 # Note, after "git reset --hard HEAD" no extensions exist other than 'TREE'
-- 
2.47.0.229.g8f8d6eee53.dirty


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

* [PATCH v3 19/22] t/helper: fix leaking buffer in "dump-untracked-cache"
  2024-11-05  6:16 ` [PATCH v3 " Patrick Steinhardt
                     ` (17 preceding siblings ...)
  2024-11-05  6:17   ` [PATCH v3 18/22] t/helper: stop re-initialization of `the_repository` Patrick Steinhardt
@ 2024-11-05  6:17   ` Patrick Steinhardt
  2024-11-05  6:17   ` [PATCH v3 20/22] dir: fix leak when parsing "status.showUntrackedFiles" Patrick Steinhardt
                     ` (3 subsequent siblings)
  22 siblings, 0 replies; 100+ messages in thread
From: Patrick Steinhardt @ 2024-11-05  6:17 UTC (permalink / raw)
  To: git; +Cc: Taylor Blau, Toon Claes, Kristoffer Haugsbakk, Justin Tobler

We never release the local `struct strbuf base` buffer, thus leaking
memory. Fix this leak.

This leak is exposed by t7063, but plugging it alone does not make the
whole test suite pass.

Signed-off-by: Patrick Steinhardt <ps@pks.im>
---
 t/helper/test-dump-untracked-cache.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/t/helper/test-dump-untracked-cache.c b/t/helper/test-dump-untracked-cache.c
index 4f010d53249..b2e70837a90 100644
--- a/t/helper/test-dump-untracked-cache.c
+++ b/t/helper/test-dump-untracked-cache.c
@@ -68,5 +68,7 @@ int cmd__dump_untracked_cache(int ac UNUSED, const char **av UNUSED)
 	printf("flags %08x\n", uc->dir_flags);
 	if (uc->root)
 		dump(uc->root, &base);
+
+	strbuf_release(&base);
 	return 0;
 }
-- 
2.47.0.229.g8f8d6eee53.dirty


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

* [PATCH v3 20/22] dir: fix leak when parsing "status.showUntrackedFiles"
  2024-11-05  6:16 ` [PATCH v3 " Patrick Steinhardt
                     ` (18 preceding siblings ...)
  2024-11-05  6:17   ` [PATCH v3 19/22] t/helper: fix leaking buffer in "dump-untracked-cache" Patrick Steinhardt
@ 2024-11-05  6:17   ` Patrick Steinhardt
  2024-11-05  6:17   ` [PATCH v3 21/22] builtin/merge: release output buffer after performing merge Patrick Steinhardt
                     ` (2 subsequent siblings)
  22 siblings, 0 replies; 100+ messages in thread
From: Patrick Steinhardt @ 2024-11-05  6:17 UTC (permalink / raw)
  To: git; +Cc: Taylor Blau, Toon Claes, Kristoffer Haugsbakk, Justin Tobler

We use `repo_config_get_string()` to read "status.showUntrackedFiles"
from the config subsystem. This function allocates the result, but we
never free the result after parsing it.

The value never leaves the scope of the calling function, so refactor it
to instead use `repo_config_get_string_tmp()`, which does not hand over
ownership to the caller.

Signed-off-by: Patrick Steinhardt <ps@pks.im>
---
 dir.c                             | 4 ++--
 t/t7063-status-untracked-cache.sh | 1 +
 2 files changed, 3 insertions(+), 2 deletions(-)

diff --git a/dir.c b/dir.c
index cb9782fa11f..7f35a3e3175 100644
--- a/dir.c
+++ b/dir.c
@@ -2872,14 +2872,14 @@ static void set_untracked_ident(struct untracked_cache *uc)
 static unsigned new_untracked_cache_flags(struct index_state *istate)
 {
 	struct repository *repo = istate->repo;
-	char *val;
+	const char *val;
 
 	/*
 	 * This logic is coordinated with the setting of these flags in
 	 * wt-status.c#wt_status_collect_untracked(), and the evaluation
 	 * of the config setting in commit.c#git_status_config()
 	 */
-	if (!repo_config_get_string(repo, "status.showuntrackedfiles", &val) &&
+	if (!repo_config_get_string_tmp(repo, "status.showuntrackedfiles", &val) &&
 	    !strcmp(val, "all"))
 		return 0;
 
diff --git a/t/t7063-status-untracked-cache.sh b/t/t7063-status-untracked-cache.sh
index 8929ef481f9..13fea7931cd 100755
--- a/t/t7063-status-untracked-cache.sh
+++ b/t/t7063-status-untracked-cache.sh
@@ -5,6 +5,7 @@ test_description='test untracked cache'
 GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
 export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
 
+TEST_PASSES_SANITIZE_LEAK=true
 . ./test-lib.sh
 
 # On some filesystems (e.g. FreeBSD's ext2 and ufs) directory mtime
-- 
2.47.0.229.g8f8d6eee53.dirty


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

* [PATCH v3 21/22] builtin/merge: release output buffer after performing merge
  2024-11-05  6:16 ` [PATCH v3 " Patrick Steinhardt
                     ` (19 preceding siblings ...)
  2024-11-05  6:17   ` [PATCH v3 20/22] dir: fix leak when parsing "status.showUntrackedFiles" Patrick Steinhardt
@ 2024-11-05  6:17   ` Patrick Steinhardt
  2024-11-05  6:17   ` [PATCH v3 22/22] list-objects-filter-options: work around reported leak on error Patrick Steinhardt
  2024-11-05  6:51   ` [PATCH v3 00/22] Memory leak fixes (pt.9) Junio C Hamano
  22 siblings, 0 replies; 100+ messages in thread
From: Patrick Steinhardt @ 2024-11-05  6:17 UTC (permalink / raw)
  To: git; +Cc: Taylor Blau, Toon Claes, Kristoffer Haugsbakk, Justin Tobler

The `obuf` member of `struct merge_options` is used to buffer output in
some cases. In order to not discard its allocated memory we only release
its contents in `merge_finalize()` when we're not currently recursing
into a subtree.

This results in some situations where we seemingly do not release the
buffer reliably. We thus have calls to `strbuf_release()` for this
buffer scattered across the codebase. But we're missing one callsite in
git-merge(1), which causes a memory leak.

We should ideally refactor this interface so that callers don't have to
know about any such internals. But for now, paper over the issue by
adding one more `strbuf_release()` call.

Signed-off-by: Patrick Steinhardt <ps@pks.im>
---
 builtin/merge.c                          | 1 +
 t/t6424-merge-unrelated-index-changes.sh | 1 +
 2 files changed, 2 insertions(+)

diff --git a/builtin/merge.c b/builtin/merge.c
index 84d0f3604bc..51038eaca84 100644
--- a/builtin/merge.c
+++ b/builtin/merge.c
@@ -754,6 +754,7 @@ static int try_merge_strategy(const char *strategy, struct commit_list *common,
 			clean = merge_recursive(&o, head, remoteheads->item,
 						reversed, &result);
 		free_commit_list(reversed);
+		strbuf_release(&o.obuf);
 
 		if (clean < 0) {
 			rollback_lock_file(&lock);
diff --git a/t/t6424-merge-unrelated-index-changes.sh b/t/t6424-merge-unrelated-index-changes.sh
index 7677c5f08d0..a7ea8acb845 100755
--- a/t/t6424-merge-unrelated-index-changes.sh
+++ b/t/t6424-merge-unrelated-index-changes.sh
@@ -2,6 +2,7 @@
 
 test_description="merges with unrelated index changes"
 
+TEST_PASSES_SANITIZE_LEAK=true
 . ./test-lib.sh
 
 # Testcase for some simple merges
-- 
2.47.0.229.g8f8d6eee53.dirty


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

* [PATCH v3 22/22] list-objects-filter-options: work around reported leak on error
  2024-11-05  6:16 ` [PATCH v3 " Patrick Steinhardt
                     ` (20 preceding siblings ...)
  2024-11-05  6:17   ` [PATCH v3 21/22] builtin/merge: release output buffer after performing merge Patrick Steinhardt
@ 2024-11-05  6:17   ` Patrick Steinhardt
  2024-11-05  6:51   ` [PATCH v3 00/22] Memory leak fixes (pt.9) Junio C Hamano
  22 siblings, 0 replies; 100+ messages in thread
From: Patrick Steinhardt @ 2024-11-05  6:17 UTC (permalink / raw)
  To: git; +Cc: Taylor Blau, Toon Claes, Kristoffer Haugsbakk, Justin Tobler

This one is a little bit more curious. In t6112, we have a test that
exercises the `git rev-list --filter` option with invalid filters. We
execute git-rev-list(1) via `test_must_fail`, which means that we check
for leaks even though Git exits with an error code. This causes the
following leak:

    Direct leak of 27 byte(s) in 1 object(s) allocated from:
        #0 0x5555555e6946 in realloc.part.0 lsan_interceptors.cpp.o
        #1 0x5555558fb4b6 in xrealloc wrapper.c:137:8
        #2 0x5555558b6e06 in strbuf_grow strbuf.c:112:2
        #3 0x5555558b7550 in strbuf_add strbuf.c:311:2
        #4 0x5555557c1a88 in strbuf_addstr strbuf.h:310:2
        #5 0x5555557c1d4c in parse_list_objects_filter list-objects-filter-options.c:261:3
        #6 0x555555885ead in handle_revision_pseudo_opt revision.c:2899:3
        #7 0x555555884e20 in setup_revisions revision.c:3014:11
        #8 0x5555556c4b42 in cmd_rev_list builtin/rev-list.c:588:9
        #9 0x5555555ec5e3 in run_builtin git.c:483:11
        #10 0x5555555eb1e4 in handle_builtin git.c:749:13
        #11 0x5555555ec001 in run_argv git.c:819:4
        #12 0x5555555eaf94 in cmd_main git.c:954:19
        #13 0x5555556fd569 in main common-main.c:64:11
        #14 0x7ffff7ca714d in __libc_start_call_main (.../lib/libc.so.6+0x2a14d)
        #15 0x7ffff7ca7208 in __libc_start_main@GLIBC_2.2.5 (.../libc.so.6+0x2a208)
        #16 0x5555555ad064 in _start (git+0x59064)

This leak is valid, as we call `die()` and do not clean up the memory at
all. But what's curious is that this is the only leak reported, because
we don't clean up any other allocated memory, either, and I have no idea
why the leak sanitizer treats this buffer specially.

In any case, we can work around the leak by shuffling things around a
bit. Instead of calling `gently_parse_list_objects_filter()` and dying
after we have modified the filter spec, we simply do so beforehand. Like
this we don't allocate the buffer in the error case, which makes the
reported leak go away.

It's not pretty, but it manages to make t6112 leak free.

Signed-off-by: Patrick Steinhardt <ps@pks.im>
---
 list-objects-filter-options.c       | 17 +++++++----------
 t/t6112-rev-list-filters-objects.sh |  1 +
 2 files changed, 8 insertions(+), 10 deletions(-)

diff --git a/list-objects-filter-options.c b/list-objects-filter-options.c
index 00611107d20..fa72e81e4ad 100644
--- a/list-objects-filter-options.c
+++ b/list-objects-filter-options.c
@@ -252,16 +252,14 @@ void parse_list_objects_filter(
 	const char *arg)
 {
 	struct strbuf errbuf = STRBUF_INIT;
-	int parse_error;
 
 	if (!filter_options->filter_spec.buf)
 		BUG("filter_options not properly initialized");
 
 	if (!filter_options->choice) {
+		if (gently_parse_list_objects_filter(filter_options, arg, &errbuf))
+			die("%s", errbuf.buf);
 		strbuf_addstr(&filter_options->filter_spec, arg);
-
-		parse_error = gently_parse_list_objects_filter(
-			filter_options, arg, &errbuf);
 	} else {
 		struct list_objects_filter_options *sub;
 
@@ -271,18 +269,17 @@ void parse_list_objects_filter(
 		 */
 		transform_to_combine_type(filter_options);
 
-		strbuf_addch(&filter_options->filter_spec, '+');
-		filter_spec_append_urlencode(filter_options, arg);
 		ALLOC_GROW_BY(filter_options->sub, filter_options->sub_nr, 1,
 			      filter_options->sub_alloc);
 		sub = &filter_options->sub[filter_options->sub_nr - 1];
 
 		list_objects_filter_init(sub);
-		parse_error = gently_parse_list_objects_filter(sub, arg,
-							       &errbuf);
+		if (gently_parse_list_objects_filter(sub, arg, &errbuf))
+			die("%s", errbuf.buf);
+
+		strbuf_addch(&filter_options->filter_spec, '+');
+		filter_spec_append_urlencode(filter_options, arg);
 	}
-	if (parse_error)
-		die("%s", errbuf.buf);
 }
 
 int opt_parse_list_objects_filter(const struct option *opt,
diff --git a/t/t6112-rev-list-filters-objects.sh b/t/t6112-rev-list-filters-objects.sh
index 0387f35a326..71e38491fa8 100755
--- a/t/t6112-rev-list-filters-objects.sh
+++ b/t/t6112-rev-list-filters-objects.sh
@@ -5,6 +5,7 @@ test_description='git rev-list 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 the blob:none filter.
-- 
2.47.0.229.g8f8d6eee53.dirty


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

* Re: [PATCH v3 00/22] Memory leak fixes (pt.9)
  2024-11-05  6:16 ` [PATCH v3 " Patrick Steinhardt
                     ` (21 preceding siblings ...)
  2024-11-05  6:17   ` [PATCH v3 22/22] list-objects-filter-options: work around reported leak on error Patrick Steinhardt
@ 2024-11-05  6:51   ` Junio C Hamano
  2024-11-05  6:52     ` Patrick Steinhardt
  22 siblings, 1 reply; 100+ messages in thread
From: Junio C Hamano @ 2024-11-05  6:51 UTC (permalink / raw)
  To: Patrick Steinhardt
  Cc: git, Taylor Blau, Toon Claes, Kristoffer Haugsbakk, Justin Tobler

Patrick Steinhardt <ps@pks.im> writes:

> Changes compared to v2:
>
>   - Remove an unnecessary cast.
>
>   - Fix a duplicate newline.
>
>   - Polish a couple of commit messages.
>
> Thanks!

I spot checked the ones that did not change from v2 and the ones I
checked at all looked sensible.  Perhaps this is now ready for
'next'?

Thanks.

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

* Re: [PATCH v3 00/22] Memory leak fixes (pt.9)
  2024-11-05  6:51   ` [PATCH v3 00/22] Memory leak fixes (pt.9) Junio C Hamano
@ 2024-11-05  6:52     ` Patrick Steinhardt
  2024-11-05 15:27       ` Justin Tobler
  0 siblings, 1 reply; 100+ messages in thread
From: Patrick Steinhardt @ 2024-11-05  6:52 UTC (permalink / raw)
  To: Junio C Hamano
  Cc: git, Taylor Blau, Toon Claes, Kristoffer Haugsbakk, Justin Tobler

On Mon, Nov 04, 2024 at 10:51:10PM -0800, Junio C Hamano wrote:
> Patrick Steinhardt <ps@pks.im> writes:
> 
> > Changes compared to v2:
> >
> >   - Remove an unnecessary cast.
> >
> >   - Fix a duplicate newline.
> >
> >   - Polish a couple of commit messages.
> >
> > Thanks!
> 
> I spot checked the ones that did not change from v2 and the ones I
> checked at all looked sensible.  Perhaps this is now ready for
> 'next'?

From my point of view it should be ready, yes.

Patrick

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

* Re: [PATCH v3 00/22] Memory leak fixes (pt.9)
  2024-11-05  6:52     ` Patrick Steinhardt
@ 2024-11-05 15:27       ` Justin Tobler
  0 siblings, 0 replies; 100+ messages in thread
From: Justin Tobler @ 2024-11-05 15:27 UTC (permalink / raw)
  To: Patrick Steinhardt
  Cc: Junio C Hamano, git, Taylor Blau, Toon Claes,
	Kristoffer Haugsbakk

On 24/11/05 07:52AM, Patrick Steinhardt wrote:
> On Mon, Nov 04, 2024 at 10:51:10PM -0800, Junio C Hamano wrote:
> > Patrick Steinhardt <ps@pks.im> writes:
> > 
> > > Changes compared to v2:
> > >
> > >   - Remove an unnecessary cast.
> > >
> > >   - Fix a duplicate newline.
> > >
> > >   - Polish a couple of commit messages.
> > >
> > > Thanks!
> > 
> > I spot checked the ones that did not change from v2 and the ones I
> > checked at all looked sensible.  Perhaps this is now ready for
> > 'next'?
> 
> From my point of view it should be ready, yes.

From looking at the range-diff, this version looks good to me. :)

-Justin

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

end of thread, other threads:[~2024-11-05 15:28 UTC | newest]

Thread overview: 100+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2024-10-11  5:32 [PATCH 00/21] Memory leak fixes (pt.9) Patrick Steinhardt
2024-10-11  5:32 ` [PATCH 01/21] builtin/ls-remote: plug leaking server options Patrick Steinhardt
2024-10-11  5:32 ` [PATCH 02/21] t/helper: fix leaks in "reach" test tool Patrick Steinhardt
2024-10-11  5:32 ` [PATCH 03/21] grep: fix leak in `grep_splice_or()` Patrick Steinhardt
2024-10-11  5:32 ` [PATCH 04/21] builtin/grep: fix leak with `--max-count=0` Patrick Steinhardt
2024-10-11  5:32 ` [PATCH 05/21] revision: fix leaking bloom filters Patrick Steinhardt
2024-10-11  5:32 ` [PATCH 06/21] diff-lib: fix leaking diffopts in `do_diff_cache()` Patrick Steinhardt
2024-10-21  9:46   ` Kristoffer Haugsbakk
2024-10-11  5:32 ` [PATCH 07/21] pretty: clear signature check Patrick Steinhardt
2024-10-18 12:02   ` Toon Claes
2024-10-21  8:44     ` Patrick Steinhardt
2024-10-11  5:32 ` [PATCH 08/21] upload-pack: fix leaking URI protocols Patrick Steinhardt
2024-10-11  5:32 ` [PATCH 09/21] builtin/commit: fix leaking change data contents Patrick Steinhardt
2024-10-11  5:32 ` [PATCH 10/21] trailer: fix leaking trailer values Patrick Steinhardt
2024-10-18 12:03   ` Toon Claes
2024-10-21  8:44     ` Patrick Steinhardt
2024-10-11  5:32 ` [PATCH 11/21] builtin/commit: fix leaking cleanup config Patrick Steinhardt
2024-10-11  5:32 ` [PATCH 12/21] transport-helper: fix leaking import/export marks Patrick Steinhardt
2024-10-11  5:32 ` [PATCH 13/21] builtin/tag: fix leaking key ID on failure to sign Patrick Steinhardt
2024-10-11  5:32 ` [PATCH 14/21] combine-diff: fix leaking lost lines Patrick Steinhardt
2024-10-11  5:32 ` [PATCH 15/21] dir: release untracked cache data Patrick Steinhardt
2024-10-11  5:32 ` [PATCH 16/21] sparse-index: correctly free EWAH contents Patrick Steinhardt
2024-10-11  5:32 ` [PATCH 17/21] t/helper: stop re-initialization of `the_repository` Patrick Steinhardt
2024-10-11  5:33 ` [PATCH 18/21] t/helper: fix leaking buffer in "dump-untracked-cache" Patrick Steinhardt
2024-10-11  5:33 ` [PATCH 19/21] dir: fix leak when parsing "status.showUntrackedFiles" Patrick Steinhardt
2024-10-11  5:33 ` [PATCH 20/21] builtin/merge: release outbut buffer after performing merge Patrick Steinhardt
2024-10-18 12:03   ` Toon Claes
2024-10-21  8:45     ` Patrick Steinhardt
2024-10-11  5:33 ` [PATCH 21/21] list-objects-filter-options: work around reported leak on error Patrick Steinhardt
2024-10-18 12:04   ` Toon Claes
2024-10-21  8:45     ` Patrick Steinhardt
2024-10-18 21:30 ` [PATCH 00/21] Memory leak fixes (pt.9) Taylor Blau
2024-10-21  8:45   ` Patrick Steinhardt
2024-10-21  9:27 ` [PATCH v2 00/22] " Patrick Steinhardt
2024-10-21  9:28   ` [PATCH v2 01/22] builtin/ls-remote: plug leaking server options Patrick Steinhardt
2024-11-04 22:10     ` Justin Tobler
2024-11-04 22:18       ` Kristoffer Haugsbakk
2024-10-21  9:28   ` [PATCH v2 02/22] t/helper: fix leaks in "reach" test tool Patrick Steinhardt
2024-10-21  9:28   ` [PATCH v2 03/22] grep: fix leak in `grep_splice_or()` Patrick Steinhardt
2024-10-21  9:42     ` Kristoffer Haugsbakk
2024-10-21  9:28   ` [PATCH v2 04/22] builtin/grep: fix leak with `--max-count=0` Patrick Steinhardt
2024-10-21  9:28   ` [PATCH v2 05/22] revision: fix leaking bloom filters Patrick Steinhardt
2024-10-21  9:28   ` [PATCH v2 06/22] diff-lib: fix leaking diffopts in `do_diff_cache()` Patrick Steinhardt
2024-10-21  9:28   ` [PATCH v2 07/22] pretty: clear signature check Patrick Steinhardt
2024-11-04 22:15     ` Justin Tobler
2024-10-21  9:28   ` [PATCH v2 08/22] upload-pack: fix leaking URI protocols Patrick Steinhardt
2024-10-21  9:28   ` [PATCH v2 09/22] builtin/commit: fix leaking change data contents Patrick Steinhardt
2024-11-04 22:21     ` Justin Tobler
2024-10-21  9:28   ` [PATCH v2 10/22] trailer: fix leaking trailer values Patrick Steinhardt
2024-11-04 22:25     ` Justin Tobler
2024-11-05  5:54       ` Patrick Steinhardt
2024-10-21  9:28   ` [PATCH v2 11/22] trailer: fix leaking strbufs when formatting trailers Patrick Steinhardt
2024-10-21 20:58     ` Taylor Blau
2024-11-04 22:31     ` Justin Tobler
2024-11-05  5:54       ` Patrick Steinhardt
2024-10-21  9:28   ` [PATCH v2 12/22] builtin/commit: fix leaking cleanup config Patrick Steinhardt
2024-10-21  9:28   ` [PATCH v2 13/22] transport-helper: fix leaking import/export marks Patrick Steinhardt
2024-10-21  9:28   ` [PATCH v2 14/22] builtin/tag: fix leaking key ID on failure to sign Patrick Steinhardt
2024-10-21  9:28   ` [PATCH v2 15/22] combine-diff: fix leaking lost lines Patrick Steinhardt
2024-11-04 22:43     ` Justin Tobler
2024-11-05  5:55       ` Patrick Steinhardt
2024-10-21  9:28   ` [PATCH v2 16/22] dir: release untracked cache data Patrick Steinhardt
2024-10-21  9:28   ` [PATCH v2 17/22] sparse-index: correctly free EWAH contents Patrick Steinhardt
2024-10-21  9:28   ` [PATCH v2 18/22] t/helper: stop re-initialization of `the_repository` Patrick Steinhardt
2024-10-21  9:28   ` [PATCH v2 19/22] t/helper: fix leaking buffer in "dump-untracked-cache" Patrick Steinhardt
2024-10-21  9:29   ` [PATCH v2 20/22] dir: fix leak when parsing "status.showUntrackedFiles" Patrick Steinhardt
2024-10-21  9:29   ` [PATCH v2 21/22] builtin/merge: release outbut buffer after performing merge Patrick Steinhardt
2024-10-21  9:41     ` Kristoffer Haugsbakk
2024-10-21  9:29   ` [PATCH v2 22/22] list-objects-filter-options: work around reported leak on error Patrick Steinhardt
2024-10-21  9:54   ` [PATCH v2 00/22] Memory leak fixes (pt.9) Kristoffer Haugsbakk
2024-10-21 10:36     ` Patrick Steinhardt
2024-10-25  7:49       ` Toon Claes
2024-11-04 22:46   ` Justin Tobler
2024-11-05  5:55     ` Patrick Steinhardt
2024-11-05  6:16 ` [PATCH v3 " Patrick Steinhardt
2024-11-05  6:16   ` [PATCH v3 01/22] builtin/ls-remote: plug leaking server options Patrick Steinhardt
2024-11-05  6:16   ` [PATCH v3 02/22] t/helper: fix leaks in "reach" test tool Patrick Steinhardt
2024-11-05  6:16   ` [PATCH v3 03/22] grep: fix leak in `grep_splice_or()` Patrick Steinhardt
2024-11-05  6:16   ` [PATCH v3 04/22] builtin/grep: fix leak with `--max-count=0` Patrick Steinhardt
2024-11-05  6:16   ` [PATCH v3 05/22] revision: fix leaking bloom filters Patrick Steinhardt
2024-11-05  6:17   ` [PATCH v3 06/22] diff-lib: fix leaking diffopts in `do_diff_cache()` Patrick Steinhardt
2024-11-05  6:17   ` [PATCH v3 07/22] pretty: clear signature check Patrick Steinhardt
2024-11-05  6:17   ` [PATCH v3 08/22] upload-pack: fix leaking URI protocols Patrick Steinhardt
2024-11-05  6:17   ` [PATCH v3 09/22] builtin/commit: fix leaking change data contents Patrick Steinhardt
2024-11-05  6:17   ` [PATCH v3 10/22] trailer: fix leaking trailer values Patrick Steinhardt
2024-11-05  6:17   ` [PATCH v3 11/22] trailer: fix leaking strbufs when formatting trailers Patrick Steinhardt
2024-11-05  6:17   ` [PATCH v3 12/22] builtin/commit: fix leaking cleanup config Patrick Steinhardt
2024-11-05  6:17   ` [PATCH v3 13/22] transport-helper: fix leaking import/export marks Patrick Steinhardt
2024-11-05  6:17   ` [PATCH v3 14/22] builtin/tag: fix leaking key ID on failure to sign Patrick Steinhardt
2024-11-05  6:17   ` [PATCH v3 15/22] combine-diff: fix leaking lost lines Patrick Steinhardt
2024-11-05  6:17   ` [PATCH v3 16/22] dir: release untracked cache data Patrick Steinhardt
2024-11-05  6:17   ` [PATCH v3 17/22] sparse-index: correctly free EWAH contents Patrick Steinhardt
2024-11-05  6:17   ` [PATCH v3 18/22] t/helper: stop re-initialization of `the_repository` Patrick Steinhardt
2024-11-05  6:17   ` [PATCH v3 19/22] t/helper: fix leaking buffer in "dump-untracked-cache" Patrick Steinhardt
2024-11-05  6:17   ` [PATCH v3 20/22] dir: fix leak when parsing "status.showUntrackedFiles" Patrick Steinhardt
2024-11-05  6:17   ` [PATCH v3 21/22] builtin/merge: release output buffer after performing merge Patrick Steinhardt
2024-11-05  6:17   ` [PATCH v3 22/22] list-objects-filter-options: work around reported leak on error Patrick Steinhardt
2024-11-05  6:51   ` [PATCH v3 00/22] Memory leak fixes (pt.9) Junio C Hamano
2024-11-05  6:52     ` Patrick Steinhardt
2024-11-05 15:27       ` Justin Tobler

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).