git.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Patrick Steinhardt <ps@pks.im>
To: git@vger.kernel.org
Cc: Phillip Wood <phillip.wood123@gmail.com>,
	Karthik Nayak <karthik.188@gmail.com>
Subject: [PATCH v2 15/29] revision: free diff options
Date: Tue, 11 Jun 2024 11:20:24 +0200	[thread overview]
Message-ID: <99f4f3d3412a40eb6ada67ae48c7369cb57762cc.1718095906.git.ps@pks.im> (raw)
In-Reply-To: <cover.1718095906.git.ps@pks.im>

[-- Attachment #1: Type: text/plain, Size: 7058 bytes --]

There is a todo comment in `release_revisions()` that mentions that we
need to free the diff options, which was added via 54c8a7c379 (revisions
API: add a TODO for diff_free(&revs->diffopt), 2022-04-14). Releasing
the diff options wasn't quite feasible at that time because some call
sites rely on its contents to remain even after the revisions have been
released.

In fact, there really only are a couple of callsites that misbehave
here:

  - `cmd_shortlog()` releases the revisions, but continues to access its
    file pointer.

  - `do_diff_cache()` creates a shallow copy of `struct diff_options`,
    but does not set the `no_free` member. Consequently, we end up
    releasing resources of the caller-provided diff options.

  - `diff_free()` and friends do not play nice when being called
    multiple times as they don't unset data structures that they have
    just released.

Fix all of those cases and enable the call to `diff_free()`, which plugs
a bunch of memory leaks.

Signed-off-by: Patrick Steinhardt <ps@pks.im>
---
 builtin/shortlog.c                        | 5 +----
 diff-lib.c                                | 2 ++
 diff.c                                    | 8 ++++++--
 revision.c                                | 2 +-
 t/t4208-log-magic-pathspec.sh             | 1 +
 t/t6000-rev-list-misc.sh                  | 1 +
 t/t6001-rev-list-graft.sh                 | 1 +
 t/t6013-rev-list-reverse-parents.sh       | 1 +
 t/t6017-rev-list-stdin.sh                 | 1 +
 t/t9500-gitweb-standalone-no-errors.sh    | 1 +
 t/t9502-gitweb-standalone-parse-output.sh | 1 +
 11 files changed, 17 insertions(+), 7 deletions(-)

diff --git a/builtin/shortlog.c b/builtin/shortlog.c
index d4daf31e22..5bde7c68c2 100644
--- a/builtin/shortlog.c
+++ b/builtin/shortlog.c
@@ -460,11 +460,8 @@ int cmd_shortlog(int argc, const char **argv, const char *prefix)
 	else
 		get_from_rev(&rev, &log);
 
-	release_revisions(&rev);
-
 	shortlog_output(&log);
-	if (log.file != stdout)
-		fclose(log.file);
+	release_revisions(&rev);
 	return 0;
 }
 
diff --git a/diff-lib.c b/diff-lib.c
index 5a5a50c5a1..1cbf03bf39 100644
--- a/diff-lib.c
+++ b/diff-lib.c
@@ -662,9 +662,11 @@ 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);
 	revs.diffopt = *opt;
+	revs.diffopt.no_free = 1;
 
 	if (diff_cache(&revs, tree_oid, NULL, 1))
 		exit(128);
+
 	release_revisions(&revs);
 	return 0;
 }
diff --git a/diff.c b/diff.c
index e70301df76..53e2f5a42e 100644
--- a/diff.c
+++ b/diff.c
@@ -6649,8 +6649,10 @@ static void diff_flush_patch_all_file_pairs(struct diff_options *o)
 
 static void diff_free_file(struct diff_options *options)
 {
-	if (options->close_file)
+	if (options->close_file && options->file) {
 		fclose(options->file);
+		options->file = NULL;
+	}
 }
 
 static void diff_free_ignore_regex(struct diff_options *options)
@@ -6661,7 +6663,9 @@ static void diff_free_ignore_regex(struct diff_options *options)
 		regfree(options->ignore_regex[i]);
 		free(options->ignore_regex[i]);
 	}
-	free(options->ignore_regex);
+
+	FREE_AND_NULL(options->ignore_regex);
+	options->ignore_regex_nr = 0;
 }
 
 void diff_free(struct diff_options *options)
diff --git a/revision.c b/revision.c
index 82c0aadb42..99c75c939d 100644
--- a/revision.c
+++ b/revision.c
@@ -3191,7 +3191,7 @@ void release_revisions(struct rev_info *revs)
 	release_revisions_mailmap(revs->mailmap);
 	free_grep_patterns(&revs->grep_filter);
 	graph_clear(revs->graph);
