git/list[1] front-page[2] threads[3] people[4] search[5] about
 

[PATCH v4 1/3] bundle cmd: stop leaking memory from parse_options_cmd_bundle()

From
Ævar Arnfjörð Bjarmason <avarab@gmail.com>
Date
Jul 2, 2021, 09:57 UTC
Message-ID
<patch-1.3-8e1d08113e5-20210702T095450Z-avarab@gmail.com>
In-Reply-To
<cover-0.3-00000000000-20210702T095450Z-avarab@gmail.com>

Fix a memory leak from the prefix_filename() function introduced with its use in 3b754eedd5 (bundle: use prefix_filename with bundle path, 2017-03-20).

As noted in that commit the leak was intentional as a part of being sloppy about freeing resources just before we exit, I'm changing this because I'll be fixing other memory leaks in the bundle API (including the library version) in subsequent commits. It's easier to reason about those fixes if valgrind runs cleanly at the end without any leaks whatsoever.

An earlier version of this change[1] went out of its way to not leak memory on the die() codepaths here, but doing so will only avoid reports of potential leaks under heap-only leak trackers such as valgrind, not the SANITIZE=leak mode.

Avoiding those leaks as well might be useful to enable us to run cleanly under the likes of valgrind in the future. But for now the relative verbosity of the resulting code, and the fact that we don't have some valgrind or SANITIZE=leak mode as part of our CI (it's only run ad-hoc, see [2]), means we're not worrying about that for now.

1. https://lore.kernel.org/git/87v95vdxrc.fsf@evledraar.gmail.com/
2. https://lore.kernel.org/git/87czsv2idy.fsf@evledraar.gmail.com/
Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 builtin/bundle.c | 62 ++++++++++++++++++++++++++++++++----------------
 1 file changed, 41 insertions(+), 21 deletions(-)
