
When passing the `-b` flag to git-blame(1), then any blamed boundary commits which were marked as uninteresting will not get their actual commit ID printed, but will instead be replaced by a couple of spaces. The flag can lead to an out-of-bounds write as though when combined with `--abbrev=` when the abbreviation length is longer than `GIT_MAX_HEXSZ` as we simply use memset(3p) on that array with the user-provided length directly. The result is most likely that we segfault. An obvious fix would be to cull `length` to `GIT_MAX_HEXSZ` many bytes. But when the underlying object ID is SHA1, and if the abbreviated length exceeds the SHA1 length, it would cause us to print more bytes than desired, and the result would be misaligned. Instead, fix the bug by computing the length via strlen(3p). This makes us write as many bytes as the formatted object ID requires and thus effectively limits the length of what we may end up printing to the length of its hash. If `--abbrev=` asks us to abbreviate to something shorter than the full length of the underlying hash function it would be handled by the call to printf(3p) correctly. Signed-off-by: Patrick Steinhardt <ps@pks.im> Signed-off-by: Junio C Hamano <gitster@pobox.com>
171 lines
4.6 KiB
Bash
Executable File
171 lines
4.6 KiB
Bash
Executable File
#!/bin/sh
|
|
|
|
test_description='git blame'
|
|
GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
|
|
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
|
|
|
|
TEST_CREATE_REPO_NO_TEMPLATE=1
|
|
. ./test-lib.sh
|
|
|
|
PROG='git blame -c'
|
|
. "$TEST_DIRECTORY"/annotate-tests.sh
|
|
|
|
test_expect_success 'setup' '
|
|
hexsz=$(test_oid hexsz)
|
|
'
|
|
|
|
test_expect_success 'blame untracked file in empty repo' '
|
|
>untracked &&
|
|
test_must_fail git blame untracked
|
|
'
|
|
|
|
PROG='git blame -c -e'
|
|
test_expect_success 'blame --show-email' '
|
|
check_count \
|
|
"<A@test.git>" 1 \
|
|
"<B@test.git>" 1 \
|
|
"<B1@test.git>" 1 \
|
|
"<B2@test.git>" 1 \
|
|
"<author@example.com>" 1 \
|
|
"<C@test.git>" 1 \
|
|
"<D@test.git>" 1 \
|
|
"<E at test dot git>" 1
|
|
'
|
|
|
|
test_expect_success 'setup showEmail tests' '
|
|
echo "bin: test number 1" >one &&
|
|
git add one &&
|
|
GIT_AUTHOR_NAME=name1 \
|
|
GIT_AUTHOR_EMAIL=email1@test.git \
|
|
git commit -m First --date="2010-01-01 01:00:00" &&
|
|
cat >expected_n <<-\EOF &&
|
|
(name1 2010-01-01 01:00:00 +0000 1) bin: test number 1
|
|
EOF
|
|
cat >expected_e <<-\EOF
|
|
(<email1@test.git> 2010-01-01 01:00:00 +0000 1) bin: test number 1
|
|
EOF
|
|
'
|
|
|
|
find_blame () {
|
|
sed -e 's/^[^(]*//'
|
|
}
|
|
|
|
test_expect_success 'blame with no options and no config' '
|
|
git blame one >blame &&
|
|
find_blame <blame >result &&
|
|
test_cmp expected_n result
|
|
'
|
|
|
|
test_expect_success 'blame with showemail options' '
|
|
git blame --show-email one >blame1 &&
|
|
find_blame <blame1 >result &&
|
|
test_cmp expected_e result &&
|
|
git blame -e one >blame2 &&
|
|
find_blame <blame2 >result &&
|
|
test_cmp expected_e result &&
|
|
git blame --no-show-email one >blame3 &&
|
|
find_blame <blame3 >result &&
|
|
test_cmp expected_n result
|
|
'
|
|
|
|
test_expect_success 'blame with showEmail config false' '
|
|
git config blame.showEmail false &&
|
|
git blame one >blame1 &&
|
|
find_blame <blame1 >result &&
|
|
test_cmp expected_n result &&
|
|
git blame --show-email one >blame2 &&
|
|
find_blame <blame2 >result &&
|
|
test_cmp expected_e result &&
|
|
git blame -e one >blame3 &&
|
|
find_blame <blame3 >result &&
|
|
test_cmp expected_e result &&
|
|
git blame --no-show-email one >blame4 &&
|
|
find_blame <blame4 >result &&
|
|
test_cmp expected_n result
|
|
'
|
|
|
|
test_expect_success 'blame with showEmail config true' '
|
|
git config blame.showEmail true &&
|
|
git blame one >blame1 &&
|
|
find_blame <blame1 >result &&
|
|
test_cmp expected_e result &&
|
|
git blame --no-show-email one >blame2 &&
|
|
find_blame <blame2 >result &&
|
|
test_cmp expected_n result
|
|
'
|
|
|
|
test_expect_success 'set up abbrev tests' '
|
|
test_commit abbrev &&
|
|
sha1=$(git rev-parse --verify HEAD) &&
|
|
check_abbrev () {
|
|
expect=$1 && shift &&
|
|
echo $sha1 | cut -c 1-$expect >expect &&
|
|
git blame "$@" abbrev.t >actual &&
|
|
perl -lne "/[0-9a-f]+/ and print \$&" <actual >actual.sha &&
|
|
test_cmp expect actual.sha
|
|
}
|
|
'
|
|
|
|
test_expect_success 'blame --abbrev=<n> works' '
|
|
# non-boundary commits get +1 for alignment
|
|
check_abbrev 31 --abbrev=30 HEAD &&
|
|
check_abbrev 30 --abbrev=30 ^HEAD
|
|
'
|
|
|
|
test_expect_success 'blame -l aligns regular and boundary commits' '
|
|
check_abbrev $hexsz -l HEAD &&
|
|
check_abbrev $((hexsz - 1)) -l ^HEAD
|
|
'
|
|
|
|
test_expect_success 'blame --abbrev with full length behaves like -l' '
|
|
check_abbrev $hexsz --abbrev=$hexsz HEAD &&
|
|
check_abbrev $((hexsz - 1)) --abbrev=$hexsz ^HEAD
|
|
'
|
|
|
|
test_expect_success '--no-abbrev works like --abbrev with full length' '
|
|
check_abbrev $hexsz --no-abbrev
|
|
'
|
|
|
|
test_expect_success 'blame --abbrev gets truncated' '
|
|
check_abbrev $hexsz --abbrev=9000 HEAD
|
|
'
|
|
|
|
test_expect_success 'blame --abbrev gets truncated with boundary commit' '
|
|
check_abbrev $hexsz --abbrev=9000 ^HEAD
|
|
'
|
|
|
|
test_expect_success 'blame --abbrev -b truncates the blank boundary' '
|
|
# Note that `--abbrev=` always gets incremented by 1, which is why we
|
|
# expect 11 leading spaces and not 10.
|
|
cat >expect <<-EOF &&
|
|
$(printf "%0.s " $(test_seq 11)) (<author@example.com> 2005-04-07 15:45:13 -0700 1) abbrev
|
|
EOF
|
|
git blame -b --abbrev=10 ^HEAD -- abbrev.t >actual &&
|
|
test_cmp expect actual
|
|
'
|
|
|
|
test_expect_success 'blame with excessive --abbrev and -b culls to hash length' '
|
|
cat >expect <<-EOF &&
|
|
$(printf "%0.s " $(test_seq $hexsz)) (<author@example.com> 2005-04-07 15:45:13 -0700 1) abbrev
|
|
EOF
|
|
git blame -b --abbrev=9000 ^HEAD -- abbrev.t >actual &&
|
|
test_cmp expect actual
|
|
'
|
|
|
|
test_expect_success '--exclude-promisor-objects does not BUG-crash' '
|
|
test_must_fail git blame --exclude-promisor-objects one
|
|
'
|
|
|
|
test_expect_success 'blame with uncommitted edits in partial clone does not crash' '
|
|
git init server &&
|
|
echo foo >server/file.txt &&
|
|
git -C server add file.txt &&
|
|
git -C server commit -m file &&
|
|
|
|
git clone --filter=blob:none "file://$(pwd)/server" client &&
|
|
echo bar >>client/file.txt &&
|
|
git -C client blame file.txt
|
|
'
|
|
|
|
test_done
|