Thomas Gummerer <t.gummerer@xxxxxxxxx> writes: > Subject: [PATCH] blame: fix segfault on untracked files > > Since 3b75ee9 ("blame: allow to blame paths freshly added to the index", > 2016-07-16) git blame also looks at the index to determine if there is a > file that was freshly added to the index. > > cache_name_pos returns -pos - 1 in case there is no match is found, or > if the name matches, but the entry has a stage other than 0. As git > blame should work for unmerged files, it uses strcmp to determine > whether the name of the returned position matches, in which case the > file exists, but is merely unmerged, or if the file actually doesn't > exist in the index. > > If the repository is empty, or if the file would lexicographically be > sorted as the last file in the repository, -cache_name_pos - 1 is > outside of the length of the active_cache array, causing git blame to > segfault. Guard against that, and die() normally to restore the old > behaviour. > > Reported-by: Simon Ruderich <simon@xxxxxxxxxxxx> > Signed-off-by: Thomas Gummerer <t.gummerer@xxxxxxxxx> > --- This is a recent regression and unfortunately is also in 2.9.3; the patch looks obviously correct. > builtin/blame.c | 3 ++- > t/t8002-blame.sh | 7 +++++++ > 2 files changed, 9 insertions(+), 1 deletion(-) > > diff --git a/builtin/blame.c b/builtin/blame.c > index 7ec7823..a5bbf91 100644 > --- a/builtin/blame.c > +++ b/builtin/blame.c > @@ -2244,7 +2244,8 @@ static void verify_working_tree_path(struct commit *work_tree, const char *path) > pos = cache_name_pos(path, strlen(path)); > if (pos >= 0) > ; /* path is in the index */ > - else if (!strcmp(active_cache[-1 - pos]->name, path)) > + else if (-1 - pos < active_nr && > + !strcmp(active_cache[-1 - pos]->name, path)) > ; /* path is in the index, unmerged */ > else > die("no such path '%s' in HEAD", path); > diff --git a/t/t8002-blame.sh b/t/t8002-blame.sh > index ff09ace..7983bb7 100755 > --- a/t/t8002-blame.sh > +++ b/t/t8002-blame.sh > @@ -6,6 +6,13 @@ test_description='git blame' > PROG='git blame -c' > . "$TEST_DIRECTORY"/annotate-tests.sh > > +test_expect_success 'blame untracked file in empty repo' ' > + touch untracked && > + test_must_fail git blame untracked 2>actual.err && > + echo "fatal: no such path '\''untracked'\'' in HEAD" >expected.err && > + test_cmp expected.err actual.err > +' The point of this fix is not that we show the exact error message, but we fail in a controlled manner. I think test_expect_success 'blame untracked file in empty repo' ' >untracked && test_must_fail git blame untracked ' is sufficient. Thanks. > PROG='git blame -c -e' > test_expect_success 'blame --show-email' ' > check_count \