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

Re: [PATCH v2 1/1] commit-reach: properly peel tags

From
Derrick Stolee <stolee@gmail.com>
Date
Sep 13, 2018, 16:38 UTC
Message-ID
<8d6061de-1654-577c-40c6-211dbd03aa36@gmail.com>
In-Reply-To
<4bf21204ddf8b9daa823db9954ddde98ab264a1b.1536855032.git.gitgitgadget@gmail.com>
On 9/13/2018 12:10 PM, Derrick Stolee via GitGitGadget wrote:
Show 61 quoted lines
> From: Derrick Stolee <dstolee@microsoft.com>
>
> The can_all_from_reach_with_flag() algorithm was refactored in 4fbcca4e
> "commit-reach: make can_all_from_reach... linear" but incorrectly
> assumed that all objects provided were commits. During a fetch
> negotiation, ok_to_give_up() in upload-pack.c may provide unpeeled tags
> to the 'from' array. The current code creates a segfault.
>
> Add a direct call to can_all_from_reach_with_flag() in 'test-tool reach'
> and add a test in t6600-test-reach.sh that demonstrates this segfault.
>
> Correct the issue by peeling tags when investigating the initial list
> of objects in the 'from' array.
>
> Signed-off-by: Jeff King <peff@peff.net>
> Signed-off-by: Derrick Stolee <dstolee@microsoft.com>
> ---
>   commit-reach.c        | 33 ++++++++++++++++++++++++++-------
>   t/helper/test-reach.c | 22 +++++++++++++++++-----
>   t/t6600-test-reach.sh | 30 ++++++++++++++++++++++++++++--
>   3 files changed, 71 insertions(+), 14 deletions(-)
>
> diff --git a/commit-reach.c b/commit-reach.c
> index 86715c103c..4048a2132a 100644
> --- a/commit-reach.c
> +++ b/commit-reach.c
> @@ -544,20 +544,39 @@ int can_all_from_reach_with_flag(struct object_array *from,
>   {
>   	struct commit **list = NULL;
>   	int i;
> +	int nr_commits;
>   	int result = 1;
>   
>   	ALLOC_ARRAY(list, from->nr);
> +	nr_commits = 0;
>   	for (i = 0; i < from->nr; i++) {
> -		list[i] = (struct commit *)from->objects[i].item;
> +		struct object *from_one = from->objects[i].item;
>   
> -		if (parse_commit(list[i]) ||
> -		    list[i]->generation < min_generation)
> -			return 0;
> +		if (!from_one || from_one->flags & assign_flag)
> +			continue;
> +
> +		from_one = deref_tag(the_repository, from_one,
> +				     "a from object", 0);
> +		if (!from_one || from_one->type != OBJ_COMMIT) {
> +			/* no way to tell if this is reachable by
> +			 * looking at the ancestry chain alone, so
> +			 * leave a note to ourselves not to worry about
> +			 * this object anymore.
> +			 */
> +			from->objects[i].item->flags |= assign_flag;
> +			continue;
> +		}
> +
> +		list[nr_commits] = (struct commit *)from_one;
> +		if (parse_commit(list[nr_commits]) ||
> +		    list[nr_commits]->generation < min_generation)
> +			return 0; /* is this a leak? */

Of course, after sending v2, I see this comment. This is a leak of 'list' and should be fixed.

Not only is it a leak here, it is also a leak in the 'cleanup' section. I'll squash the following into v3, but I'll let v2 simmer for review before rerolling.

diff --git a/commit-reach.c b/commit-reach.c
index 4048a2132a..c457d8d85f 100644
--- a/commit-reach.c
+++ b/commit-reach.c
@@ -569,8 +569,11 @@ int can_all_from_reach_with_flag(struct 
object_array *from,

                 list[nr_commits] = (struct commit *)from_one;
                 if (parse_commit(list[nr_commits]) ||
-                   list[nr_commits]->generation < min_generation)
-                       return 0; /* is this a leak? */
+                   list[nr_commits]->generation < min_generation) {
+                       result = 0;
+                       goto cleanup;
+               }
+
                 nr_commits++;
         }

@@ -623,6 +626,7 @@ int can_all_from_reach_with_flag(struct object_array 
*from,
                 clear_commit_marks(list[i], RESULT);
                 clear_commit_marks(list[i], assign_flag);
         }
+       free(list);
         return result;
  }
Previous: Derrick Stolee via GitGitGadgetNext: Junio C Hamano
Message 8 of 25 in “Properly peel tags in can_all_from_reach_with_flags()”
  1. 0/1 Properly peel tags in can_all_from_reach_with_flags()Derrick Stolee via GitGitGadget, Sep 12, 2018
  2. 1/1 commit-reach: properly peel tagsDerrick Stolee via GitGitGadget, Sep 12, 2018
  3. Jeff KingSep 12, 2018
  4. Junio C HamanoSep 12, 2018
  5. Jeff KingSep 12, 2018
  6. 0/1 Properly peel tags in can_all_from_reach_with_flags()Derrick Stolee via GitGitGadget, Sep 13, 2018
  7. 1/1 commit-reach: properly peel tagsDerrick Stolee via GitGitGadget, Sep 13, 2018
  8. Derrick StoleeSep 13, 2018
  9. Junio C HamanoSep 13, 2018
  10. 0/2 Properly peel tags in can_all_from_reach_with_flags()Derrick Stolee via GitGitGadget, Sep 21, 2018
  11. 1/2 commit-reach: properly peel tagsDerrick Stolee via GitGitGadget, Sep 21, 2018
  12. Jeff KingSep 21, 2018
  13. Derrick StoleeSep 24, 2018
  14. 2/2 commit-reach: fix memory and flag leaksDerrick Stolee via GitGitGadget, Sep 21, 2018
  15. Jeff KingSep 21, 2018
  16. Derrick StoleeSep 24, 2018
  17. Jeff KingSep 24, 2018
  18. 0/1 Properly peel tags in can_all_from_reach_with_flags()Derrick Stolee via GitGitGadget, Sep 24, 2018
  19. 1/1 commit-reach: properly peel tags and clear flagsDerrick Stolee via GitGitGadget, Sep 24, 2018
  20. Jeff KingSep 24, 2018
  21. Eric SunshineSep 25, 2018
  22. commit-reach: cleanups in can_all_from_reach...Derrick Stolee, Sep 25, 2018
  23. Junio C HamanoSep 25, 2018
  24. Derrick StoleeSep 25, 2018
  25. Junio C HamanoSep 25, 2018

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.