git/t/t3436-rebase-more-options.sh
Ævar Arnfjörð Bjarmason 15a4cc912e sequencer.c: fix overflow & segfault in parse_strategy_opts()
The split_cmdline() function introduced in [1] returns an "int". If
it's negative it signifies an error. The option parsing in [2] didn't
account for this, and assigned the value directly to the "size_t
xopts_nr". We'd then attempt to loop over all of these elements, and
access uninitialized memory.

There's a few things that use this for option parsing, but one way to
trigger it is with a bad value to "-X <strategy-option>", e.g:

	git rebase -X"bad argument\""

In another context this might be a security issue, but in this case
someone who's already able to inject arguments directly to our
commands would be past other defenses, making this potential
escalation a moot point.

As the example above & test case shows the error reporting leaves
something to be desired. The function will loop over the
whitespace-split values, but when it encounters an error we'll only
report the first element, which is OK, not the second "argument\""
whose quote is unbalanced.

This is an inherent limitation of the current API, and the issue
affects other API users. Let's not attempt to fix that now. If and
when that happens these tests will need to be adjusted to assert the
new output.

1. 2b11e3170e (If you have a config containing something like this:,
   2006-06-05)
2. ca6c6b45dd (sequencer (rebase -i): respect strategy/strategy_opts
   settings, 2017-01-02)

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2023-03-08 14:14:42 -08:00

228 lines
6.9 KiB
Bash
Executable file

