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

Re: [PATCH] add_submodule_odb: initialize alt_odb list earlier

From
Junio C Hamano <gitster@pobox.com>
Date
Oct 28, 2015, 15:24 UTC
Message-ID
<xmqqa8r3m2xq.fsf@gitster.mtv.corp.google.com>
In-Reply-To
<20151028140725.GA15304@sigill.intra.peff.net>
Jeff King <peff@peff.net> writes:
Show 50 quoted lines
> Yeah, I can reproduce it easily with that. Thanks for providing the
> repository. It takes a rather convoluted set of conditions to trigger
> the bug. :)
>
> Here's the fix:
>
> -- >8 --
> Subject: add_submodule_odb: initialize alt_odb list earlier
>
> The add_submodule_odb function tries to add a submodule's
> object store as an "alternate". It needs the existing list
> to be initialized (from the objects/info/alternates file)
> for two reasons:
>
>   1. We look for duplicates with the existing alternate
>      stores, but obviously this doesn't work if we haven't
>      loaded any yet.
>
>   2. We link our new entry into the list by prepending it to
>      alt_odb_list. But we do _not_ modify alt_odb_tail.
>      This variable starts as NULL, and is a signal to the
>      alt_odb code that the list has not yet been
>      initialized.
>
>      We then call read_info_alternates on the submodule (to
>      recursively load its alternates), which will try to
>      append to that tail, assuming it has been initialized.
>      This causes us to segfault if it is NULL.
>
> This rarely comes up in practice, because we will have
> initialized the alt_odb any time we do an object lookup. So
> you can trigger this only when:
>
>   - you try to access a submodule (e.g., a diff with
>     diff.submodule=log)
>
>   - the access happens before any other object has been
>     accessed (e.g., because the diff is between the working
>     tree and the index)
>
>   - the submodule contains an alternates file (so we try to
>     add an entry to the NULL alt_odb_tail)
>
> To fix this, we just need to call prepare_alt_odb at the
> start of the function (and if we have already initialized,
> it is a noop).
>
> Note that we can remove the prepare_alt_odb call from the
> end. It is guaranteed to be a noop, since we will have
> called it earlier.
Thanks for a quick and detailed diagnosis and a fix.

The removal is correct, but even without this fix, the order of calls in the original should have screamed "bug" loudly at us, I think. We shouldn't be reading data from alternates file without first preparing the place we read data into.

Show 25 quoted lines
> Signed-off-by: Jeff King <peff@peff.net>
> ---
>  submodule.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/submodule.c b/submodule.c
> index 5879cfb..88af54c 100644
> --- a/submodule.c
> +++ b/submodule.c
> @@ -130,6 +130,7 @@ static int add_submodule_odb(const char *path)
>  		goto done;
>  	}
>  	/* avoid adding it twice */
> +	prepare_alt_odb();
>  	for (alt_odb = alt_odb_list; alt_odb; alt_odb = alt_odb->next)
>  		if (alt_odb->name - alt_odb->base == objects_directory.len &&
>  				!strncmp(alt_odb->base, objects_directory.buf,
> @@ -148,7 +149,6 @@ static int add_submodule_odb(const char *path)
>  
>  	/* add possible alternates from the submodule */
>  	read_info_alternates(objects_directory.buf, 0);
> -	prepare_alt_odb();
>  done:
>  	strbuf_release(&objects_directory);
>  	return ret;
Previous: Jeff KingNext: Jeff King
Message 6 of 7 in “Bug: Segfault when doing "git diff"”
  1. Mathias L. BaumannOct 28, 2015
  2. Victor LeschukOct 28, 2015
  3. Mathias L. BaumannOct 28, 2015
  4. Victor LeschukOct 28, 2015
  5. add_submodule_odb: initialize alt_odb list earlierJeff King, Oct 28, 2015
  6. Junio C HamanoOct 28, 2015
  7. Jeff KingOct 28, 2015

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.