Refuse to patch symlinks

* src/inp.c (get_input_file), src/pch.c (there_is_another_patch,
intuit_diff_type): Use lstat instead of stat.  This causes patch to
refuse patching symlinks (get_input_file() will refuse to read them).
* src/util.c (create_backup): Refuse to create backups of symlinks.
* tests/symlinks: New test case.
* tests/Makefile.am (TESTS): Add test case.
* bootstrap.conf: Use the gnulib lstat module.
This commit is contained in:
Andreas Gruenbacher 2010-04-26 19:01:08 +02:00
parent f558fff533
commit e3cfef7f99
8 changed files with 95 additions and 6 deletions

View File

@ -1,5 +1,13 @@
2009-04-26 Andreas Gruenbacher <agruen@suse.de>
* src/inp.c (get_input_file), src/pch.c (there_is_another_patch,
intuit_diff_type): Use lstat instead of stat. This causes patch to
refuse patching symlinks (get_input_file() will refuse to read them).
* src/util.c (create_backup): Refuse to create backups of symlinks.
* tests/symlinks: New test case.
* tests/Makefile.am (TESTS): Add test case.
* bootstrap.conf: Use the gnulib lstat module.
* src/pch.c (intuit_diff_type): Only check for reversed patches when
the input file is patchable in the first place.

View File

@ -33,6 +33,7 @@ getopt-gnu
gettime
git-version-gen
hash
lstat
malloc
memchr
minmax

View File

@ -143,7 +143,7 @@ get_input_file (char const *filename, char const *outname)
char *getbuf;
if (inerrno == -1)
inerrno = stat (filename, &instat) == 0 ? 0 : errno;
inerrno = lstat (filename, &instat) == 0 ? 0 : errno;
/* Perhaps look for RCS or SCCS versions. */
if (patch_get

View File

@ -479,7 +479,7 @@ main (int argc, char **argv)
struct stat oldst;
int olderrno;
olderrno = stat (rej, &oldst) ? errno : 0;
olderrno = lstat (rej, &oldst) ? errno : 0;
if (olderrno && olderrno != ENOENT)
write_fatal ();
if (! olderrno && file_already_seen (&oldst))

View File

@ -283,7 +283,7 @@ there_is_another_patch (bool need_header)
{
inname = savebuf (buf, t - buf);
inname[t - buf - 1] = 0;
if (stat (inname, &instat) == 0)
if (lstat (inname, &instat) == 0)
{
inerrno = 0;
invc = -1;
@ -656,7 +656,7 @@ intuit_diff_type (bool need_header)
if (! stat_errno[i])
st[i] = st[i0];
}
else if (stat (p_name[i], &st[i]) != 0)
else if (lstat (p_name[i], &st[i]) != 0)
stat_errno[i] = errno;
else
{
@ -747,7 +747,7 @@ intuit_diff_type (bool need_header)
{
if (inname)
{
inerrno = stat (inname, &instat) == 0 ? 0 : errno;
inerrno = lstat (inname, &instat) == 0 ? 0 : errno;
if (inerrno || S_ISREG (instat.st_mode))
maybe_reverse (inname, inerrno, inerrno || instat.st_size == 0);
}

View File

@ -157,7 +157,10 @@ create_backup (char *to, struct stat *to_st, int *to_errno,
to_st = &tmp_st;
to_errno = &tmp_errno;
}
*to_errno = stat (to, to_st) == 0 ? 0 : errno;
*to_errno = lstat (to, to_st) == 0 ? 0 : errno;
if (! to_errno && ! S_ISREG (to_st->st_mode))
fatal ("File %s is not a regular file -- can't create backup", to);
if (! *to_errno && file_already_seen (to_st))
{

View File

@ -38,6 +38,7 @@ TESTS = \
reject-format \
remember-backup-files \
remember-reject-files \
symlinks \
unmodified-files
XFAIL_TESTS = \

76
tests/symlinks Normal file
View File

@ -0,0 +1,76 @@
# Copyright (C) 2010 Free Software Foundation, Inc.
#
# Copying and distribution of this file, with or without modification,
# in any medium, are permitted without royalty provided the copyright
# notice and this notice are preserved.
# Symlink related tests
. $srcdir/test-lib.sh
require_cat
use_local_patch
use_tmpdir
# ==============================================================
cat > create.diff <<EOF
--- /dev/null
+++ l
@@ -0,0 +1 @@
+one
EOF
rm -f f l
echo f > f
ncheck 'ln -s f l'
check 'patch < create.diff || echo "Status: $?"' <<EOF
File l is not a regular file -- can't patch
1 out of 1 hunk ignored -- saving rejects to file l.rej
Status: 1
EOF
check 'cat f' <<EOF
f
EOF
# --------------------------------------------------------------
rm -f f l
echo f > f
ncheck 'ln -s f l'
cat > modify.diff <<EOF
--- l
+++ l
@@ -1 +1 @@
-one
+two
EOF
check 'patch < modify.diff || echo "Status: $?"' <<EOF
File l is not a regular file -- can't patch
1 out of 1 hunk ignored -- saving rejects to file l.rej
Status: 1
EOF
# --------------------------------------------------------------
rm -f f l
echo f > f
ncheck 'ln -s f l'
cat > delete.diff <<EOF
--- l
+++ /dev/null
@@ -1 +0,0 @@
-one
EOF
check 'patch < delete.diff || echo "Status: $?"' <<EOF
File l is not a regular file -- can't patch
1 out of 1 hunk ignored -- saving rejects to file l.rej
Status: 1
EOF
# FIXME: Add tests for backup / reject file clashes with symlinks