202 Commits

Author SHA1 Message Date
Andreas Gruenbacher
38d87ecb9e Fix indentation heuristic for context diffs
Diffs can be indented by a variable number of spaces, tabs, or X characters.
Make sure that intuit_diff_type() only accepts context diffs where the first
and second line are indented identically, or else another_hunk() will fail.
* src/pch.c (intuit_diff_type): Remember the indentation of the last line. Only
recognize context diff hunks with the same amount of indentation on the first
and second line.
* tests/garbage: New test case.
* tests/Makefile.am (TESTS): Add test case.
2015-01-31 22:14:01 +01:00
Quentin Casasnovas
82b800c955 patch: git-diff mode: do not change permissions if there isn't an explicit mode change.
Signed-off-by: Quentin Casasnovas <quentin.casasnovas@oracle.com>
2015-01-31 22:14:01 +01:00
Tim Waugh
290ffcb488 Allow arbitrary symlink targets again
* src/util.c (symlink_target_is_valid): Remove.
(move_file): Remove symlink target checking.
* tests/symlinks: Update test case.
2015-01-31 22:14:01 +01:00
Andreas Gruenbacher
b72e3be5c8 Update list of gnulib modules used
* bootstrap.conf (gnulib_modules): Remove lchmod, lstat, mkdir, readlink,
rename, mkdir, symlink, unlink, utimens. Add fchownat, fchmodat, fstatat,
mkdirat, openat, readlinkat, renameat, symlinkat, unlinkat, utimensat.
* src/util.h: Don't include <utimens.h> anymore.
2015-01-31 22:14:01 +01:00
Andreas Gruenbacher
71a3172c7e Use symlink-safe system call replacements
Use the symlink-safe replacements for system calls in many places throughout
the code: In some places this makes patch safe against path traversal attacks;
in other places, it saves the kernel from having to re-traverse the pathnames.
* src/inp.c (plan_b): Use safe_open() + fdopen() instead of fopen().
* src/util.c (copy_attr): Document why we are safe here.
(create_backup): Use safe_open() instead of creat().
2015-01-31 22:14:00 +01:00
Tim Waugh
025a54b789 Add symlink-safe system call replacements
Add wrappers around system calls that traverse relative pathnames without
following symlinks. Written by Tim Waugh <twaugh@redhat.com> and Andreas
Gruenbacher <agruenba@redhat.com>.
* src/safe.h: Declare functions here.
* src/safe.c: Implement safe_* system call replacements that do not follow
symlinks along pathnames. Pathname components are resolved with openat().
Lookup results are cached to keep the overhead reasonably low.
* tests/deep-directories: New path traversal cache test.
* src/Makefile.am (patch_SOURCES): Add safe.[ch].
* tests/Makefile.am (TESTS): Add new test.
2015-01-31 22:13:44 +01:00
Tim Waugh
75fcb4b560 Avoid closing file descriptor twice
* src/patch.c (main): Make sure we don't close() outfd after passing it on to
fdopen(): the file descriptor might have been reused in the meantime.
2015-01-31 18:25:12 +01:00
Andreas Gruenbacher
3e7113a6b5 Remove unused variable
* src/pch.c (name_is_valid): Remove unused variable.
2015-01-29 19:31:53 +01:00
Andreas Gruenbacher
41688ad8ef Fix the fix for CVE-2015-1196
* src/util.c (filename_is_safe): New function split off from name_is_valid().
(symlink_target_is_valid): Explain why we cannot have absolute symlinks or
symlinks with ".." components for now.
(move_file): Move absolute filename check here and explain.
* tests/symlinks: Put test case with ".." symlink in comments for now.
* NEWS: Add CVE number.
2015-01-22 21:51:51 +01:00
Andreas Gruenbacher
17953b5893 For renames and copies, make sure that both file names are valid
* src/patch.c (main): Allow there_is_another_patch() to set the
skip_rest_of_patch flag.
* src/pch.c (intuit_diff_type): For renames and copies, also check the "other"
file name.
(pch_copy, pch_rename): Now that both names are checked in intuit_diff_type(),
we know they are defined here.
2015-01-21 16:32:41 +01:00
Andreas Gruenbacher
0c08d7a902 Fail when out of memory in set_hunkmax()
src/pch.c (another_hunk): Call set_hunkmax() from here to make sure it is
called even when falling back from plan A to plan B.
(open_patch_file): No need to call set_hunkmax() anymore.
src/pch.c (set_hunkmax): Fail when out of memory. Make static.
src/pch.h: Remove set_hunkmax() prototype.
2015-01-20 12:43:57 +01:00
Andreas Gruenbacher
19285e563a Don't try applying hunks at offsets that can't work
* src/patch.c (locate_hunk): Start trying to apply the hunk at the minimum
offset which puts the hunk in the valid range of lines. This will often still
be offset 0.
2015-01-20 12:00:24 +01:00
Andreas Gruenbacher
ae88d1c270 Move symlink_target_is_valid() and cwd_is_root()
* src/util.c: Move symlink_target_is_valid() and cwd_is_root() here from
src/pch.c.
2015-01-20 10:10:10 +01:00
Andreas Gruenbacher
4e9269a5fc Make sure symlinks don't point outside working directory (CVE-2015-119)
When creating symlinks from git-style patches, make sure the symlinks don't
point above the current working directory.  Otherwise, a subsequent patch could
use the symlink to write outside the working directory.

