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

[PATCH v2 10/15] sequencer.c: fix "opts->strategy" leak in read_strategy_opts()

From
Ævar Arnfjörð Bjarmason <avarab@gmail.com>
Date
Nov 8, 2022, 18:17 UTC
Message-ID
<patch-v2-10.15-243ab74120b-20221108T172650Z-avarab@gmail.com>
In-Reply-To
<cover-v2-00.15-00000000000-20221108T172650Z-avarab@gmail.com>

When "read_strategy_opts()" is called we may have populated the "opts->strategy" before, so we'll need to free() it to avoid leaking memory.

We populate it before because we cal get_replay_opts() from within "rebase.c" with an already populated "opts", which we then copy. Then if we're doing a "rebase -i" the sequencer API itself will promptly clobber our alloc'd version of it with its own.

If this code is changed to do, instead of the added free() here a:
	if (opts->strategy)
		opts->strategy = xstrdup("another leak");

We get a couple of stacktraces from -fsanitize=leak showing how we ended up clobbering the already allocated value, i.e.:

	Direct leak of 6 byte(s) in 1 object(s) allocated from:
	    #0 0x7f2e8cd45545 in __interceptor_malloc ../../../../src/libsanitizer/lsan/lsan_interceptors.cpp:75
	    #1 0x7f2e8cb0fcaa in __GI___strdup string/strdup.c:42
	    #2 0x6c4778 in xstrdup wrapper.c:39
	    #3 0x66bcb8 in read_strategy_opts sequencer.c:2902
	    #4 0x66bf7b in read_populate_opts sequencer.c:2969
	    #5 0x6723f9 in sequencer_continue sequencer.c:5063
	    #6 0x4a4f74 in run_sequencer_rebase builtin/rebase.c:348
	    #7 0x4a64c8 in run_specific_rebase builtin/rebase.c:753
	    #8 0x4a9b8b in cmd_rebase builtin/rebase.c:1824
	    #9 0x407a32 in run_builtin git.c:466
	    #10 0x407e0a in handle_builtin git.c:721
	    #11 0x40803d in run_argv git.c:788
	    #12 0x40850f in cmd_main git.c:923
	    #13 0x4eee79 in main common-main.c:57
	    #14 0x7f2e8ca9f209 in __libc_start_call_main ../sysdeps/nptl/libc_start_call_main.h:58
	    #15 0x7f2e8ca9f2bb in __libc_start_main_impl ../csu/libc-start.c:389
	    #16 0x405fd0 in _start (git+0x405fd0)
	Direct leak of 4 byte(s) in 1 object(s) allocated from:
	    #0 0x7f2e8cd45545 in __interceptor_malloc ../../../../src/libsanitizer/lsan/lsan_interceptors.cpp:75
	    #1 0x7f2e8cb0fcaa in __GI___strdup string/strdup.c:42
	    #2 0x6c4778 in xstrdup wrapper.c:39
	    #3 0x4a3c31 in xstrdup_or_null git-compat-util.h:1169
	    #4 0x4a447a in get_replay_opts builtin/rebase.c:163
	    #5 0x4a4f5b in run_sequencer_rebase builtin/rebase.c:346
	    #6 0x4a64c8 in run_specific_rebase builtin/rebase.c:753
	    #7 0x4a9b8b in cmd_rebase builtin/rebase.c:1824
	    #8 0x407a32 in run_builtin git.c:466
	    #9 0x407e0a in handle_builtin git.c:721
	    #10 0x40803d in run_argv git.c:788
	    #11 0x40850f in cmd_main git.c:923
	    #12 0x4eee79 in main common-main.c:57
	    #13 0x7f2e8ca9f209 in __libc_start_call_main ../sysdeps/nptl/libc_start_call_main.h:58
	    #14 0x7f2e8ca9f2bb in __libc_start_main_impl ../csu/libc-start.c:389
	    #15 0x405fd0 in _start (git+0x405fd0)

This can be seen in e.g. the 4th test of "t3404-rebase-interactive.sh".

In the larger picture the ownership of the "struct replay_opts" is quite a mess, e.g. in this case rebase.c's static "get_replay_opts()" function partially creates it, but nothing in rebase.c will free() it. The structure is "mostly owned" by the sequencer API, but it also expects to get these partially populated versions of it.

It would be better to have rebase keep track of what it allocated, and free() that, and to pass that as a "const" to the sequencer API, which would copy what it needs to its own version, and to free() that.

But doing so is a much larger change, and however messy the ownership boundary is here is consistent with what we're doing already, so let's just free() this to fix the leak.

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 sequencer.c | 1 +
 1 file changed, 1 insertion(+)
diff --git a/sequencer.c b/sequencer.c
index e23f6f0b718..433fec21562 100644
--- a/sequencer.c
+++ b/sequencer.c
@@ -2897,6 +2897,7 @@ static void read_strategy_opts(struct replay_opts *opts, struct strbuf *buf)
 	strbuf_reset(buf);
 	if (!read_oneliner(buf, rebase_path_strategy(), 0))
 		return;
+	free(opts->strategy);
 	opts->strategy = strbuf_detach(buf, NULL);
 	if (!read_oneliner(buf, rebase_path_strategy_opts(), 0))
 		return;