diff --git a/builtin/bundle.c b/builtin/bundle.c
index ea6948110b0..15e2bd61965 100644
--- a/builtin/bundle.c
+++ b/builtin/bundle.c
@@ -46,7 +46,7 @@ static int parse_options_cmd_bundle(int argc,
 		const char* prefix,
 		const char * const usagestr[],
 		const struct option options[],
-		const char **bundle_file) {
+		char **bundle_file) {
 	int newargc;
 	newargc = parse_options(argc, argv, NULL, options, usagestr,
 			     PARSE_OPT_STOP_AT_NON_OPTION);
@@ -61,7 +61,7 @@ static int cmd_bundle_create(int argc, const char **argv, const char *prefix) {
 	int progress = isatty(STDERR_FILENO);
 	struct strvec pack_opts;
 	int version = -1;
-
+	int ret;
 	struct option options[] = {
 		OPT_SET_INT('q', "quiet", &progress,
 			    N_("do not show progress meter"), 0),
@@ -76,7 +76,7 @@ static int cmd_bundle_create(int argc, const char **argv, const char *prefix) {
 			    N_("specify bundle format version")),
 		OPT_END()
 	};
-	const char* bundle_file;
+	char *bundle_file;
 
 	argc = parse_options_cmd_bundle(argc, argv, prefix,
 			builtin_bundle_create_usage, options, &bundle_file);
@@ -94,75 +94,95 @@ static int cmd_bundle_create(int argc, const char **argv, const char *prefix) {
 
 	if (!startup_info->have_repository)
 		die(_("Need a repository to create a bundle."));
-	return !!create_bundle(the_repository, bundle_file, argc, argv, &pack_opts, version);
+	ret = !!create_bundle(the_repository, bundle_file, argc, argv, &pack_opts, version);
+	free(bundle_file);
+	return ret;
 }
 
 static int cmd_bundle_verify(int argc, const char **argv, const char *prefix) {
 	struct bundle_header header;
 	int bundle_fd = -1;
 	int quiet = 0;
-
+	int ret;
 	struct option options[] = {
 		OPT_BOOL('q', "quiet", &quiet,
 			    N_("do not show bundle details")),
 		OPT_END()
 	};
-	const char* bundle_file;
+	char *bundle_file;
 
 	argc = parse_options_cmd_bundle(argc, argv, prefix,
 			builtin_bundle_verify_usage, options, &bundle_file);
 	/* bundle internals use argv[1] as further parameters */
 
 	memset(&header, 0, sizeof(header));
-	if ((bundle_fd = read_bundle_header(bundle_file, &header)) < 0)
-		return 1;
+	if ((bundle_fd = read_bundle_header(bundle_file, &header)) < 0) {
+		ret = 1;
+		goto cleanup;
+	}
 	close(bundle_fd);
-	if (verify_bundle(the_repository, &header, !quiet))
-		return 1;
+	if (verify_bundle(the_repository, &header, !quiet)) {
+		ret = 1;
+		goto cleanup;
+	}
+
 	fprintf(stderr, _("%s is okay\n"), bundle_file);
-	return 0;
+	ret = 0;
+cleanup:
+	free(bundle_file);
+	return ret;
 }
 
 static int cmd_bundle_list_heads(int argc, const char **argv, const char *prefix) {
 	struct bundle_header header;
 	int bundle_fd = -1;
-
+	int ret;
 	struct option options[] = {
 		OPT_END()
 	};
-	const char* bundle_file;
+	char *bundle_file;
 
 	argc = parse_options_cmd_bundle(argc, argv, prefix,
 			builtin_bundle_list_heads_usage, options, &bundle_file);
 	/* bundle internals use argv[1] as further parameters */
 
 	memset(&header, 0, sizeof(header));
-	if ((bundle_fd = read_bundle_header(bundle_file, &header)) < 0)
-		return 1;
+	if ((bundle_fd = read_bundle_header(bundle_file, &header)) < 0) {
+		ret = 1;
+		goto cleanup;
+	}
 	close(bundle_fd);
-	return !!list_bundle_refs(&header, argc, argv);
+	ret = !!list_bundle_refs(&header, argc, argv);
+cleanup:
+	free(bundle_file);
+	return ret;
 }
 
 static int cmd_bundle_unbundle(int argc, const char **argv, const char *prefix) {
 	struct bundle_header header;
 	int bundle_fd = -1;
-
+	int ret;
 	struct option options[] = {
 		OPT_END()
 	};
-	const char* bundle_file;
+	char *bundle_file;
 
 	argc = parse_options_cmd_bundle(argc, argv, prefix,
 			builtin_bundle_unbundle_usage, options, &bundle_file);
 	/* bundle internals use argv[1] as further parameters */
 
 	memset(&header, 0, sizeof(header));
-	if ((bundle_fd = read_bundle_header(bundle_file, &header)) < 0)
-		return 1;
+	if ((bundle_fd = read_bundle_header(bundle_file, &header)) < 0) {
+		ret = 1;
+		goto cleanup;
+	}
 	if (!startup_info->have_repository)
 		die(_("Need a repository to unbundle."));
-	return !!unbundle(the_repository, &header, bundle_fd, 0) ||
+	ret = !!unbundle(the_repository, &header, bundle_fd, 0) ||
 		list_bundle_refs(&header, argc, argv);
+cleanup:
+	free(bundle_file);
+	return ret;
 }
 
 int cmd_bundle(int argc, const char **argv, const char *prefix)
-- 
2.32.0.632.g49a94b9226d
Previous: Ævar Arnfjörð BjarmasonNext: Ævar Arnfjörð Bjarmason
Message 29 of 33 in “bundle.c: remove "ref_list" in favor of string-list.c API”
  1. 0/3 bundle.c: remove "ref_list" in favor of string-list.c APIÆvar Arnfjörð Bjarmason, Jun 17, 2021
  2. 1/3 bundle cmd: stop leaking memory from parse_options_cmd_bundle()Ævar Arnfjörð Bjarmason, Jun 17, 2021
  3. 3/3 bundle: remove "ref_list" in favor of string-list.c APIÆvar Arnfjörð Bjarmason, Jun 17, 2021
  4. Andrei RybakJun 19, 2021
  5. 2/3 bundle.c: use a temporary variable for OIDs and namesÆvar Arnfjörð Bjarmason, Jun 17, 2021
  6. 0/3 bundle.c: remove "ref_list" in favor of string-list.c APIÆvar Arnfjörð Bjarmason, Jun 21, 2021
  7. 2/3 bundle.c: use a temporary variable for OIDs and namesÆvar Arnfjörð Bjarmason, Jun 21, 2021
  8. 1/3 bundle cmd: stop leaking memory from parse_options_cmd_bundle()Ævar Arnfjörð Bjarmason, Jun 21, 2021
  9. Jeff KingJun 24, 2021
  10. Ævar Arnfjörð BjarmasonJun 24, 2021
  11. 3/3 bundle: remove "ref_list" in favor of string-list.c APIÆvar Arnfjörð Bjarmason, Jun 21, 2021
  12. Jeff KingJun 24, 2021
  13. Ævar Arnfjörð BjarmasonJun 24, 2021
  14. Junio C HamanoJun 29, 2021
  15. Jeff KingJun 24, 2021
  16. 0/3 Ævar Arnfjörð Bjarmason, Jun 30, 2021
  17. 1/3 bundle cmd: stop leaking memory from parse_options_cmd_bundle()Ævar Arnfjörð Bjarmason, Jun 30, 2021
  18. Jeff KingJun 30, 2021
  19. Ævar Arnfjörð BjarmasonJun 30, 2021
  20. Jeff KingJul 1, 2021
  21. 2/3 bundle.c: use a temporary variable for OIDs and namesÆvar Arnfjörð Bjarmason, Jun 30, 2021
  22. 3/3 bundle: remove "ref_list" in favor of string-list.c APIÆvar Arnfjörð Bjarmason, Jun 30, 2021
  23. Junio C HamanoJun 30, 2021
  24. Jeff KingJun 30, 2021
  25. Jeff KingJun 30, 2021
  26. Ævar Arnfjörð BjarmasonJun 30, 2021
  27. Ævar Arnfjörð BjarmasonJul 1, 2021
  28. 0/3 bundle.c: remove "ref_list" in favor of string-list.c APIÆvar Arnfjörð Bjarmason, Jul 2, 2021
  29. 1/3 bundle cmd: stop leaking memory from parse_options_cmd_bundle()Ævar Arnfjörð Bjarmason, Jul 2, 2021
  30. 2/3 bundle.c: use a temporary variable for OIDs and namesÆvar Arnfjörð Bjarmason, Jul 2, 2021
  31. 3/3 bundle: remove "ref_list" in favor of string-list.c APIÆvar Arnfjörð Bjarmason, Jul 2, 2021
  32. Jeff KingJul 3, 2021
  33. Ævar Arnfjörð BjarmasonJul 3, 2021

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.