* src/pch.c (symlink_target_is_valid): New function to check for valid symlink
targets.
* src/util.c (move_file): Use symlink_target_is_valid() here.
* tests/symlinks: Add valid and invalid symlink test cases.
2015-01-19 23:18:30 +01:00
Andreas Gruenbacher
44a987e02f Add line number overflow checking
* bootstrap.conf: use intprops module.
* src/common.h: Define LINENUM_MIN and LINENUM_MAX macros.
* src/pch.c (another_hunk): Add line number overflow checking.  Based on Robert
C. Seacord's INT32-C document for integer overflow checking and Tobias
Stoeckmann's "integer overflows and oob memory access" patch for FreeBSD.
2014-11-30 20:56:46 +01:00
Andreas Gruenbacher
f22e47d873 More savebuf/savestr error handling
* bootstrap.conf: use xmemdup0 module.
* src/pch.c (there_is_another_patch): Use xmemdup0 instead of savebuf when we
cannot recover from out-of-memory situations.
(intuit_diff_type): Likewise, use xstrdup instead of savestr.
(another_hunk): Handle the case when savestr returns NULL.
* src/util.c (fetchname, parse_name): Use xmemdup0 instead of savebuf when we
cannot recover from out-of-memory situations.

Bugs pointed out by Tobias Stoeckmann <tobias@stoeckmann.org>.
2014-11-30 15:52:42 +01:00
Tobias Stoeckmann
e4c6511f46 savebuf/savestr error handling
* src/patch.c (get_some_switches): The function savebuf (and therefore savestr)
copies strings using malloc.  If malloc fails, NULL is returned.  This is
intentional behavior so that in case of failure during "plan a" patching, "plan
b" can step in.  The return value has to be properly checked for NULL.  If the
return value must not be NULL, use xstrdup instead.
2014-11-30 15:35:44 +01:00
Andreas Gruenbacher
3fd4144ae9 build: update gnulib submodule to latest
* src/merge.c (compute_changes): The TOO_EXPENSIVE heuristic in diffseq has
been removed, including compareseq's find_minimal parameter and the context's
too_expensive limit.  Adjust.
2014-11-30 15:35:31 +01:00
Jean Delvare
65193f1cc1 Drop useless test in another_hunk()
src/pch.c (another_hunk): This test will always succeed.
2014-11-10 11:43:36 +01:00
Tobias Stoeckmann
e25e622dec Buffer overflow on malicious input file
There is a hard to reach but possible buffer overflow when using
patch with a very large (modified) input file.  I doubt you will ever
see this with a 64 bit system, but it's possible with 32 bit:

