apply: reject input that touches outside the working area
[gitweb.git] / builtin / apply.c
index ef32e4f62415956aa8e2366589d4cd6200d3bf37..8561236d04fabb9b81494325def4b7d0f2a5c22a 100644 (file)
@@ -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;