Репозитории ALT
S: | 2.7.6.0.27.7623-alt1 |
5.1: | 2.5.9-alt3 |
4.1: | 2.5.9-alt3 |
4.0: | 2.5.9-alt3 |
3.0: | 2.5.4-ipl10mdk |
Группа :: Работа с текстами
Пакет: patch
Главная Изменения Спек Патчи Sources Загрузить Gear Bugs and FR Repocop
Патч: patch-2.6.1-alt3.patch
Скачать
Скачать
src/common.h | 1 +
src/patch.c | 32 ++++++++++++++++++++++++++++++++
src/pch.c | 3 +++
src/util.c | 11 -----------
tests/bad-filenames | 38 ++++++++++++++++++++++++++++++--------
5 files changed, 66 insertions(+), 19 deletions(-)
diff --git a/src/common.h b/src/common.h
index b38f1b2..8e8486e 100644
--- a/src/common.h
+++ b/src/common.h
@@ -143,6 +143,7 @@ XTERN char *revision; /* prerequisite revision, if any */
#endif
void fatal_exit (int) __attribute__ ((noreturn));
+void validate_target_name (char const *n);
#include <errno.h>
#if !STDC_HEADERS && !defined errno
diff --git a/src/patch.c b/src/patch.c
index 77be499..f07fafb 100644
--- a/src/patch.c
+++ b/src/patch.c
@@ -31,6 +31,7 @@
#include <util.h>
#include <version.h>
#include <xalloc.h>
+#include <dirname.h>
/* procedures */
@@ -105,6 +106,7 @@ main (int argc, char **argv)
mode_t file_type;
int outfd = -1;
+ outst.st_size = -1;
exit_failure = 2;
program_name = argv[0];
init_time ();
@@ -500,6 +502,16 @@ main (int argc, char **argv)
set_file_attributes (TMPOUTNAME, attr, inname, &instat,
mode, &new_time);
+ /* We may have useful data in outst, via spew_output.
+ If not, get it now, via the file descriptor when
+ possible. */
+ if (outst.st_size == -1)
+ {
+ if (0 <= outfd
+ ? fstat (outfd, &outst)
+ : stat (TMPOUTNAME, &outst))
+ fatal ("failed to stat %s", quotearg (TMPOUTNAME));
+ }
move_file (TMPOUTNAME, &TMPOUTNAME_needs_removal, &outst,
outname, mode, backup);
@@ -1004,6 +1016,26 @@ numeric_string (char const *string,
return value;
}
+void
+validate_target_name (char const *n)
+{
+ char const *p = n;
+ if (explicit_inname)
+ return;
+ if (IS_ABSOLUTE_FILE_NAME (p))
+ fatal ("rejecting absolute target file name: %s", quotearg (p));
+ while (*p)
+ {
+ if (*p == '.' && *++p == '.' && ( ! *++p || ISSLASH (*p)))
+ fatal ("rejecting target file name with \"..\" component: %s",
+ quotearg (n));
+ while (*p && ! ISSLASH (*p))
+ p++;
+ while (ISSLASH (*p))
+ p++;
+ }
+}
+
/* Attempt to find the right place to apply this hunk of patch. */
static lin
diff --git a/src/pch.c b/src/pch.c
index 68f7bc8..bdfe0d4 100644
--- a/src/pch.c
+++ b/src/pch.c
@@ -194,6 +194,8 @@ maybe_reverse (char const *name, bool nonexistent, bool is_empty)
{
bool looks_reversed = (! is_empty) < p_says_nonexistent[reverse ^ is_empty];
+ validate_target_name (name);
+
/* Allow to create and delete empty files when we know that they are empty:
in the "diff --git" format, we know that from the index header. */
if (is_empty
@@ -929,6 +931,7 @@ intuit_diff_type (bool need_header, mode_t *p_file_type)
inerrno = stat_errno[i];
invc = version_controlled[i];
instat = st[i];
+ validate_target_name (inname);
}
return retval;
diff --git a/src/util.c b/src/util.c
index 553cfbd..f1187ff 100644
--- a/src/util.c
+++ b/src/util.c
@@ -1415,17 +1415,6 @@ strip_leading_slashes (char *name, int strip_leading)
n = p+1;
}
}
- if (IS_ABSOLUTE_FILE_NAME (n))
- fatal ("rejecting absolute file name: %s", quotearg (n));
- for (p = n; *p; )
- {
- if (*p == '.' && *++p == '.' && ( ! *++p || ISSLASH (*p)))
- fatal ("rejecting file name with \"..\" component: %s", quotearg (n));
- while (*p && ! ISSLASH (*p))
- p++;
- while (ISSLASH (*p))
- p++;
- }
if ((strip_leading < 0 || s <= 0) && *n)
{
memmove (name, n, strlen (n) + 1);
diff --git a/tests/bad-filenames b/tests/bad-filenames
index f53a613..44d02ba 100644
--- a/tests/bad-filenames
+++ b/tests/bad-filenames
@@ -7,43 +7,65 @@
. $srcdir/test-lib.sh
use_local_patch
+use_tmpdir
# ================================================================
-emit_patch()
+emit_2()
{
cat <<EOF
---- /dev/null
-+++ $1
+--- $1
++++ $2
@@ -0,0 +1 @@
+x
EOF
}
+emit_patch() { emit_2 /dev/null "$1"; }
+
# Ensure that patch rejects an output file name that is absolute
# or that contains a ".." component.
check 'emit_patch /absolute/path | patch -p0; echo status: $?' <<EOF
-$PATCH: **** rejecting absolute file name: /absolute/path
+$PATCH: **** rejecting absolute target file name: /absolute/path
status: 2
EOF
check 'emit_patch a/../z | patch -p0; echo status: $?' <<EOF
-$PATCH: **** rejecting file name with ".." component: a/../z
+$PATCH: **** rejecting target file name with ".." component: a/../z
status: 2
EOF
check 'emit_patch a/../z | patch -p1; echo status: $?' <<EOF
-$PATCH: **** rejecting file name with ".." component: ../z
+$PATCH: **** rejecting target file name with ".." component: ../z
status: 2
EOF
check 'emit_patch a/.. | patch -p0; echo status: $?' <<EOF
-$PATCH: **** rejecting file name with ".." component: a/..
+$PATCH: **** rejecting target file name with ".." component: a/..
status: 2
EOF
check 'emit_patch ../z | patch -p0; echo status: $?' <<EOF
-$PATCH: **** rejecting file name with ".." component: ../z
+$PATCH: **** rejecting target file name with ".." component: ../z
status: 2
EOF
+
+check 'emit_2 /abs/path target | patch -p0; echo status: $?' <<EOF
+patching file target
+status: 0
+EOF
+
+echo x > target
+check 'emit_2 /abs/path target | patch -R -p0; echo status: $?' <<EOF
+patching file target
+status: 0
+EOF
+
+# Do not validate any file name from the input when the target
+# is specified on the command line:
+touch abs
+check 'emit_patch /absolute/path | patch `pwd`/abs; echo status: $?' <<EOF
+patching file `pwd`/abs
+status: 0
+EOF