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

Re: [PATCH 01/12] revision: free remainder of old commit list in limit_list

From
Andrzej Hunt <andrzej@ahunt.org>
Date
Apr 25, 2021, 13:32 UTC
Message-ID
<c883a4b0-668c-3d43-b1d6-183ccd61133f@ahunt.org>
In-Reply-To
<797e5ce8-14e2-0689-cf19-4426c1c8bd5d@web.de>
On 10/04/2021 09:29, René Scharfe wrote:
Show 95 quoted lines
> Am 09.04.21 um 20:47 schrieb Andrzej Hunt via GitGitGadget:
>> From: Andrzej Hunt <ajrhunt@google.com>
>>
>> limit_list() iterates over the original revs->commits list, and consumes
>> many of its entries via pop_commit. However we might stop iterating over
>> the list early (e.g. if we realise that the rest of the list is
>> uninteresting). If we do stop iterating early, list will be pointing to
>> the unconsumed portion of revs->commits - and we need to free this list
>> to avoid a leak. (revs->commits itself will be an invalid pointer: it
>> will have been free'd during the first pop_commit.)
>>
>> This leak was found while running t0090. It's not likely to be very
>> impactful, but it can happen quite early during some checkout
>> invocations, and hence seems to be worth fixing:
>>
>> Direct leak of 16 byte(s) in 1 object(s) allocated from:
>>      #0 0x49a85d in malloc ../projects/compiler-rt/lib/asan/asan_malloc_linux.cpp:145:3
>>      #1 0x9ac084 in do_xmalloc wrapper.c:41:8
>>      #2 0x9ac05a in xmalloc wrapper.c:62:9
>>      #3 0x7175d6 in commit_list_insert commit.c:540:33
>>      #4 0x71800f in commit_list_insert_by_date commit.c:604:9
>>      #5 0x8f8d2e in process_parents revision.c:1128:5
>>      #6 0x8f2f2c in limit_list revision.c:1418:7
>>      #7 0x8f210e in prepare_revision_walk revision.c:3577:7
>>      #8 0x514170 in orphaned_commit_warning builtin/checkout.c:1185:6
>>      #9 0x512f05 in switch_branches builtin/checkout.c:1250:3
>>      #10 0x50f8de in checkout_branch builtin/checkout.c:1646:9
>>      #11 0x50ba12 in checkout_main builtin/checkout.c:2003:9
>>      #12 0x5086c0 in cmd_checkout builtin/checkout.c:2055:8
>>      #13 0x4cd91d in run_builtin git.c:467:11
>>      #14 0x4cb5f3 in handle_builtin git.c:719:3
>>      #15 0x4ccf47 in run_argv git.c:808:4
>>      #16 0x4caf49 in cmd_main git.c:939:19
>>      #17 0x69dc0e in main common-main.c:52:11
>>      #18 0x7faaabd0e349 in __libc_start_main (/lib64/libc.so.6+0x24349)
>>
>> Indirect leak of 48 byte(s) in 3 object(s) allocated from:
>>      #0 0x49a85d in malloc ../projects/compiler-rt/lib/asan/asan_malloc_linux.cpp:145:3
>>      #1 0x9ac084 in do_xmalloc wrapper.c:41:8
>>      #2 0x9ac05a in xmalloc wrapper.c:62:9
>>      #3 0x717de6 in commit_list_append commit.c:1609:35
>>      #4 0x8f1f9b in prepare_revision_walk revision.c:3554:12
>>      #5 0x514170 in orphaned_commit_warning builtin/checkout.c:1185:6
>>      #6 0x512f05 in switch_branches builtin/checkout.c:1250:3
>>      #7 0x50f8de in checkout_branch builtin/checkout.c:1646:9
>>      #8 0x50ba12 in checkout_main builtin/checkout.c:2003:9
>>      #9 0x5086c0 in cmd_checkout builtin/checkout.c:2055:8
>>      #10 0x4cd91d in run_builtin git.c:467:11
>>      #11 0x4cb5f3 in handle_builtin git.c:719:3
>>      #12 0x4ccf47 in run_argv git.c:808:4
>>      #13 0x4caf49 in cmd_main git.c:939:19
>>      #14 0x69dc0e in main common-main.c:52:11
>>      #15 0x7faaabd0e349 in __libc_start_main (/lib64/libc.so.6+0x24349)
>>
>> Signed-off-by: Andrzej Hunt <ajrhunt@google.com>
>> ---
>>   revision.c | 1 +
>>   1 file changed, 1 insertion(+)
>>
>> diff --git a/revision.c b/revision.c
>> index 553c0faa9b38..7b509aab0c87 100644
>> --- a/revision.c
>> +++ b/revision.c
>> @@ -1460,6 +1460,7 @@ static int limit_list(struct rev_info *revs)
>>   			update_treesame(revs, c);
>>   		}
>>
>> +	free_commit_list(list);
> 
> This patch would benefit from more context, but this function is quite
> long.  So let me sketch it:
> 
> 	struct commit_list *list = revs->commits;
> 
> 	while (list) {
> 		struct commit *commit = pop_commit(&list);
> 		struct object *obj = &commit->object;
> 
> 		if (obj->flags & UNINTERESTING) {
> 			break;
> 		}
> 	}
> 
>          if (limiting_can_increase_treesame(revs))
>                  for (list = newlist; list; list = list->next) {
> 		}
> 
> 	free_commit_list(list);
> 
> So the while loop can leave list dangling and you want to free its
> remaining entries.  The for loop sometimes overwrites the list pointer,
> though, and you will end up passing NULL to free_commit_list in that
> case.  So either the call should be moved between the loops or a fresh
> variable should be used in the second loop instead of reusing list to
> make sure the entries are released in all cases.