#!/bin/sh
#
# Copyright (c) 2019 Rohit Ashiwal
#
test_description='tests to ensure compatibility between am and interactive backends'
. ./test-lib.sh
. "$TEST_DIRECTORY"/lib-rebase.sh
GIT_AUTHOR_DATE="1999-04-02T08:03:20+05:30"
export GIT_AUTHOR_DATE
# This is a special case in which both am and interactive backends
# provide the same output. It was done intentionally because
# both the backends fall short of optimal behaviour.
test_expect_success 'setup' '
git checkout -b topic &&
test_write_lines "line 1" " line 2" "line 3" >file &&
git add file &&
git commit -m "add file" &&
test_write_lines "line 1" "new line 2" "line 3" >file &&
git commit -am "update file" &&
git tag side &&
test_commit commit1 foo foo1 &&
test_commit commit2 foo foo2 &&
test_commit commit3 foo foo3 &&
git checkout --orphan main &&
rm foo &&
test_write_lines "line 1" " line 2" "line 3" >file &&
git commit -am "add file" &&
git tag main &&
mkdir test-bin &&
write_script test-bin/git-merge-test <<-\EOF
exec git merge-recursive "$@"
EOF
'
test_expect_success 'bad -X <strategy-option> arguments: unclosed quote' '
cat >expect <<-\EOF &&
fatal: could not split '\''--bad'\'': unclosed quote
EOF
test_expect_code 128 git rebase -X"bad argument\"" side main >out 2>actual &&
test_must_be_empty out &&
test_cmp expect actual
'
test_expect_success 'bad -X <strategy-option> arguments: bad escape' '
cat >expect <<-\EOF &&
fatal: could not split '\''--bad'\'': cmdline ends with \
EOF
test_expect_code 128 git rebase -X"bad escape \\" side main >out 2>actual &&
test_must_be_empty out &&
test_cmp expect actual
'
test_expect_success '--ignore-whitespace works with apply backend' '
test_must_fail git rebase --apply main side &&
git rebase --abort &&
git rebase --apply --ignore-whitespace main side &&
git diff --exit-code side
'
test_expect_success '--ignore-whitespace works with merge backend' '
test_must_fail git rebase --merge main side &&
git rebase --abort &&
git rebase --merge --ignore-whitespace main side &&
git diff --exit-code side
'
test_expect_success '--ignore-whitespace is remembered when continuing' '
(
set_fake_editor &&
FAKE_LINES="break 1" git rebase -i --ignore-whitespace \
main side &&
git rebase --continue
) &&
git diff --exit-code side
'
test_ctime_is_atime () {
git log $1 --format="$GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> %ai" >authortime &&
git log $1 --format="%cn <%ce> %ci" >committertime &&
test_cmp authortime committertime
}
test_expect_success '--committer-date-is-author-date works with apply backend' '
GIT_AUTHOR_DATE="@1234 +0300" git commit --amend --reset-author &&
git rebase --apply --committer-date-is-author-date HEAD^ &&
test_ctime_is_atime -1
'
test_expect_success '--committer-date-is-author-date works with merge backend' '
GIT_AUTHOR_DATE="@1234 +0300" git commit --amend --reset-author &&
git rebase -m --committer-date-is-author-date HEAD^ &&
test_ctime_is_atime -1
'
test_expect_success '--committer-date-is-author-date works when rewording' '
GIT_AUTHOR_DATE="@1234 +0300" git commit --amend --reset-author &&
(
set_fake_editor &&
FAKE_COMMIT_MESSAGE=edited \
FAKE_LINES="reword 1" \
git rebase -i --committer-date-is-author-date HEAD^
) &&
test_write_lines edited "" >expect &&
git log --format="%B" -1 >actual &&
test_cmp expect actual &&
test_ctime_is_atime -1
'
test_expect_success '--committer-date-is-author-date works with rebase -r' '
git checkout side &&
GIT_AUTHOR_DATE="@1234 +0300" git merge --no-ff commit3 &&
git rebase -r --root --committer-date-is-author-date &&
test_ctime_is_atime
'
test_expect_success '--committer-date-is-author-date works when forking merge' '
git checkout side &&
GIT_AUTHOR_DATE="@1234 +0300" git merge --no-ff commit3 &&
PATH="./test-bin:$PATH" git rebase -r --root --strategy=test \
--committer-date-is-author-date &&
test_ctime_is_atime
'
test_expect_success '--committer-date-is-author-date works when committing conflict resolution' '
git checkout commit2 &&
GIT_AUTHOR_DATE="@1980 +0000" git commit --amend --only --reset-author &&
test_must_fail git rebase -m --committer-date-is-author-date \
--onto HEAD^^ HEAD^ &&
echo resolved > foo &&
git add foo &&
git rebase --continue &&
test_ctime_is_atime -1
'
# Checking for +0000 in the author date is sufficient since the
# default timezone is UTC but the timezone used while committing is
# +0530. The inverted logic in the grep is necessary to check all the
# author dates in the file.
test_atime_is_ignored () {
git log $1 --format=%ai >authortime &&
! grep -v +0000 authortime
}
test_expect_success '--reset-author-date works with apply backend' '
git commit --amend --date="$GIT_AUTHOR_DATE" &&
git rebase --apply --reset-author-date HEAD^ &&
test_atime_is_ignored -1
'
test_expect_success '--reset-author-date works with merge backend' '
git commit --amend --date="$GIT_AUTHOR_DATE" &&
git rebase --reset-author-date -m HEAD^ &&
test_atime_is_ignored -1
'
test_expect_success '--reset-author-date works after conflict resolution' '
test_must_fail git rebase --reset-author-date -m \
--onto commit2^^ commit2^ commit2 &&
echo resolved >foo &&
git add foo &&
git rebase --continue &&
test_atime_is_ignored -1
'
test_expect_success '--reset-author-date works with rebase -r' '
git checkout side &&
git merge --no-ff commit3 &&
git rebase -r --root --reset-author-date &&
test_atime_is_ignored
'
test_expect_success '--reset-author-date with --committer-date-is-author-date works' '
test_must_fail git rebase -m --committer-date-is-author-date \
--reset-author-date --onto commit2^^ commit2^ commit3 &&
git checkout --theirs foo &&
git add foo &&
git rebase --continue &&
test_ctime_is_atime -2 &&
test_atime_is_ignored -2
'
test_expect_success 'reset-author-date with --committer-date-is-author-date works when rewording' '
GIT_AUTHOR_DATE="@1234 +0300" git commit --amend --reset-author &&
(
set_fake_editor &&
FAKE_COMMIT_MESSAGE=edited \
FAKE_LINES="reword 1" \
git rebase -i --committer-date-is-author-date \
--reset-author-date HEAD^
) &&
test_write_lines edited "" >expect &&
git log --format="%B" -1 >actual &&
test_cmp expect actual &&
test_atime_is_ignored -1
'
test_expect_success '--reset-author-date --committer-date-is-author-date works when forking merge' '
GIT_SEQUENCE_EDITOR="echo \"merge -C $(git rev-parse HEAD) commit3\">" \
PATH="./test-bin:$PATH" git rebase -i --strategy=test \
--reset-author-date \
--committer-date-is-author-date side side &&
test_ctime_is_atime -1 &&
test_atime_is_ignored -1
'
test_expect_success '--ignore-date is an alias for --reset-author-date' '
git commit --amend --date="$GIT_AUTHOR_DATE" &&
git rebase --apply --ignore-date HEAD^ &&
git commit --allow-empty -m empty --date="$GIT_AUTHOR_DATE" &&
git rebase -m --ignore-date HEAD^ &&
test_atime_is_ignored -2
'
# This must be the last test in this file
test_expect_success '$EDITOR and friends are unchanged' '
test_editor_unchanged
'
test_done