sequencer: detect author name errors in read_author_script()

As we parse the author-script file, we check for missing or duplicate lines for GIT_AUTHOR_NAME, etc. But after reading the whole file, our final error conditional checks "date_i" twice and "name_i" not at all. This not only leads to us failing to abort, but we may do an out-of-bounds read on the string_list array. The bug goes back to 442c36bd08 (am: improve author-script error reporting, 2018-10-31), though the code was soon after moved to this spot by bcd33ec25f (add read_author_script() to libgit, 2018-10-31). It was presumably just a typo in 442c36bd08. We'll add test coverage for all the error cases here, though only the GIT_AUTHOR_NAME ones fail (even in a vanilla build they segfault consistently, but certainly with SANITIZE=address). Reported-by: Michael V. Scovetta <michael.scovetta@gmail.com> Signed-off-by: Jeff King <peff@peff.net> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Jeff King committed Oct 3, 2022 at 13:35 UTC 45350aeb11e0d8b5f76a121dfb9fc053af8e6042
2 files changed +60 -1
sequencer.c
+1 -1
@@ -872,7 +872,7 @@ int read_author_script(const char *path, char **name, char **email, char **date,
872 error(_("missing 'GIT_AUTHOR_EMAIL'"));
873 if (date_i == -2)
874 error(_("missing 'GIT_AUTHOR_DATE'"));
875 - if (date_i < 0 || email_i < 0 || date_i < 0 || err)
875 + if (name_i < 0 || email_i < 0 || date_i < 0 || err)
876 goto finish;
877 *name = kv.items[name_i].util;
878 *email = kv.items[email_i].util;
t/t3438-rebase-broken-files.sh new
+59
@@ -0,0 +1,59 @@
1 +#!/bin/sh
2 +
3 +test_description='rebase behavior when on-disk files are broken'
4 +. ./test-lib.sh
5 +
6 +test_expect_success 'set up conflicting branches' '
7 + test_commit base file &&
8 + git checkout -b branch1 &&
9 + test_commit one file &&
10 + git checkout -b branch2 HEAD^ &&
11 + test_commit two file
12 +'
13 +
14 +create_conflict () {
15 + test_when_finished "git rebase --abort" &&
16 + git checkout -B tmp branch2 &&
17 + test_must_fail git rebase branch1
18 +}
19 +
20 +check_resolve_fails () {
21 + echo resolved >file &&
22 + git add file &&
23 + test_must_fail git rebase --continue
24 +}
25 +
26 +for item in NAME EMAIL DATE
27 +do
28 + test_expect_success "detect missing GIT_AUTHOR_$item" '
29 + create_conflict &&
30 +
31 + grep -v $item .git/rebase-merge/author-script >tmp &&
32 + mv tmp .git/rebase-merge/author-script &&
33 +
34 + check_resolve_fails
35 + '
36 +done
37 +
38 +for item in NAME EMAIL DATE
39 +do
40 + test_expect_success "detect duplicate GIT_AUTHOR_$item" '
41 + create_conflict &&
42 +
43 + grep -i $item .git/rebase-merge/author-script >tmp &&
44 + cat tmp >>.git/rebase-merge/author-script &&
45 +
46 + check_resolve_fails
47 + '
48 +done
49 +
50 +test_expect_success 'unknown key in author-script' '
51 + create_conflict &&
52 +
53 + echo "GIT_AUTHOR_BOGUS=${SQ}whatever${SQ}" \
54 + >>.git/rebase-merge/author-script &&
55 +
56 + check_resolve_fails
57 +'
58 +
59 +test_done