aboutsummaryrefslogtreecommitdiff
path: root/builtin/apply.c
diff options
context:
space:
mode:
authorJunio C Hamano <gitster@pobox.com>2015-01-29 15:35:24 -0800
committerJunio C Hamano <gitster@pobox.com>2015-02-10 13:40:20 -0800
commitc536c0755f6450b7bcce499cfda171f8c6d1e593 (patch)
tree16e7272d8411592c0743e08182823d7084d42c36 /builtin/apply.c
parent3d8a54eb37d298c251c0b6823dc06935a611bc33 (diff)
downloadgit-c536c0755f6450b7bcce499cfda171f8c6d1e593.tar.gz
git-c536c0755f6450b7bcce499cfda171f8c6d1e593.tar.xz
apply: reject input that touches outside the working area
By default, a patch that affects outside the working area (either a Git controlled working tree, or the current working directory when "git apply" is used as a replacement of GNU patch) is rejected as a mistake (or a mischief). Git itself does not create such a patch, unless the user bends over backwards and specifies a non-standard prefix to "git diff" and friends. When `git apply` is used as a "better GNU patch", the user can pass the `--unsafe-paths` option to override this safety check. This option has no effect when `--index` or `--cached` is in use. The new test was stolen from Jeff King with slight enhancements. Note that a few new tests for touching outside the working area by following a symbolic link are still expected to fail at this step, but will be fixed in later steps. Signed-off-by: Junio C Hamano <gitster@pobox.com>
Diffstat (limited to 'builtin/apply.c')
-rw-r--r--builtin/apply.c26
1 files changed, 26 insertions, 0 deletions
diff --git a/builtin/apply.c b/builtin/apply.c
index ef32e4f62..8561236d0 100644
--- a/builtin/apply.c
+++ b/builtin/apply.c
@@ -50,6 +50,7 @@ static int apply_verbosely;
static int allow_overlap;
static int no_add;
static int threeway;
+static int unsafe_paths;
static const char *fake_ancestor;
static int line_termination = '\n';
static unsigned int p_context = UINT_MAX;
@@ -3483,6 +3484,23 @@ static int check_to_create(const char *new_name, int ok_if_exists)
return 0;
}
+static void die_on_unsafe_path(struct patch *patch)
+{
+ const char *old_name = NULL;
+ const char *new_name = NULL;
+ if (patch->is_delete)
+ old_name = patch->old_name;
+ else if (!patch->is_new && !patch->is_copy)
+ old_name = patch->old_name;
+ if (!patch->is_delete)
+ new_name = patch->new_name;
+
+ if (old_name && !verify_path(old_name))
+ die(_("invalid path '%s'"), old_name);
+ if (new_name && !verify_path(new_name))
+ die(_("invalid path '%s'"), new_name);
+}
+
/*
* Check and apply the patch in-core; leave the result in patch->result
* for the caller to write it out to the final destination.
@@ -3570,6 +3588,9 @@ static int check_patch(struct patch *patch)
}
}
+ if (!unsafe_paths)
+ die_on_unsafe_path(patch);
+
if (apply_data(patch, &st, ce) < 0)
return error(_("%s: patch does not apply"), name);
patch->rejected = 0;
@@ -4379,6 +4400,8 @@ int cmd_apply(int argc, const char **argv, const char *prefix_)
N_("make sure the patch is applicable to the current index")),
OPT_BOOL(0, "cached", &cached,
N_("apply a patch without touching the working tree")),
+ OPT_BOOL(0, "unsafe-paths", &unsafe_paths,
+ N_("accept a patch that touches outside the working area")),
OPT_BOOL(0, "apply", &force_apply,
N_("also apply the patch (use with --stat/--summary/--check)")),
OPT_BOOL('3', "3way", &threeway,
@@ -4451,6 +4474,9 @@ int cmd_apply(int argc, const char **argv, const char *prefix_)
die(_("--cached outside a repository"));
check_index = 1;
}
+ if (check_index)
+ unsafe_paths = 0;
+
for (i = 0; i < argc; i++) {
const char *arg = argv[i];
int fd;