summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndreas Gruenbacher <agruen@gnu.org>2015-02-28 13:28:49 +0100
committerAndreas Gruenbacher <agruen@gnu.org>2015-03-05 22:57:07 +0100
commit6fbdcefe7d099731a18a5a82cfea6ee87e332556 (patch)
treeab07d973e7701250a93de1d4120821016eb28c5a
parenta025a51ca5c173c958ad446d9ba5718019867ba8 (diff)
downloadpatch-6fbdcefe7d099731a18a5a82cfea6ee87e332556.tar.gz
Move path traversal error reporting into main()
* src/safe.c (traverse_another_path): Don't report errors here. * src/patch.c (main): Instead, recognize and report them here. Detect when an output file name is invalid; it doesn't make sense to try creating a reject file based on the same outbut file name in that case.
-rw-r--r--src/patch.c22
-rw-r--r--src/safe.c9
2 files changed, 18 insertions, 13 deletions
diff --git a/src/patch.c b/src/patch.c
index 42d0267..a60e631 100644
--- a/src/patch.c
+++ b/src/patch.c
@@ -115,6 +115,7 @@ main (int argc, char **argv)
struct stat tmpoutst;
char numbuf[LINENUM_LENGTH_BOUND + 1];
bool written_to_rejname = false;
+ bool skip_reject_file = false;
bool apply_empty_patch = false;
mode_t file_type;
int outfd = -1;
@@ -190,6 +191,7 @@ main (int argc, char **argv)
there_is_another_patch (! (inname || posixly_correct), &file_type)
|| apply_empty_patch;
reinitialize_almost_everything(),
+ skip_reject_file = false,
apply_empty_patch = false
) { /* for each patch in patch file */
int hunk = 0;
@@ -310,8 +312,19 @@ main (int argc, char **argv)
O_WRONLY | binary_transput,
instat.st_mode & S_IRWXUGO);
if (outfd == -1)
- pfatal ("Can't create temporary file %s", TMPOUTNAME);
- TMPOUTNAME_needs_removal = true;
+ {
+ if (errno == ELOOP || errno == EXDEV)
+ {
+ say ("Invalid file name %s -- skipping patch\n", quotearg (outname));
+ skip_rest_of_patch = true;
+ skip_reject_file = true;
+ somefailed = true;
+ }
+ else
+ pfatal ("Can't create temporary file %s", TMPOUTNAME);
+ }
+ else
+ TMPOUTNAME_needs_removal = true;
if (diff_type == ED_DIFF) {
outstate.zero_output = false;
somefailed |= skip_rest_of_patch;
@@ -454,7 +467,8 @@ main (int argc, char **argv)
|| ! where
|| ! apply_hunk (&outstate, where))))
{
- abort_hunk (outname, ! failed, reverse);
+ if (! skip_reject_file)
+ abort_hunk (outname, ! failed, reverse);
failed++;
if (verbosity == VERBOSE ||
(! skip_rest_of_patch && verbosity != SILENT))
@@ -595,7 +609,7 @@ main (int argc, char **argv)
if (diff_type != ED_DIFF) {
struct stat rejst;
- if (failed) {
+ if (failed && ! skip_reject_file) {
if (fstat (fileno (rejfp), &rejst) != 0 || fclose (rejfp) != 0)
write_fatal ();
rejfp = NULL;
diff --git a/src/safe.c b/src/safe.c
index d4a2a4b..129ccf4 100644
--- a/src/safe.c
+++ b/src/safe.c
@@ -419,15 +419,6 @@ static int traverse_another_path (const char **pathname, int keepfd)
printf (" (failed)\n");
fflush (stdout);
}
- if (errno == ELOOP
- || errno == EMLINK /* FreeBSD 10.1: Too many links */
- || errno == EFTYPE /* NetBSD 6.1: Inappropriate file type or format */
- || errno == ENOTDIR)
- {
- say ("file %.*s is not a directory\n",
- (int) (path - *pathname), *pathname);
- skip_rest_of_patch = true;
- }
goto fail;
}
dir = entry;