diff options
author | Andreas Gruenbacher <agruen@gnu.org> | 2015-02-28 13:28:49 +0100 |
---|---|---|
committer | Andreas Gruenbacher <agruen@gnu.org> | 2015-03-05 22:57:07 +0100 |
commit | 6fbdcefe7d099731a18a5a82cfea6ee87e332556 (patch) | |
tree | ab07d973e7701250a93de1d4120821016eb28c5a | |
parent | a025a51ca5c173c958ad446d9ba5718019867ba8 (diff) | |
download | patch-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.c | 22 | ||||
-rw-r--r-- | src/safe.c | 9 |
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; @@ -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; |