Re: Segfault in `git describe`

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

 



On Mon, Jul 15, 2013 at 4:03 PM, Michael Haggerty <mhagger@xxxxxxxxxxxx> wrote:
> On 07/13/2013 03:27 PM, Mantas Mikulėnas wrote:
>> I have a clone of linux.git with various stuff added to it (remotes for
>> 'stable' and 'next', a bunch of local tags, and historical repositories
>> imported using `git replace`).
>>
>> Yesterday, I noticed that `git describe`, built from git.git master
>> (v1.8.3.2-804-g0da7a53, gcc 4.8) would simply crash when run in that
>> repository, with the following backtrace:
>>
>>> Program terminated with signal 11, Segmentation fault.
>>> #0  0x00000000004c39dc in hashcpy (sha_src=0x1c <Address 0x1c out of bounds>,
>>>     sha_dst=0x7fffc0b4d610 "\242\271\301\366 \201&\346\337l\002B\214P\037\210ShX\022")
>>>     at cache.h:694
>>> 694          memcpy(sha_dst, sha_src, 20);
>>> (gdb) bt
>>> #0  0x00000000004c39dc in hashcpy (sha_src=0x1c <Address 0x1c out of bounds>,
>>>     sha_dst=0x7fffc0b4d610 "\242\271\301\366 \201&\346\337l\002B\214P\037\210ShX\022")
>>>     at cache.h:694
>>> #1  peel_ref (refname=refname@entry=0x1fe2d10 "refs/tags/next-20130607",
>>>     sha1=sha1@entry=0x7fffc0b4d610 "\242\271\301\366 \201&\346\337l\002B\214P\037\210ShX\022") at refs.c:1586
>>> #2  0x0000000000424194 in get_name (path=0x1fe2d10 "refs/tags/next-20130607",
>>>     sha1=0x1fe2ce8 "\222V\356\276S5\tk\231Hi\264\r=\336\315\302\225\347\257\300N\376\327\064@\237ZDq[T\246\312\033T\260\314\362\025refs/tags/next-20130607", flag=<optimized out>,
>>>     cb_data=<optimized out>) at builtin/describe.c:156
>>> #3  0x00000000004c1c21 in do_one_ref (entry=0x1fe2ce0, cb_data=0x7fffc0b4d7c0)
>>>     at refs.c:646
>>> #4  0x00000000004c318d in do_for_each_entry_in_dir (dir=0x1fe1728,
>>>     offset=<optimized out>, fn=0x4c1bc0 <do_one_ref>, cb_data=0x7fffc0b4d7c0)
>>>     at refs.c:672
>>> #5  0x00000000004c33d1 in do_for_each_entry_in_dirs (dir1=0x1fdf4d8, dir2=0x1fd6318,
>>>     cb_data=0x7fffc0b4d7c0, fn=0x4c1bc0 <do_one_ref>) at refs.c:716
>>> #6  0x00000000004c33d1 in do_for_each_entry_in_dirs (dir1=0x1fdf1f8, dir2=0x1fd62d8,
>>>     cb_data=0x7fffc0b4d7c0, fn=0x4c1bc0 <do_one_ref>) at refs.c:716
>>> #7  0x00000000004c3540 in do_for_each_entry (refs=refs@entry=0x7a2800 <ref_cache>,
>>>     base=base@entry=0x509cc6 "", cb_data=cb_data@entry=0x7fffc0b4d7c0,
>>>     fn=0x4c1bc0 <do_one_ref>) at refs.c:1689
>>> #8  0x00000000004c3ff8 in do_for_each_ref (cb_data=cb_data@entry=0x0, flags=1, trim=0,
>>>     fn=fn@entry=0x424120 <get_name>, base=0x509cc6 "", refs=0x7a2800 <ref_cache>)
>>>     at refs.c:1724
>>> #9  for_each_rawref (fn=fn@entry=0x424120 <get_name>, cb_data=cb_data@entry=0x0)
>>>     at refs.c:1873
>>> #10 0x0000000000424f5b in cmd_describe (argc=0, argv=0x7fffc0b4ddc0, prefix=0x0)
>>>     at builtin/describe.c:466
>>> #11 0x000000000040596d in run_builtin (argv=0x7fffc0b4ddc0, argc=1,
>>>     p=0x760b40 <commands.21352+576>) at git.c:291
>>> #12 handle_internal_command (argc=1, argv=0x7fffc0b4ddc0) at git.c:453
>>> #13 0x0000000000404d6e in run_argv (argv=0x7fffc0b4dc78, argcp=0x7fffc0b4dc5c)
>>>     at git.c:499
>>> #14 main (argc=1, av=<optimized out>) at git.c:575
>>> (gdb)
>>
>> According to `git bisect`, the first bad commit is:
>>
>> commit 9a489f3c17d6c974b18c47cf406404ca2a721c87
>> Author: Michael Haggerty <mhagger@xxxxxxxxxxxx>
>> Date:   Mon Apr 22 21:52:22 2013 +0200
>>
>>     refs: extract a function peel_entry()
>>
>> The crash happens only in repositories that have at least one replaced
>> object in the branch's history. Running `git --no-replace-objects
>> describe` avoids the crash.
>>
>> The crash happens only if there are any tags under .git/refs/tags/ that
>> do not exist in .git/packed-refs, or if I remove all "peeled" lines from
>> .git/packed-refs (including the '#' line; /^[#^]/d).
>>
>> A quick way to reproduce this with git.git master is:
>>
>> git tag -f test-tag HEAD~10
>> git replace -f HEAD $(git --no-replace-objects cat-file commit HEAD \
>>   | sed 's/@/@test/' | git hash-object --stdin -t commit -w)
>> ./git describe
>
> Thanks for the bug report.
>
> I think the cause of this bug is that peel_entry() is causing a nested
> call to do_for_each_entry() to look up the replace reference, which
> resets current_ref to NULL between the test and the dereference of
> current_ref in peel_ref().
>
> Unfortunately, I cannot reproduce the failure by following your recipe
> (though I didn't have a lot of time yet for this).  I suppose that my
> repo starts out in a slightly different state than yours and therefore I
> don't get the same results.  If you could find a recipe to reproduce the
> problem, starting either with an empty repo, or perhaps a fresh clone of
> git.git, and double-check that you don't have any unusual config options
> that might be affecting things, that would be very helpful.

Hmm, yes, just creating a new tag doesn't break in another
freshly-cloned repo, either.

However,

> …or if I remove all "peeled" lines from .git/packed-refs (including the '#' line; /^[#^]/d).

still works for reproducing the crash. When packed-refs does not have
any peeled refs, older git versions do it manually (I assume for
compatibility with even older git versions), while the latest one
crashes. This recipe should work:

git pack-refs --all --prune
sed -i '/^[#^]/d' .git/packed-refs
git replace -f HEAD $(git --no-replace-objects cat-file commit HEAD \
    | sed 's/@/@test/' | git hash-object --stdin -t commit -w)
~/src/git/git describe

--
Mantas Mikulėnas <grawity@xxxxxxxxx>
--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html




[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]