$ echo hello > file1
$ echo world > file2
$ diff -Nau file1 file2 > file.diff

Nothing fancy so far.  Adjust file1 so it contains at least one line that
is 2 GB in size.  Larger is fine too, but stay below 4 GB.

$ tr '\0' c < /dev/zero | dd bs=1K count=2097152 of=file1

Now try to patch it.

$ patch -Np0 -i file.diff
Segmentation fault

The issue is in patch's "plan b" strategy  (If your system would still
want to use "plan a", force patch to use "plan b" through debug flag).

Plan b writes lines into a temporary file, with equally long lines, so
it can use a buffer mechanism to access them in a kind of randomly
fassion.  In order to do that, it retrieves the longest line.

In this example, it will encounter the 2 GB line and stores that as the
longest one.  Afterwards it will adjust the tibufsize variable to be
large enough:

  for (tibufsize = TIBUFSIZE_MINIMUM;  tibufsize < maxlen;  tibufsize <<= 1)
    /* do nothing */ ;

Due to maxlen's size (2 GB), tibufsize will be SIZE_T_MAX, i.e. 4 GB.
A few lines later it allocates space for the tibuf buffers:

  tibuf[0] = xmalloc (2 * tibufsize);
  tibuf[1] = tibuf[0] + tibufsize;

This will allocate 0 bytes because tibufsize overflowed.  The next
time patch writes into the buffer, a segmentation fault will occur...
Depends on your system how long it takes until that happens. ;)

