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

Re: git 2.40.1 tree-diff crashes with (glob) magic on pathspecs

From
JPJim Pryor <dubiousjim@gmail.com>
Date
May 27, 2023, 19:00 UTC
Message-ID
<51012e79-c6ce-41dd-9755-960e065214ef@app.fastmail.com>
In-Reply-To
<20230527173903.GB1460206@coredump.intra.peff.net>
On Sat, May 27, 2023, at 7:39 PM, Jeff King wrote:
Show 99 quoted lines
> On Sat, May 27, 2023 at 03:53:31PM +0200, Jim Pryor wrote:
>
>> $ git --no-pager log --oneline -- ':(glob)**/test2'
>> 
>> What did you expect to happen? (Expected behavior)
>> 
>> 13a1b11 (HEAD -> master) third commit
>> 2bacc0c second commit
>> c6eb1c1 first commit
>> 
>> What happened instead? (Actual behavior)
>> 
>> 13a1b11 (HEAD -> master) third commit
>> BUG: tree-diff.c:596: unsupported magic 8
>> error: git died of signal 6
>
> Thanks for your report. I had trouble reproducing at first, but there is
> one extra twist. By default, the command you gave produces:
>
>   $ git --no-pager log --oneline -- ':(glob)**/test2'
>   48eab09 (HEAD -> main) third commit
>   89a47e5 second commit
>
> which makes sense; we did not ask about "test", which is the path the
> original commit touched. So I guessed you might have log.follow set, and
> indeed:
>
>   $ git --no-pager log --oneline --follow -- ':(glob)**/test2'
>   48eab09 (HEAD -> main) third commit
>   BUG: tree-diff.c:596: unsupported magic 8
>   Aborted
>
> I _think_ in this case that ":(glob)" is not actually doing much. It is
> already the default that we will glob pathspecs; it is only needed to
> override "git --literal" (which changes the default to not glob).
>
> But this also seems to be wading into a spot that is not actually
> supported by --follow. The code near where the BUG() is triggered looks
> like this:
>
> static void try_to_follow_renames([...])
> {
> [...]
>         /*
>          * follow-rename code is very specific, we need exactly one
>          * path. Magic that matches more than one path is not
>          * supported.
>          */
>         GUARD_PATHSPEC(&opt->pathspec, PATHSPEC_FROMTOP | PATHSPEC_LITERAL);
> #if 0
>         /*
>          * We should reject wildcards as well. Unfortunately we
>          * haven't got a reliable way to detect that 'foo\*bar' in
>          * fact has no wildcards. nowildcard_len is merely a hint for
>          * optimization. Let it slip for now until wildmatch is taught
>          * about dry-run mode and returns wildcard info.
>          */
>         if (opt->pathspec.has_wildcard)
>                 BUG("wildcards are not supported");
> #endif
>
> So follow-mode does not actually work with wildcards, but we err on the
> side of not rejecting them outright. In that sense, the simplest "fix"
> here would be to allow :(glob) to match the '#if 0' section, like:
>
> diff --git a/tree-diff.c b/tree-diff.c
> index 69031d7cba..d287079253 100644
> --- a/tree-diff.c
> +++ b/tree-diff.c
> @@ -593,7 +593,8 @@ static void try_to_follow_renames(const struct 
> object_id *old_oid,
>  	 * path. Magic that matches more than one path is not
>  	 * supported.
>  	 */
> -	GUARD_PATHSPEC(&opt->pathspec, PATHSPEC_FROMTOP | PATHSPEC_LITERAL);
> +	GUARD_PATHSPEC(&opt->pathspec,
> +		       PATHSPEC_FROMTOP | PATHSPEC_LITERAL | PATHSPEC_GLOB);
>  #if 0
>  	/*
>  	 * We should reject wildcards as well. Unfortunately we
>
> That would avoid the BUG() and make things work consistently. But it
> still would not produce the output you expect, because --follow simply
> does not work with wildcard pathspecs. And fixing that would presumably
> be a much bigger change (I didn't dig into it).
>
> Complicating this slightly is the fact that you didn't explicitly ask
> for --follow, but just had log.follow set. I think we automatically
> disable log.follow when there is more than one pathspec, and in theory
> we ought to do the same for actual wildcards. But maybe it would be
> enough for follow-mode to kick in, but to end up mostly ignored (which
> is what the patch above would do).
>
> (I say "mostly" because I suspect you could construct a history where
> the glob matched a literal filename, too, and the follow code gets
> confused. But outside of intentionally-constructed pathological cases,
> that seems unlikely).
>
> -Peff
Confirmed I have log.follow = true, and also GIT_NOGLOB_PATHSPECS set, thus the explicit `(glob)` magic.
I'd be happy with --follow not working with the wildcard pathspecs, but with the crash avoided.
-- 
dubiousjim@gmail.com
Previous: Jeff KingNext: Jeff King
Message 3 of 12 in “git 2.40.1 tree-diff crashes with (glob) magic on pathspecs”
  1. Jim PryorMay 27, 2023
  2. Jeff KingMay 27, 2023
  3. Jim PryorMay 27, 2023
  4. 0/3 handling pathspec magic with --followJeff King, Jun 1, 2023
  5. 1/3 pathspec: factor out magic-to-name functionJeff King, Jun 1, 2023
  6. 2/3 diff: factor out --follow pathspec checkJeff King, Jun 1, 2023
  7. 3/3 diff: detect pathspec magic not supported by --followJeff King, Jun 1, 2023
  8. Junio C HamanoJun 2, 2023
  9. Jeff KingJun 15, 2023
  10. Junio C HamanoJun 15, 2023
  11. Junio C HamanoJun 1, 2023
  12. Jeff KingJun 1, 2023

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.