Good catch, I did not look closely enough at this one - V1 definitely is buggy*. I've decided I'll add a new variable for the list in V2, but I also took the opportunity to rename the original list since I think that makes it more obvious where that list came from in the first place.

* However I also didn't run into any failures when running the entire 
test-suite with this change, so I'm guessing this codepath isn't being 
exercised by our tests. I'm hoping to try and investigate this in more 
detail when I find a spare moment.
Previous: René ScharfeNext: Andrzej Hunt via GitGitGadget
Message 4 of 35 in “Fix all leaks in tests t0002-t0099: Part 1”
  1. 00/12 Fix all leaks in tests t0002-t0099: Part 1Andrzej Hunt via GitGitGadget, Apr 9, 2021
  2. 01/12 revision: free remainder of old commit list in limit_listAndrzej Hunt via GitGitGadget, Apr 9, 2021
  3. René ScharfeApr 10, 2021
  4. Andrzej HuntApr 25, 2021
  5. 03/12 ls-files: free max_prefix when doneAndrzej Hunt via GitGitGadget, Apr 9, 2021
  6. René ScharfeApr 10, 2021
  7. Andrzej HuntApr 25, 2021
  8. 02/12 wt-status: fix multiple small leaksAndrzej Hunt via GitGitGadget, Apr 9, 2021
  9. 05/12 branch: FREE_AND_NULL instead of NULL'ing real_refAndrzej Hunt via GitGitGadget, Apr 9, 2021
  10. 04/12 bloom: clear each bloom_key after useAndrzej Hunt via GitGitGadget, Apr 9, 2021
  11. SZEDER GáborApr 11, 2021
  12. Andrzej HuntApr 25, 2021
  13. 06/12 builtin/bugreport: don't leak prefixed filenameAndrzej Hunt via GitGitGadget, Apr 9, 2021
  14. 07/12 builtin/check-ignore: clear_pathspec before returningAndrzej Hunt via GitGitGadget, Apr 9, 2021
  15. 08/12 builtin/checkout: clear pending objects after diffingAndrzej Hunt via GitGitGadget, Apr 9, 2021
  16. 09/12 mailinfo: also free strbuf lists when clearing mailinfoAndrzej Hunt via GitGitGadget, Apr 9, 2021
  17. Junio C HamanoApr 11, 2021
  18. Andrzej HuntApr 25, 2021
  19. 10/12 builtin/for-each-ref: free filter and UNLEAK sorting.Andrzej Hunt via GitGitGadget, Apr 9, 2021
  20. 11/12 builtin/rebase: release git_format_patch_opt tooAndrzej Hunt via GitGitGadget, Apr 9, 2021
  21. 12/12 builtin/rm: avoid leaking pathspec and seenAndrzej Hunt via GitGitGadget, Apr 9, 2021
  22. 00/12 Fix all leaks in tests t0002-t0099: Part 1Andrzej Hunt via GitGitGadget, Apr 25, 2021
  23. 01/12 revision: free remainder of old commit list in limit_listAndrzej Hunt via GitGitGadget, Apr 25, 2021
  24. 02/12 wt-status: fix multiple small leaksAndrzej Hunt via GitGitGadget, Apr 25, 2021
  25. 03/12 ls-files: free max_prefix when doneAndrzej Hunt via GitGitGadget, Apr 25, 2021
  26. 05/12 branch: FREE_AND_NULL instead of NULL'ing real_refAndrzej Hunt via GitGitGadget, Apr 25, 2021
  27. 04/12 bloom: clear each bloom_key after useAndrzej Hunt via GitGitGadget, Apr 25, 2021
  28. 06/12 builtin/bugreport: don't leak prefixed filenameAndrzej Hunt via GitGitGadget, Apr 25, 2021
  29. 07/12 builtin/check-ignore: clear_pathspec before returningAndrzej Hunt via GitGitGadget, Apr 25, 2021
  30. 09/12 mailinfo: also free strbuf lists when clearing mailinfoAndrzej Hunt via GitGitGadget, Apr 25, 2021
  31. Junio C HamanoApr 28, 2021
  32. 10/12 builtin/for-each-ref: free filter and UNLEAK sorting.Andrzej Hunt via GitGitGadget, Apr 25, 2021
  33. 08/12 builtin/checkout: clear pending objects after diffingAndrzej Hunt via GitGitGadget, Apr 25, 2021
  34. 11/12 builtin/rebase: release git_format_patch_opt tooAndrzej Hunt via GitGitGadget, Apr 25, 2021
  35. 12/12 builtin/rm: avoid leaking pathspec and seenAndrzej Hunt via GitGitGadget, Apr 25, 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.