-	/* TODO (need to handle "no_free"): diff_free(&revs->diffopt) */
+	diff_free(&revs->diffopt);
 	diff_free(&revs->pruning);
 	reflog_walk_info_release(revs->reflog_info);
 	release_revisions_topo_walk_info(revs->topo_walk_info);
diff --git a/t/t4208-log-magic-pathspec.sh b/t/t4208-log-magic-pathspec.sh
index 806b2809d4..2a46eb6bed 100755
--- a/t/t4208-log-magic-pathspec.sh
+++ b/t/t4208-log-magic-pathspec.sh
@@ -5,6 +5,7 @@ test_description='magic pathspec tests using 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_expect_success 'setup' '
diff --git a/t/t6000-rev-list-misc.sh b/t/t6000-rev-list-misc.sh
index 6289a2e8b0..f6d17ee902 100755
--- a/t/t6000-rev-list-misc.sh
+++ b/t/t6000-rev-list-misc.sh
@@ -5,6 +5,7 @@ test_description='miscellaneous rev-list tests'
 GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
 export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
 
+TEST_PASSES_SANITIZE_LEAK=true
 . ./test-lib.sh
 
 test_expect_success setup '
diff --git a/t/t6001-rev-list-graft.sh b/t/t6001-rev-list-graft.sh
index 73a2465aa0..3553bbbfe7 100755
--- a/t/t6001-rev-list-graft.sh
+++ b/t/t6001-rev-list-graft.sh
@@ -5,6 +5,7 @@ test_description='Revision traversal vs grafts and path limiter'
 GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
 export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
 
+TEST_PASSES_SANITIZE_LEAK=true
 . ./test-lib.sh
 
 test_expect_success setup '
diff --git a/t/t6013-rev-list-reverse-parents.sh b/t/t6013-rev-list-reverse-parents.sh
index 39793cbbd6..4128269c1d 100755
--- a/t/t6013-rev-list-reverse-parents.sh
+++ b/t/t6013-rev-list-reverse-parents.sh
@@ -5,6 +5,7 @@ test_description='--reverse combines with --parents'
 GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
 export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
 
+TEST_PASSES_SANITIZE_LEAK=true
 . ./test-lib.sh
 
 
diff --git a/t/t6017-rev-list-stdin.sh b/t/t6017-rev-list-stdin.sh
index 4821b90e74..a0a40fe55c 100755
--- a/t/t6017-rev-list-stdin.sh
+++ b/t/t6017-rev-list-stdin.sh
@@ -8,6 +8,7 @@ test_description='log family learns --stdin'
 GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
 export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
 
