1
0
Fork 0
mirror of https://github.com/git/git.git synced 2024-05-29 00:26:12 +02:00
git/t/t4126-apply-empty.sh

95 lines
2.4 KiB
Bash
Raw Normal View History

#!/bin/sh
test_description='apply empty'
TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
test_expect_success setup '
>empty &&
git add empty &&
test_tick &&
git commit -m initial &&
git commit --allow-empty -m "empty commit" &&
git format-patch --always HEAD~ >empty.patch &&
test_write_lines a b c d e >empty &&
cat empty >expect &&
git diff |
sed -e "/^diff --git/d" \
-e "/^index /d" \
-e "s|a/empty|empty.orig|" \
-e "s|b/empty|empty|" >patch0 &&
sed -e "s|empty|missing|" patch0 >patch1 &&
>empty &&
git update-index --refresh
'
test_expect_success 'apply empty' '
rm -f missing &&
test_when_finished "git reset --hard" &&
git apply patch0 &&
test_cmp expect empty
'
test_expect_success 'apply empty patch fails' '
test_when_finished "git reset --hard" &&
test_must_fail git apply empty.patch &&
test_must_fail git apply - </dev/null
'
test_expect_success 'apply with --allow-empty succeeds' '
test_when_finished "git reset --hard" &&
git apply --allow-empty empty.patch &&
git apply --allow-empty - </dev/null
'
test_expect_success 'apply --index empty' '
rm -f missing &&
test_when_finished "git reset --hard" &&
git apply --index patch0 &&
test_cmp expect empty &&
git diff --exit-code
'
test_expect_success 'apply create' '
rm -f missing &&
test_when_finished "git reset --hard" &&
git apply patch1 &&
test_cmp expect missing
'
test_expect_success 'apply --index create' '
rm -f missing &&
test_when_finished "git reset --hard" &&
git apply --index patch1 &&
test_cmp expect missing &&
git diff --exit-code
'
test_expect_success 'parsing a patch with no-contents and a funny pathname' '
apply: parse names out of "diff --git" more carefully "git apply" uses the pathname parsed out of the "diff --git" header to decide which path is being patched, but this is used only when there is no other names available in the patch. When there is any content change (like we can see in this patch, that modifies the contents of "apply.c") or rename (which comes with "rename from" and "rename to" extended diff headers), the names are available without having to parse this header. When we do need to parse this header, a special care needs to be taken, as the name of a directory or a file can have a SP in it so it is not like "find a space, and take everything before the space and that is the preimage filename, everything after the space is the postimage filename". We have a loop that stops at every SP on the "diff --git a/dir/file b/dir/foo" line and see if that SP is the right place that separates such a pair of names. Unfortunately, this loop can terminate prematurely when a crafted directory name ended with a SP. The next pathname component after that SP (i.e. the beginning of the possible postimage filename) will be a slash, and instead of rejecting that position as the valid separation point between pre- and post-image filenames and keep looping, we stopped processing right there. The fix is simple. Instead of stopping and giving up, keep going on when we see such a condition. Reported-by: Han Young <hanyang.tony@bytedance.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2024-03-19 23:56:44 +01:00
git reset --hard &&
empty_blob=$(test_oid empty_blob) &&
echo "$empty_blob" >expect &&
apply: parse names out of "diff --git" more carefully "git apply" uses the pathname parsed out of the "diff --git" header to decide which path is being patched, but this is used only when there is no other names available in the patch. When there is any content change (like we can see in this patch, that modifies the contents of "apply.c") or rename (which comes with "rename from" and "rename to" extended diff headers), the names are available without having to parse this header. When we do need to parse this header, a special care needs to be taken, as the name of a directory or a file can have a SP in it so it is not like "find a space, and take everything before the space and that is the preimage filename, everything after the space is the postimage filename". We have a loop that stops at every SP on the "diff --git a/dir/file b/dir/foo" line and see if that SP is the right place that separates such a pair of names. Unfortunately, this loop can terminate prematurely when a crafted directory name ended with a SP. The next pathname component after that SP (i.e. the beginning of the possible postimage filename) will be a slash, and instead of rejecting that position as the valid separation point between pre- and post-image filenames and keep looping, we stopped processing right there. The fix is simple. Instead of stopping and giving up, keep going on when we see such a condition. Reported-by: Han Young <hanyang.tony@bytedance.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2024-03-19 23:56:44 +01:00
git update-index --add --cacheinfo "100644,$empty_blob,funny /empty" &&
git diff --cached HEAD -- "funny /" >sample.patch &&
git diff --cached -R HEAD -- "funny /" >elpmas.patch &&
git reset &&
apply: parse names out of "diff --git" more carefully "git apply" uses the pathname parsed out of the "diff --git" header to decide which path is being patched, but this is used only when there is no other names available in the patch. When there is any content change (like we can see in this patch, that modifies the contents of "apply.c") or rename (which comes with "rename from" and "rename to" extended diff headers), the names are available without having to parse this header. When we do need to parse this header, a special care needs to be taken, as the name of a directory or a file can have a SP in it so it is not like "find a space, and take everything before the space and that is the preimage filename, everything after the space is the postimage filename". We have a loop that stops at every SP on the "diff --git a/dir/file b/dir/foo" line and see if that SP is the right place that separates such a pair of names. Unfortunately, this loop can terminate prematurely when a crafted directory name ended with a SP. The next pathname component after that SP (i.e. the beginning of the possible postimage filename) will be a slash, and instead of rejecting that position as the valid separation point between pre- and post-image filenames and keep looping, we stopped processing right there. The fix is simple. Instead of stopping and giving up, keep going on when we see such a condition. Reported-by: Han Young <hanyang.tony@bytedance.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2024-03-19 23:56:44 +01:00
git apply --cached --stat --check --apply sample.patch &&
git rev-parse --verify ":funny /empty" >actual &&
test_cmp expect actual &&
apply: parse names out of "diff --git" more carefully "git apply" uses the pathname parsed out of the "diff --git" header to decide which path is being patched, but this is used only when there is no other names available in the patch. When there is any content change (like we can see in this patch, that modifies the contents of "apply.c") or rename (which comes with "rename from" and "rename to" extended diff headers), the names are available without having to parse this header. When we do need to parse this header, a special care needs to be taken, as the name of a directory or a file can have a SP in it so it is not like "find a space, and take everything before the space and that is the preimage filename, everything after the space is the postimage filename". We have a loop that stops at every SP on the "diff --git a/dir/file b/dir/foo" line and see if that SP is the right place that separates such a pair of names. Unfortunately, this loop can terminate prematurely when a crafted directory name ended with a SP. The next pathname component after that SP (i.e. the beginning of the possible postimage filename) will be a slash, and instead of rejecting that position as the valid separation point between pre- and post-image filenames and keep looping, we stopped processing right there. The fix is simple. Instead of stopping and giving up, keep going on when we see such a condition. Reported-by: Han Young <hanyang.tony@bytedance.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2024-03-19 23:56:44 +01:00
git apply --cached --stat --check --apply elpmas.patch &&
test_must_fail git rev-parse --verify ":funny /empty" &&
apply: parse names out of "diff --git" more carefully "git apply" uses the pathname parsed out of the "diff --git" header to decide which path is being patched, but this is used only when there is no other names available in the patch. When there is any content change (like we can see in this patch, that modifies the contents of "apply.c") or rename (which comes with "rename from" and "rename to" extended diff headers), the names are available without having to parse this header. When we do need to parse this header, a special care needs to be taken, as the name of a directory or a file can have a SP in it so it is not like "find a space, and take everything before the space and that is the preimage filename, everything after the space is the postimage filename". We have a loop that stops at every SP on the "diff --git a/dir/file b/dir/foo" line and see if that SP is the right place that separates such a pair of names. Unfortunately, this loop can terminate prematurely when a crafted directory name ended with a SP. The next pathname component after that SP (i.e. the beginning of the possible postimage filename) will be a slash, and instead of rejecting that position as the valid separation point between pre- and post-image filenames and keep looping, we stopped processing right there. The fix is simple. Instead of stopping and giving up, keep going on when we see such a condition. Reported-by: Han Young <hanyang.tony@bytedance.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2024-03-19 23:56:44 +01:00
git apply -R --cached --stat --check --apply elpmas.patch &&
git rev-parse --verify ":funny /empty" >actual &&
test_cmp expect actual &&
git apply -R --cached --stat --check --apply sample.patch &&
test_must_fail git rev-parse --verify ":funny /empty"
apply: parse names out of "diff --git" more carefully "git apply" uses the pathname parsed out of the "diff --git" header to decide which path is being patched, but this is used only when there is no other names available in the patch. When there is any content change (like we can see in this patch, that modifies the contents of "apply.c") or rename (which comes with "rename from" and "rename to" extended diff headers), the names are available without having to parse this header. When we do need to parse this header, a special care needs to be taken, as the name of a directory or a file can have a SP in it so it is not like "find a space, and take everything before the space and that is the preimage filename, everything after the space is the postimage filename". We have a loop that stops at every SP on the "diff --git a/dir/file b/dir/foo" line and see if that SP is the right place that separates such a pair of names. Unfortunately, this loop can terminate prematurely when a crafted directory name ended with a SP. The next pathname component after that SP (i.e. the beginning of the possible postimage filename) will be a slash, and instead of rejecting that position as the valid separation point between pre- and post-image filenames and keep looping, we stopped processing right there. The fix is simple. Instead of stopping and giving up, keep going on when we see such a condition. Reported-by: Han Young <hanyang.tony@bytedance.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2024-03-19 23:56:44 +01:00
'
test_done