The fix is simple:  Bail out on lines that are too long.  Patch already
does that for files that have too many lines.
2014-10-30 22:47:40 +01:00
Andreas Gruenbacher
f926295f4f Improve error message when refusing to delete file
* src/patch.c: Improve error message.
* tests/create-delete: Update the test case.
2014-08-13 01:16:44 +02:00
Andreas Gruenbacher
dc63883f08 Correct the --help text of option --merge
* src/patch.c (option_help): The --merge option does not have a short
form; update the help text.
2013-12-09 09:26:16 +01:00
Steven Rostedt
a2f4bfe0f3 Preserve function names in reject files
* src/patch.c (main): Preserve function names in reject files.
* tests/reject-format: Update the test case.
Signed-off-by: Steven Rostedt <rostedt@goodmis.org>
Signed-off-by: Andreas Gruenbacher <agruen@linbit.com>
2013-08-19 22:44:46 +02:00
Andreas Gruenbacher
afdfa9ec8e In dry-run mode, create temporary files in a temporary directory
* src/util.c (make_tempfile): Do not create temporary files in the final output
directory when in dry-run mode: the path may be read-only.  In addition, we do
not want to leave intermediary empty output directories around.
2013-07-30 12:52:42 +02:00
Andreas Gruenbacher
2f40ef66be Fix removing empty directories
Reported by Thomas Moschny <thomas.moschny@gmx.de>:
src/patch.c (main): Temporary output files are created in the same directory as
the output file.  Make sure to remove them before removing empty files and
their empty ancestor directories; else the directories won't be empty.
tests/remove-directories: Add directory removal test case.
tests/Makefile.am (TESTS): Add new test case.
2013-03-10 19:02:54 +01:00
Andreas Gruenbacher
291ec17581 Initialize data structures early enough
* src/patch.c (main): Initialize data structures early enough, before error
paths can access them.
* tests/bad-usage: Test bad command line usage.
* tests/Makefile.am (TESTS): Add bad-usage here.
2012-10-04 12:43:05 +02:00
Andreas Gruenbacher
ac59899327 Use gnulib errno module instead of our own default ENOTSUP fallback
* bootstrap.conf (gnulib_modules): Add errno module.
* src/common.h: Remove ENOTSUP fallback.
2012-09-28 16:00:04 +02:00
Andreas Gruenbacher
e8bfce6547 Improve the previous commit
* src/patch.c: Only print the "file is not empty after patch" message when
trying to delete the output file.  Say that we were trying to delete the file.
* tests/create-delete: Fix the expected messages.  Add test cases for the
--remove-empty-files and --posix options.
* NEWS: Better describe this change.
2012-09-26 01:33:22 +02:00
Andreas Gruenbacher
1d9ed51e9c Only expect files to become empty if the patch says so
Test cases based on patches from Dmitry V. Levin <ldv@altlinux.org>.
* src/patch.c (main): Only expect files to become empty if the patch says so.
* NEWS: Document this change.
* tests/create-delete: Add (more) empty vs. non-empty test cases.
2012-09-25 04:07:53 +02:00
Andreas Gruenbacher
3ccb16e10b Improve messages when in --dry-run mode
* src/patch.c (main): Say that we are checking a file and not that we are
patching it in --dry-run mode.  Don't say "saving rejects to file" when we
don't create reject files.
* tests/reject-format: Add rejects with --dry-run test case.
* tests/bad-filenames, tests/fifo, tests/mixed-patch-types: Update.
2012-09-22 20:10:53 +02:00
Andreas Gruenbacher
db1bd7f693 Improve handling of LF vs. CRLF line endings
* src/patch.c (check_line_endings): New function.
(main): When a hunk fails, report when the line endings differ between the
input file and the patch.
* src/pch.c (there_is_another_patch): When saying that we strip trailing CRs,
also say how to turn this off.
* tests/crlf-handling: Update changed messages.  Add test case that fails.
2012-09-22 20:02:48 +02:00
Andreas Gruenbacher
d24f630fbc Ignore when preserving extended attributes is not supported or allowed
* src/common.h (ENOTSUP): Make sure this error code is defined.
* src/util.c (set_file_attributes): Ignore ENOSYS, ENOTSUP, and EPERM errors.
2012-09-22 18:32:10 +02:00
Andreas Gruenbacher
293415dbcf Add --follow-symlinks option for backwards compatibility
* src/common.h (follow_symlinks): New variable.
* src/patch.c (longopts): Add new --follow-symlinks option.
(get_some_switches): Recognize the new option.
* src/util.c (stat_file): Follow symlinks if requested.
* patch.man: Document the new option.
* tests/symlinks: Add test case.
2012-09-19 03:16:07 +02:00
Andreas Gruenbacher
59609b50c5 Introduce function to lstat all input files
* src/util.c (stat_file): New function.
(move_file): Use here.
* src/util.h (stat_file): Declare here.
* src/inp.c (get_input_file): Use here.
* src/patch.c (main): Use here.
(delete_file_later): Use here.
* src/pch.c (there_is_another_patch): Use here.
(intuit_diff_type): Use here.
2012-09-19 03:07:31 +02:00
Andreas Gruenbacher
b578985c3c Use stat where we want to follow symlinks
* src/pch.c (prefix_components): Follow symlinks.
(cwd_is_root): Follow symlinks.
2012-09-19 02:51:23 +02:00
Andreas Gruenbacher
99f2638763 Fix file truncation when switching from git diff to non-git diff
* src/patch.c (main): Output queued output files only when switching from a git
diff to a non-git diff.  This can modify the input file, so make sure to
stat() it again.
* tests/concat-git-diff: Add test case growing a file with a git diff and then
with a non-git diff; without this fix; the result would be truncated.
2012-09-18 12:53:38 +02:00
Andreas Gruenbacher
0f22a35cec Rename get_input_file() parameter to clarify code
* src/inp.c (get_input_file): Rename mode parameter to file_type, it's all we
care about here.
2012-09-18 00:48:01 +02:00
Andreas Gruenbacher
4c7c0976ac Improve error message when patching a file of different type
* src/inp.c (get_input_file): Improve error message when patching a file of
different type.
* tests/symlinks: Update test case.
2012-09-18 00:48:01 +02:00
Andreas Gruenbacher
1ea53aae17 Disable xattrs if libattr doesn't implement attr_copy_action()
* m4/xattr.m4 (gl_FUNC_XATTR): Only enable USE_XATTR if both attr_copy_file()
and attr_copy_action() are defined.
* src/util.c (copy_attr_check): No fallback needed if attr_copy_action() is not
defined.
2012-09-17 17:04:20 +02:00
Andreas Gruenbacher
20c9d7d5ab Allow to use potentially dangerous filenames from the root directory
* src/pch.c (cwd_is_root): New function to check if we are in the root
directory of a filename.
(name_is_valid): Allow to use potentially dangerous filenames when the current
working directory is the root directory: from there, those names are not
any more dangerous than other names.
* tests/bad-filenames: New test case.
2012-09-17 15:48:06 +02:00
Andreas Gruenbacher
543906f1a4 Check if libattr implements attr_copy_action()
* m4/xattr.m4 (gl_FUNC_XATTR): Check if attr_copy_action() is defined.
* src/util.c: If attr_copy_action() doesn't exist, fall back to the default
copy_attr_file() behavior of copying most extended attributes except ACLs.
2012-09-14 11:39:02 +02:00
Andreas Gruenbacher
f0388d2dbf Change the type of *_needs_removal from int to bool 2012-09-13 16:34:58 +02:00
Andreas Gruenbacher
281537bcd9 In a git-style diff, make sure not to unlink the original by accident
* src/patch.c (main): Fail if a file is not empty as expected.
(output_files): In a git-style diff, make sure not to unlink the original when
making a backup of an unmodified file.
* tests/create-delete: Fix failed-file-deletion test and add
successful-file-deletion test.
2012-09-13 16:32:53 +02:00
Andreas Gruenbacher
dc3cdeebca Do not pass file type in mode of open(..., O_CREAT, mode)
* src/patch.c (main): Strip file type off of create mode for temporary output
files: some systems don't ignore the file type; we want to create a regular
file even when patching a symlink.
2012-09-13 16:31:25 +02:00
Andreas Gruenbacher
66aeedee12 Support double-quoted filenames in all context diff formats
* src/util.c (fetchname): Always recognize double-quoted filenames.
* src/util.h (fetchname): Update prototype.
* src/pch.c (intuit_diff_type): Update calls to fetchname().
* tests/quoted-filenames: Change to a normal unified diff.
* NEWS: Update.
2012-08-11 11:09:11 +02:00
Andreas Gruenbacher
9a37354cc6 Remove SHA1 hashes from the file id cache
* src/util.c (file_id): Remove sha1 field.
(update_sha1, lookup_sha1): Remove functions.
* src/util.h (update_sha1, lookup_sha1): Remove declarations.
2012-08-08 13:39:19 +02:00
Andreas Gruenbacher
a18960d31e Detect concatenated git-style patches by tracking what's in the output queue
* src/patch.c (main): Instead of looking at the SHA hashes to detect
concatenated git-style patches, detect when a file to write to is already in
the output queue.
* tests/concat-git-diff: Add create/delete tests.
2012-08-08 13:39:08 +02:00
Andreas Gruenbacher
e294241b86 In the file id cache, allow to flag files in the output queue
* src/util.c (file_id): Add queued_output field.
(__insert_file_id): Initialize queued_output.
(set_queued_output, has_queued_output): New functions.
* src/util.h (set_queued_output, has_queued_output): Declare.
2012-08-08 13:10:41 +02:00
Andreas Gruenbacher
81d006fe4b Change outst variable name to tmpoutst to be less misleading
* src/patch.c (main): Rename outst to tmpoutst.
2012-08-07 22:38:32 +02:00
Andreas Gruenbacher
1e6c0d07ab In git-style diffs, create new files immediatetly and only remember files to modify
* src/patch.c (output_file): Create new files immediately.  Document why
things are implemented that way.
* tests/concat-git-diff: Fix glitch in test case.
2012-08-02 20:38:31 +02:00