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

[PATCH v2 02/13] sparse-checkout: pass string literals directly to add_pattern()

From
Jeff King <peff@peff.net>
Date
Jun 4, 2024, 10:13 UTC
Message-ID
<20240604101310.GB1304593@coredump.intra.peff.net>
In-Reply-To
<20240604100814.GA1304520@coredump.intra.peff.net>

The add_pattern() function takes a pattern string, but neither makes a copy of it nor takes ownership of the memory. So it is the caller's responsibility to make sure the string hangs around as long as the pattern_list which references it.

There are a few cases in sparse-checkout where we use string literal patterns by stuffing them into a strbuf, detaching the buffer, and then passing the result into add_pattern(). This creates a leak when the pattern_list is eventually cleared, since we don't retain a copy of the detached buffer to free.

But we can observe that the whole strbuf dance is unnecessary. The point was presumably[1] to satisfy the lifetime requirement of the string. But string literals have static duration; we can count on them lasting for the whole program.

So we can fix the leak by just passing them directly. And as a bonus, that simplifies the code. The leaks can be seen in t7002, which drops from 25 leaks to 22 with this patch. It also makes t3602 and t1090 leak-free.

In the long run, we will also want to clean up this (undocumented!) memory lifetime requirement of add_pattern(). But that can come in a later patch; passing the string literals directly will be the right thing either way.

[1] The code in question comes from 416adc8711 (sparse-checkout: update
    working directory in-process for 'init', 2019-11-21) and 99dfa6f970
    (sparse-checkout: use in-process update for disable subcommand,
    2019-11-21), but I didn't see anything in their commit messages or
    on the list explaining the strbufs.
Signed-off-by: Jeff King <peff@peff.net>
---
 builtin/sparse-checkout.c        | 11 +++--------
 t/t1090-sparse-checkout-scope.sh |  1 +
 t/t3602-rm-sparse-checkout.sh    |  1 +
 3 files changed, 5 insertions(+), 8 deletions(-)
diff --git a/builtin/sparse-checkout.c b/builtin/sparse-checkout.c
index 8747191484..7c17ed238c 100644
--- a/builtin/sparse-checkout.c
+++ b/builtin/sparse-checkout.c
@@ -442,7 +442,6 @@ static int sparse_checkout_init(int argc, const char **argv, const char *prefix)
 	char *sparse_filename;
 	int res;
 	struct object_id oid;