+TEST_PASSES_SANITIZE_LEAK=true
 . ./test-lib.sh
 
 check () {
diff --git a/t/t9500-gitweb-standalone-no-errors.sh b/t/t9500-gitweb-standalone-no-errors.sh
index 7679780fb8..ccfa415384 100755
--- a/t/t9500-gitweb-standalone-no-errors.sh
+++ b/t/t9500-gitweb-standalone-no-errors.sh
@@ -13,6 +13,7 @@ or warnings to log.'
 GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
 export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
 
+TEST_PASSES_SANITIZE_LEAK=true
 . ./lib-gitweb.sh
 
 # ----------------------------------------------------------------------
diff --git a/t/t9502-gitweb-standalone-parse-output.sh b/t/t9502-gitweb-standalone-parse-output.sh
index 81d5625557..b41ea19331 100755
--- a/t/t9502-gitweb-standalone-parse-output.sh
+++ b/t/t9502-gitweb-standalone-parse-output.sh
@@ -13,6 +13,7 @@ in the HTTP header or the actual script output.'
 GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
 export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
 
+TEST_PASSES_SANITIZE_LEAK=true
 . ./lib-gitweb.sh
 
 # ----------------------------------------------------------------------
-- 
2.45.2.436.gcd77e87115.dirty


[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

  parent reply	other threads:[~2024-06-11  9:20 UTC|newest]

Thread overview: 74+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2024-06-03  9:46 [PATCH 00/29] Memory leak fixes (pt.2) Patrick Steinhardt
2024-06-03  9:46 ` [PATCH 01/29] revision: fix memory leak when reversing revisions Patrick Steinhardt
2024-06-03  9:46 ` [PATCH 02/29] parse-options: fix leaks for users of OPT_FILENAME Patrick Steinhardt
2024-06-06 10:00   ` Karthik Nayak
2024-06-03  9:46 ` [PATCH 03/29] notes-utils: free note trees when releasing copied notes Patrick Steinhardt
2024-06-06 10:02   ` Karthik Nayak
2024-06-03  9:46 ` [PATCH 04/29] bundle: plug leaks in `create_bundle()` Patrick Steinhardt
2024-06-03  9:46 ` [PATCH 05/29] biultin/rev-parse: fix memory leaks in `--parseopt` mode Patrick Steinhardt
2024-06-03  9:46 ` [PATCH 06/29] merge-recursive: fix leaging rename conflict info Patrick Steinhardt
2024-06-06 10:07   ` Karthik Nayak
2024-06-03  9:46 ` [PATCH 07/29] revision: fix leaking display notes Patrick Steinhardt
2024-06-03  9:47 ` [PATCH 08/29] notes: fix memory leak when pruning notes Patrick Steinhardt
2024-06-03  9:47 ` [PATCH 09/29] builtin/rev-list: fix leaking bitmap index when calculating disk usage Patrick Steinhardt
2024-06-03  9:47 ` [PATCH 10/29] object-name: free leaking object contexts Patrick Steinhardt
2024-06-03  9:47 ` [PATCH 11/29] builtin/difftool: plug memory leaks in `run_dir_diff()` Patrick Steinhardt
2024-06-03  9:47 ` [PATCH 12/29] builtin/merge-recursive: fix leaking object ID bases Patrick Steinhardt
2024-06-03  9:47 ` [PATCH 13/29] merge-recursive: fix memory leak when finalizing merge Patrick Steinhardt
2024-06-06 10:50   ` Karthik Nayak
2024-06-06 15:52     ` Phillip Wood
2024-06-12  9:33       ` Karthik Nayak
2024-06-03  9:47 ` [PATCH 14/29] builtin/log: fix leaking commit list in git-cherry(1) Patrick Steinhardt
2024-06-03  9:47 ` [PATCH 15/29] revision: free diff options Patrick Steinhardt
2024-06-03  9:47 ` [PATCH 16/29] builtin/stash: fix leak in `show_stash()` Patrick Steinhardt
2024-06-03  9:47 ` [PATCH 17/29] rerere: fix various trivial leaks Patrick Steinhardt
2024-06-03  9:47 ` [PATCH 18/29] config: fix leaking "core.notesref" variable Patrick Steinhardt
2024-06-03  9:47 ` [PATCH 19/29] commit: fix leaking parents when calling `commit_tree_extended()` Patrick Steinhardt
2024-06-03  9:48 ` [PATCH 20/29] sequencer: fix leaking string buffer in `commit_staged_changes()` Patrick Steinhardt
2024-06-03 13:14   ` Phillip Wood
2024-06-04  6:45     ` Patrick Steinhardt
2024-06-04  7:19       ` Patrick Steinhardt
2024-06-04 13:58         ` Phillip Wood
2024-06-03  9:48 ` [PATCH 21/29] apply: fix leaking string in `match_fragment()` Patrick Steinhardt
2024-06-03  9:48 ` [PATCH 22/29] builtin/clone: plug leaking HEAD ref in `wanted_peer_refs()` Patrick Steinhardt
2024-06-03  9:48 ` [PATCH 23/29] sequencer: fix memory leaks in `make_script_with_merges()` Patrick Steinhardt
2024-06-03  9:48 ` [PATCH 24/29] builtin/merge: fix leaking `struct cmdnames` in `get_strategy()` Patrick Steinhardt
2024-06-03  9:48 ` [PATCH 25/29] merge: fix leaking merge bases Patrick Steinhardt
2024-06-03  9:48 ` [PATCH 26/29] line-range: plug leaking find functions Patrick Steinhardt
2024-06-03  9:48 ` [PATCH 27/29] blame: fix leaking data for blame scoreboards Patrick Steinhardt
2024-06-03  9:48 ` [PATCH 28/29] builtin/blame: fix leaking prefixed paths Patrick Steinhardt
2024-06-03  9:48 ` [PATCH 29/29] builtin/blame: fix leaking ignore revs files Patrick Steinhardt
2024-06-06 14:33 ` [PATCH 00/29] Memory leak fixes (pt.2) Karthik Nayak
2024-06-07  4:07   ` Patrick Steinhardt
2024-06-11  9:19 ` [PATCH v2 " Patrick Steinhardt
2024-06-11  9:19   ` [PATCH v2 01/29] revision: fix memory leak when reversing revisions Patrick Steinhardt
2024-06-11  9:19   ` [PATCH v2 02/29] parse-options: fix leaks for users of OPT_FILENAME Patrick Steinhardt
2024-06-11  9:19   ` [PATCH v2 03/29] notes-utils: free note trees when releasing copied notes Patrick Steinhardt
2024-06-11  9:19   ` [PATCH v2 04/29] bundle: plug leaks in `create_bundle()` Patrick Steinhardt
2024-06-11  9:19   ` [PATCH v2 05/29] biultin/rev-parse: fix memory leaks in `--parseopt` mode Patrick Steinhardt
2024-06-11  9:19   ` [PATCH v2 06/29] merge-recursive: fix leaking rename conflict info Patrick Steinhardt
2024-06-11  9:19   ` [PATCH v2 07/29] revision: fix leaking display notes Patrick Steinhardt
2024-06-11  9:19   ` [PATCH v2 08/29] notes: fix memory leak when pruning notes Patrick Steinhardt
2024-06-11  9:19   ` [PATCH v2 09/29] builtin/rev-list: fix leaking bitmap index when calculating disk usage Patrick Steinhardt
2024-06-11  9:19   ` [PATCH v2 10/29] object-name: free leaking object contexts Patrick Steinhardt
2024-06-11  9:20   ` [PATCH v2 11/29] builtin/difftool: plug memory leaks in `run_dir_diff()` Patrick Steinhardt
2024-06-11  9:20   ` [PATCH v2 12/29] builtin/merge-recursive: fix leaking object ID bases Patrick Steinhardt
2024-06-11  9:20   ` [PATCH v2 13/29] merge-recursive: fix memory leak when finalizing merge Patrick Steinhardt
2024-06-11  9:20   ` [PATCH v2 14/29] builtin/log: fix leaking commit list in git-cherry(1) Patrick Steinhardt
2024-06-11  9:20   ` Patrick Steinhardt [this message]
2024-06-11  9:20   ` [PATCH v2 16/29] builtin/stash: fix leak in `show_stash()` Patrick Steinhardt
2024-06-11  9:20   ` [PATCH v2 17/29] rerere: fix various trivial leaks Patrick Steinhardt
2024-06-11  9:20   ` [PATCH v2 18/29] config: fix leaking "core.notesref" variable Patrick Steinhardt
2024-06-11  9:20   ` [PATCH v2 19/29] commit: fix leaking parents when calling `commit_tree_extended()` Patrick Steinhardt
2024-06-11  9:20   ` [PATCH v2 20/29] sequencer: fix leaking string buffer in `commit_staged_changes()` Patrick Steinhardt
2024-06-11  9:20   ` [PATCH v2 21/29] apply: fix leaking string in `match_fragment()` Patrick Steinhardt
2024-06-11  9:20   ` [PATCH v2 22/29] builtin/clone: plug leaking HEAD ref in `wanted_peer_refs()` Patrick Steinhardt
2024-06-11  9:21   ` [PATCH v2 23/29] sequencer: fix memory leaks in `make_script_with_merges()` Patrick Steinhardt
2024-06-11  9:21   ` [PATCH v2 24/29] builtin/merge: fix leaking `struct cmdnames` in `get_strategy()` Patrick Steinhardt
2024-06-11  9:21   ` [PATCH v2 25/29] merge: fix leaking merge bases Patrick Steinhardt
2024-06-11  9:21   ` [PATCH v2 26/29] line-range: plug leaking find functions Patrick Steinhardt
2024-06-11  9:21   ` [PATCH v2 27/29] blame: fix leaking data for blame scoreboards Patrick Steinhardt
2024-06-11  9:21   ` [PATCH v2 28/29] builtin/blame: fix leaking prefixed paths Patrick Steinhardt
2024-06-11  9:21   ` [PATCH v2 29/29] builtin/blame: fix leaking ignore revs files Patrick Steinhardt
2024-06-12  9:09   ` [PATCH v2 00/29] Memory leak fixes (pt.2) Phillip Wood
2024-06-12  9:35   ` Karthik Nayak

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=99f4f3d3412a40eb6ada67ae48c7369cb57762cc.1718095906.git.ps@pks.im \
    --to=ps@pks.im \
    --cc=git@vger.kernel.org \
    --cc=karthik.188@gmail.com \
    --cc=phillip.wood123@gmail.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
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).