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

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Sat, May 27, 2023, at 7:39 PM, Jeff King wrote:
> 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@xxxxxxxxx



[Index of Archives]     [Linux Kernel Development]     [Gcc Help]     [IETF Annouce]     [DCCP]     [Netdev]     [Networking]     [Security]     [V4L]     [Bugtraq]     [Yosemite]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux SCSI]     [Fedora Users]

  Powered by Linux