-- 
2.38.0.1467.g709fbdff1a9
Previous: Ævar Arnfjörð BjarmasonNext: Ævar Arnfjörð Bjarmason
Message 39 of 45 in “leak fixes: use existing constructors & other trivia”
  1. 00/17 leak fixes: use existing constructors & other triviaÆvar Arnfjörð Bjarmason, Nov 3, 2022
  2. 02/17 {reset,merge}: call discard_index() before returningÆvar Arnfjörð Bjarmason, Nov 3, 2022
  3. 01/17 tests: mark tests as passing with SANITIZE=leakÆvar Arnfjörð Bjarmason, Nov 3, 2022
  4. 04/17 read-cache.c: clear and free "sparse_checkout_patterns"Ævar Arnfjörð Bjarmason, Nov 3, 2022
  5. 05/17 dir.c: free "ident" and "exclude_per_dir" in "struct untracked_cache"Ævar Arnfjörð Bjarmason, Nov 3, 2022
  6. 06/17 built-ins & libs & helpers: add/move destructors, fix leaksÆvar Arnfjörð Bjarmason, Nov 3, 2022
  7. 07/17 unpack-file: fix ancient leak in create_temp_file()Ævar Arnfjörð Bjarmason, Nov 3, 2022
  8. 09/17 ls-files: fix a --with-tree memory leakÆvar Arnfjörð Bjarmason, Nov 3, 2022
  9. 10/17 sequencer.c: fix "opts->strategy" leak in read_strategy_opts()Ævar Arnfjörð Bjarmason, Nov 3, 2022
  10. Phillip WoodNov 4, 2022
  11. Taylor BlauNov 4, 2022
  12. Ævar Arnfjörð BjarmasonNov 5, 2022
  13. Phillip WoodNov 8, 2022
  14. Ævar Arnfjörð BjarmasonNov 8, 2022
  15. 03/17 commit: discard partial cache before (re-)reading itÆvar Arnfjörð Bjarmason, Nov 3, 2022
  16. 08/17 revision API: call graph_clear() in release_revisions()Ævar Arnfjörð Bjarmason, Nov 3, 2022
  17. 12/17 sequencer.c: fix a pick_commits() leakÆvar Arnfjörð Bjarmason, Nov 3, 2022
  18. 11/17 connected.c: free the "struct packed_git"Ævar Arnfjörð Bjarmason, Nov 3, 2022
  19. 13/17 rebase: don't leak on "--abort"Ævar Arnfjörð Bjarmason, Nov 3, 2022
  20. Phillip WoodNov 4, 2022
  21. Ævar Arnfjörð BjarmasonNov 5, 2022
  22. 16/17 revert: fix parse_options_concat() leakÆvar Arnfjörð Bjarmason, Nov 3, 2022
  23. 14/17 sequencer.c: fix sequencer_continue() leakÆvar Arnfjörð Bjarmason, Nov 3, 2022
  24. 15/17 cherry-pick: free "struct replay_opts" membersÆvar Arnfjörð Bjarmason, Nov 3, 2022
  25. 17/17 built-ins: use free() not UNLEAK() if trivial, rm dead codeÆvar Arnfjörð Bjarmason, Nov 3, 2022
  26. Phillip WoodNov 4, 2022
  27. Ævar Arnfjörð BjarmasonNov 5, 2022
  28. Phillip WoodNov 7, 2022
  29. 00/15 leak fixes: use existing constructors & other triviaÆvar Arnfjörð Bjarmason, Nov 8, 2022
  30. 01/15 tests: mark tests as passing with SANITIZE=leakÆvar Arnfjörð Bjarmason, Nov 8, 2022
  31. 02/15 {reset,merge}: call discard_index() before returningÆvar Arnfjörð Bjarmason, Nov 8, 2022
  32. 04/15 read-cache.c: clear and free "sparse_checkout_patterns"Ævar Arnfjörð Bjarmason, Nov 8, 2022
  33. 03/15 commit: discard partial cache before (re-)reading itÆvar Arnfjörð Bjarmason, Nov 8, 2022
  34. 05/15 dir.c: free "ident" and "exclude_per_dir" in "struct untracked_cache"Ævar Arnfjörð Bjarmason, Nov 8, 2022
  35. 06/15 built-ins & libs & helpers: add/move destructors, fix leaksÆvar Arnfjörð Bjarmason, Nov 8, 2022
  36. 08/15 revision API: call graph_clear() in release_revisions()Ævar Arnfjörð Bjarmason, Nov 8, 2022
  37. 07/15 unpack-file: fix ancient leak in create_temp_file()Ævar Arnfjörð Bjarmason, Nov 8, 2022
  38. 09/15 ls-files: fix a --with-tree memory leakÆvar Arnfjörð Bjarmason, Nov 8, 2022
  39. 10/15 sequencer.c: fix "opts->strategy" leak in read_strategy_opts()Ævar Arnfjörð Bjarmason, Nov 8, 2022
  40. 11/15 connected.c: free the "struct packed_git"Ævar Arnfjörð Bjarmason, Nov 8, 2022
  41. 13/15 cherry-pick: free "struct replay_opts" membersÆvar Arnfjörð Bjarmason, Nov 8, 2022
  42. 12/15 rebase: don't leak on "--abort"Ævar Arnfjörð Bjarmason, Nov 8, 2022
  43. 15/15 built-ins: use free() not UNLEAK() if trivial, rm dead codeÆvar Arnfjörð Bjarmason, Nov 8, 2022
  44. 14/15 revert: fix parse_options_concat() leakÆvar Arnfjörð Bjarmason, Nov 8, 2022
  45. Taylor BlauNov 8, 2022

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.