|
|
|
#!/bin/sh
|
|
|
|
|
|
|
|
test_description='paths written by git-apply cannot escape the working tree'
|
|
|
|
. ./test-lib.sh
|
|
|
|
|
|
|
|
# tests will try to write to ../foo, and we do not
|
|
|
|
# want them to escape the trash directory when they
|
|
|
|
# fail
|
|
|
|
test_expect_success 'bump git repo one level down' '
|
|
|
|
mkdir inside &&
|
|
|
|
mv .git inside/ &&
|
|
|
|
cd inside
|
|
|
|
'
|
|
|
|
|
|
|
|
# $1 = name of file
|
|
|
|
# $2 = current path to file (if different)
|
|
|
|
mkpatch_add () {
|
|
|
|
rm -f "${2:-$1}" &&
|
|
|
|
cat <<-EOF
|
|
|
|
diff --git a/$1 b/$1
|
|
|
|
new file mode 100644
|
|
|
|
index 0000000..53c74cd
|
|
|
|
--- /dev/null
|
|
|
|
+++ b/$1
|
|
|
|
@@ -0,0 +1 @@
|
|
|
|
+evil
|
|
|
|
EOF
|
|
|
|
}
|
|
|
|
|
|
|
|
mkpatch_del () {
|
|
|
|
echo evil >"${2:-$1}" &&
|
|
|
|
cat <<-EOF
|
|
|
|
diff --git a/$1 b/$1
|
|
|
|
deleted file mode 100644
|
|
|
|
index 53c74cd..0000000
|
|
|
|
--- a/$1
|
|
|
|
+++ /dev/null
|
|
|
|
@@ -1 +0,0 @@
|
|
|
|
-evil
|
|
|
|
EOF
|
|
|
|
}
|
|
|
|
|
|
|
|
# $1 = name of file
|
|
|
|
# $2 = content of symlink
|
|
|
|
mkpatch_symlink () {
|
|
|
|
rm -f "$1" &&
|
|
|
|
cat <<-EOF
|
|
|
|
diff --git a/$1 b/$1
|
|
|
|
new file mode 120000
|
|
|
|
index 0000000..$(printf "%s" "$2" | git hash-object --stdin)
|
|
|
|
--- /dev/null
|
|
|
|
+++ b/$1
|
|
|
|
@@ -0,0 +1 @@
|
|
|
|
+$2
|
|
|
|
\ No newline at end of file
|
|
|
|
EOF
|
|
|
|
}
|
|
|
|
|
|
|
|
test_expect_success 'cannot create file containing ..' '
|
|
|
|
mkpatch_add ../foo >patch &&
|
|
|
|
test_must_fail git apply patch &&
|
|
|
|
test_path_is_missing ../foo
|
|
|
|
'
|
|
|
|
|
|
|
|
test_expect_success 'can create file containing .. with --unsafe-paths' '
|
|
|
|
mkpatch_add ../foo >patch &&
|
|
|
|
git apply --unsafe-paths patch &&
|
|
|
|
test_path_is_file ../foo
|
|
|
|
'
|
|
|
|
|
|
|
|
test_expect_success 'cannot create file containing .. (index)' '
|
|
|
|
mkpatch_add ../foo >patch &&
|
|
|
|
test_must_fail git apply --index patch &&
|
|
|
|
test_path_is_missing ../foo
|
|
|
|
'
|
|
|
|
|
|
|
|
test_expect_success 'cannot create file containing .. with --unsafe-paths (index)' '
|
|
|
|
mkpatch_add ../foo >patch &&
|
|
|
|
test_must_fail git apply --index --unsafe-paths patch &&
|
|
|
|
test_path_is_missing ../foo
|
|
|
|
'
|
|
|
|
|
|
|
|
test_expect_success 'cannot delete file containing ..' '
|
|
|
|
mkpatch_del ../foo >patch &&
|
|
|
|
test_must_fail git apply patch &&
|
|
|
|
test_path_is_file ../foo
|
|
|
|
'
|
|
|
|
|
|
|
|
test_expect_success 'can delete file containing .. with --unsafe-paths' '
|
|
|
|
mkpatch_del ../foo >patch &&
|
|
|
|
git apply --unsafe-paths patch &&
|
|
|
|
test_path_is_missing ../foo
|
|
|
|
'
|
|
|
|
|
|
|
|
test_expect_success 'cannot delete file containing .. (index)' '
|
|
|
|
mkpatch_del ../foo >patch &&
|
|
|
|
test_must_fail git apply --index patch &&
|
|
|
|
test_path_is_file ../foo
|
|
|
|
'
|
|
|
|
|
apply: do not touch a file beyond a symbolic link
Because Git tracks symbolic links as symbolic links, a path that
has a symbolic link in its leading part (e.g. path/to/dir/file,
where path/to/dir is a symbolic link to somewhere else, be it
inside or outside the working tree) can never appear in a patch
that validly applies, unless the same patch first removes the
symbolic link to allow a directory to be created there.
Detect and reject such a patch.
Things to note:
- Unfortunately, we cannot reuse the has_symlink_leading_path()
from dir.c, as that is only about the working tree, but "git
apply" can be told to apply the patch only to the index or to
both the index and to the working tree.
- We cannot directly use has_symlink_leading_path() even when we
are applying only to the working tree, as an early patch of a
valid input may remove a symbolic link path/to/dir and then a
later patch of the input may create a path path/to/dir/file, but
"git apply" first checks the input without touching either the
index or the working tree. The leading symbolic link check must
be done on the interim result we compute in-core (i.e. after the
first patch, there is no path/to/dir symbolic link and it is
perfectly valid to create path/to/dir/file).
Similarly, when an input creates a symbolic link path/to/dir and
then creates a file path/to/dir/file, we need to flag it as an
error without actually creating path/to/dir symbolic link in the
filesystem.
Instead, for any patch in the input that leaves a path (i.e. a non
deletion) in the result, we check all leading paths against the
resulting tree that the patch would create by inspecting all the
patches in the input and then the target of patch application
(either the index or the working tree).
This way, we catch a mischief or a mistake to add a symbolic link
path/to/dir and a file path/to/dir/file at the same time, while
allowing a valid patch that removes a symbolic link path/to/dir and
then adds a file path/to/dir/file.
Signed-off-by: Junio C Hamano <gitster@pobox.com>
10 years ago
|
|
|
test_expect_success SYMLINKS 'symlink escape via ..' '
|
|
|
|
{
|
|
|
|
mkpatch_symlink tmp .. &&
|
|
|
|
mkpatch_add tmp/foo ../foo
|
|
|
|
} >patch &&
|
|
|
|
test_must_fail git apply patch &&
|
|
|
|
test_path_is_missing tmp &&
|
|
|
|
test_path_is_missing ../foo
|
|
|
|
'
|
|
|
|
|
apply: do not touch a file beyond a symbolic link
Because Git tracks symbolic links as symbolic links, a path that
has a symbolic link in its leading part (e.g. path/to/dir/file,
where path/to/dir is a symbolic link to somewhere else, be it
inside or outside the working tree) can never appear in a patch
that validly applies, unless the same patch first removes the
symbolic link to allow a directory to be created there.
Detect and reject such a patch.
Things to note:
- Unfortunately, we cannot reuse the has_symlink_leading_path()
from dir.c, as that is only about the working tree, but "git
apply" can be told to apply the patch only to the index or to
both the index and to the working tree.
- We cannot directly use has_symlink_leading_path() even when we
are applying only to the working tree, as an early patch of a
valid input may remove a symbolic link path/to/dir and then a
later patch of the input may create a path path/to/dir/file, but
"git apply" first checks the input without touching either the
index or the working tree. The leading symbolic link check must
be done on the interim result we compute in-core (i.e. after the
first patch, there is no path/to/dir symbolic link and it is
perfectly valid to create path/to/dir/file).
Similarly, when an input creates a symbolic link path/to/dir and
then creates a file path/to/dir/file, we need to flag it as an
error without actually creating path/to/dir symbolic link in the
filesystem.
Instead, for any patch in the input that leaves a path (i.e. a non
deletion) in the result, we check all leading paths against the
resulting tree that the patch would create by inspecting all the
patches in the input and then the target of patch application
(either the index or the working tree).
This way, we catch a mischief or a mistake to add a symbolic link
path/to/dir and a file path/to/dir/file at the same time, while
allowing a valid patch that removes a symbolic link path/to/dir and
then adds a file path/to/dir/file.
Signed-off-by: Junio C Hamano <gitster@pobox.com>
10 years ago
|
|
|
test_expect_success SYMLINKS 'symlink escape via .. (index)' '
|
|
|
|
{
|
|
|
|
mkpatch_symlink tmp .. &&
|
|
|
|
mkpatch_add tmp/foo ../foo
|
|
|
|
} >patch &&
|
|
|
|
test_must_fail git apply --index patch &&
|
|
|
|
test_path_is_missing tmp &&
|
|
|
|
test_path_is_missing ../foo
|
|
|
|
'
|
|
|
|
|
apply: do not touch a file beyond a symbolic link
Because Git tracks symbolic links as symbolic links, a path that
has a symbolic link in its leading part (e.g. path/to/dir/file,
where path/to/dir is a symbolic link to somewhere else, be it
inside or outside the working tree) can never appear in a patch
that validly applies, unless the same patch first removes the
symbolic link to allow a directory to be created there.
Detect and reject such a patch.
Things to note:
- Unfortunately, we cannot reuse the has_symlink_leading_path()
from dir.c, as that is only about the working tree, but "git
apply" can be told to apply the patch only to the index or to
both the index and to the working tree.
- We cannot directly use has_symlink_leading_path() even when we
are applying only to the working tree, as an early patch of a
valid input may remove a symbolic link path/to/dir and then a
later patch of the input may create a path path/to/dir/file, but
"git apply" first checks the input without touching either the
index or the working tree. The leading symbolic link check must
be done on the interim result we compute in-core (i.e. after the
first patch, there is no path/to/dir symbolic link and it is
perfectly valid to create path/to/dir/file).
Similarly, when an input creates a symbolic link path/to/dir and
then creates a file path/to/dir/file, we need to flag it as an
error without actually creating path/to/dir symbolic link in the
filesystem.
Instead, for any patch in the input that leaves a path (i.e. a non
deletion) in the result, we check all leading paths against the
resulting tree that the patch would create by inspecting all the
patches in the input and then the target of patch application
(either the index or the working tree).
This way, we catch a mischief or a mistake to add a symbolic link
path/to/dir and a file path/to/dir/file at the same time, while
allowing a valid patch that removes a symbolic link path/to/dir and
then adds a file path/to/dir/file.
Signed-off-by: Junio C Hamano <gitster@pobox.com>
10 years ago
|
|
|
test_expect_success SYMLINKS 'symlink escape via absolute path' '
|
|
|
|
{
|
|
|
|
mkpatch_symlink tmp "$(pwd)" &&
|
|
|
|
mkpatch_add tmp/foo ../foo
|
|
|
|
} >patch &&
|
|
|
|
test_must_fail git apply patch &&
|
|
|
|
test_path_is_missing tmp &&
|
|
|
|
test_path_is_missing ../foo
|
|
|
|
'
|
|
|
|
|
apply: do not touch a file beyond a symbolic link
Because Git tracks symbolic links as symbolic links, a path that
has a symbolic link in its leading part (e.g. path/to/dir/file,
where path/to/dir is a symbolic link to somewhere else, be it
inside or outside the working tree) can never appear in a patch
that validly applies, unless the same patch first removes the
symbolic link to allow a directory to be created there.
Detect and reject such a patch.
Things to note:
- Unfortunately, we cannot reuse the has_symlink_leading_path()
from dir.c, as that is only about the working tree, but "git
apply" can be told to apply the patch only to the index or to
both the index and to the working tree.
- We cannot directly use has_symlink_leading_path() even when we
are applying only to the working tree, as an early patch of a
valid input may remove a symbolic link path/to/dir and then a
later patch of the input may create a path path/to/dir/file, but
"git apply" first checks the input without touching either the
index or the working tree. The leading symbolic link check must
be done on the interim result we compute in-core (i.e. after the
first patch, there is no path/to/dir symbolic link and it is
perfectly valid to create path/to/dir/file).
Similarly, when an input creates a symbolic link path/to/dir and
then creates a file path/to/dir/file, we need to flag it as an
error without actually creating path/to/dir symbolic link in the
filesystem.
Instead, for any patch in the input that leaves a path (i.e. a non
deletion) in the result, we check all leading paths against the
resulting tree that the patch would create by inspecting all the
patches in the input and then the target of patch application
(either the index or the working tree).
This way, we catch a mischief or a mistake to add a symbolic link
path/to/dir and a file path/to/dir/file at the same time, while
allowing a valid patch that removes a symbolic link path/to/dir and
then adds a file path/to/dir/file.
Signed-off-by: Junio C Hamano <gitster@pobox.com>
10 years ago
|
|
|
test_expect_success SYMLINKS 'symlink escape via absolute path (index)' '
|
|
|
|
{
|
|
|
|
mkpatch_symlink tmp "$(pwd)" &&
|
|
|
|
mkpatch_add tmp/foo ../foo
|
|
|
|
} >patch &&
|
|
|
|
test_must_fail git apply --index patch &&
|
|
|
|
test_path_is_missing tmp &&
|
|
|
|
test_path_is_missing ../foo
|
|
|
|
'
|
|
|
|
|
|
|
|
test_done
|