-	struct strbuf pattern = STRBUF_INIT;
 
 	static struct option builtin_sparse_checkout_init_options[] = {
 		OPT_BOOL(0, "cone", &init_opts.cone_mode,
@@ -493,10 +492,8 @@ static int sparse_checkout_init(int argc, const char **argv, const char *prefix)
 		return 0;
 	}
 
-	strbuf_addstr(&pattern, "/*");
-	add_pattern(strbuf_detach(&pattern, NULL), empty_base, 0, &pl, 0);
-	strbuf_addstr(&pattern, "!/*/");
-	add_pattern(strbuf_detach(&pattern, NULL), empty_base, 0, &pl, 0);
+	add_pattern("/*", empty_base, 0, &pl, 0);
+	add_pattern("!/*/", empty_base, 0, &pl, 0);
 	pl.use_cone_patterns = init_opts.cone_mode;
 
 	return write_patterns_and_update(&pl);
@@ -893,7 +890,6 @@ static int sparse_checkout_disable(int argc, const char **argv,
 		OPT_END(),
 	};
 	struct pattern_list pl;
-	struct strbuf match_all = STRBUF_INIT;
 
 	/*
 	 * We do not exit early if !core_apply_sparse_checkout; due to the
@@ -919,8 +915,7 @@ static int sparse_checkout_disable(int argc, const char **argv,
 	pl.use_cone_patterns = 0;
 	core_apply_sparse_checkout = 1;
 
-	strbuf_addstr(&match_all, "/*");
-	add_pattern(strbuf_detach(&match_all, NULL), empty_base, 0, &pl, 0);
+	add_pattern("/*", empty_base, 0, &pl, 0);
 
 	prepare_repo_settings(the_repository);
 	the_repository->settings.sparse_index = 0;
diff --git a/t/t1090-sparse-checkout-scope.sh b/t/t1090-sparse-checkout-scope.sh
index 3a14218b24..da0e7714d5 100755
--- a/t/t1090-sparse-checkout-scope.sh
+++ b/t/t1090-sparse-checkout-scope.sh
@@ -6,6 +6,7 @@ GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
 export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
 
 TEST_CREATE_REPO_NO_TEMPLATE=1
+TEST_PASSES_SANITIZE_LEAK=true
 . ./test-lib.sh
 
 test_expect_success 'setup' '
diff --git a/t/t3602-rm-sparse-checkout.sh b/t/t3602-rm-sparse-checkout.sh
index 08580fd3dc..fcdefba48c 100755
--- a/t/t3602-rm-sparse-checkout.sh
+++ b/t/t3602-rm-sparse-checkout.sh
@@ -2,6 +2,7 @@
 
 test_description='git rm in sparse checked out working trees'
 
+TEST_PASSES_SANITIZE_LEAK=true
 . ./test-lib.sh
 
 test_expect_success 'setup' "
-- 
2.45.2.807.g3b5fadc4da
Previous: Jeff KingNext: Jeff King
Message 28 of 43 in “leak fixes for sparse-checkout code”
  1. 0/13 leak fixes for sparse-checkout codeJeff King, May 31, 2024
  2. 01/13 sparse-checkout: free string list in write_cone_to_file()Jeff King, May 31, 2024
  3. 02/13 sparse-checkout: pass string literals directly to add_pattern()Jeff King, May 31, 2024
  4. Junio C HamanoMay 31, 2024
  5. Jeff KingJun 4, 2024
  6. 03/13 dir.c: free strings in sparse cone pattern hashmapsJeff King, May 31, 2024
  7. 04/13 sparse-checkout: clear patterns when init() sees existing sparse fileJeff King, May 31, 2024
  8. 05/13 dir.c: free removed sparse-pattern hashmap entriesJeff King, May 31, 2024
  9. 06/13 dir.c: always copy input to add_pattern()Jeff King, May 31, 2024
  10. Junio C HamanoMay 31, 2024
  11. 07/13 sparse-checkout: reuse --stdin buffer when reading patternsJeff King, May 31, 2024
  12. 08/13 sparse-checkout: always free "line" strbuf after reading inputJeff King, May 31, 2024
  13. 09/13 sparse-checkout: refactor temporary sparse_checkout_patternsJeff King, May 31, 2024
  14. Patrick SteinhardtJun 4, 2024
  15. Jeff KingJun 4, 2024
  16. 10/13 sparse-checkout: free sparse_filename after useJeff King, May 31, 2024
  17. Patrick SteinhardtJun 4, 2024
  18. Jeff KingJun 4, 2024
  19. Patrick SteinhardtJun 4, 2024
  20. 11/13 sparse-checkout: free pattern list in sparse_checkout_list()Jeff King, May 31, 2024
  21. 12/13 sparse-checkout: free string list after displayingJeff King, May 31, 2024
  22. 13/13 sparse-checkout: free duplicate hashmap entriesJeff King, May 31, 2024
  23. Patrick SteinhardtJun 4, 2024
  24. Jeff KingMay 31, 2024
  25. Junio C HamanoMay 31, 2024
  26. 0/13 leak fixes for sparse-checkout codeJeff King, Jun 4, 2024
  27. 01/13 sparse-checkout: free string list in write_cone_to_file()Jeff King, Jun 4, 2024
  28. 02/13 sparse-checkout: pass string literals directly to add_pattern()Jeff King, Jun 4, 2024
  29. 03/13 dir.c: free strings in sparse cone pattern hashmapsJeff King, Jun 4, 2024
  30. 04/13 sparse-checkout: clear patterns when init() sees existing sparse fileJeff King, Jun 4, 2024
  31. 05/13 dir.c: free removed sparse-pattern hashmap entriesJeff King, Jun 4, 2024
  32. 06/13 dir.c: always copy input to add_pattern()Jeff King, Jun 4, 2024
  33. René ScharfeJun 5, 2024
  34. Jeff KingJun 5, 2024
  35. Junio C HamanoJun 5, 2024
  36. 07/13 sparse-checkout: reuse --stdin buffer when reading patternsJeff King, Jun 4, 2024
  37. 08/13 sparse-checkout: always free "line" strbuf after reading inputJeff King, Jun 4, 2024
  38. 09/13 sparse-checkout: refactor temporary sparse_checkout_patternsJeff King, Jun 4, 2024
  39. 10/13 sparse-checkout: free sparse_filename after useJeff King, Jun 4, 2024
  40. 11/13 sparse-checkout: free pattern list in sparse_checkout_list()Jeff King, Jun 4, 2024
  41. 12/13 sparse-checkout: free string list after displayingJeff King, Jun 4, 2024
  42. 13/13 sparse-checkout: free duplicate hashmap entriesJeff King, Jun 4, 2024
  43. Patrick SteinhardtJun 4, 2024

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.