summaryrefslogtreecommitdiff
path: root/usr.bin/patch
diff options
context:
space:
mode:
authorchristos <christos@NetBSD.org>2015-07-30 21:47:51 +0000
committerchristos <christos@NetBSD.org>2015-07-30 21:47:51 +0000
commit39275d4eabce7266b68ebdfca95e6a46b5a0ca4a (patch)
treeb77e0ff6306433397568eae8f2b5f6274604261e /usr.bin/patch
parent53796b1872dc053e4f8f64d728ee555a60d0fb5c (diff)
from bitrieg:
Substitution commands might contain a newline in the replacement pattern (escaped with a backslash before it), causing patch's understanding of the state the ed child process is in to diverge from reality. This can lead to patch unwillingly feeding '!' (execute shell command) lines to ed. Finding out how to do this is left as an exercise to the reader. XXX: pullup-7
Diffstat (limited to 'usr.bin/patch')
-rw-r--r--usr.bin/patch/pch.c19
1 files changed, 16 insertions, 3 deletions
diff --git a/usr.bin/patch/pch.c b/usr.bin/patch/pch.c
index 1ef322fb7d9..7ffb0cc76a7 100644
--- a/usr.bin/patch/pch.c
+++ b/usr.bin/patch/pch.c
@@ -1,7 +1,7 @@
/*
* $OpenBSD: pch.c,v 1.37 2007/09/02 15:19:33 deraadt Exp $
* $DragonFly: src/usr.bin/patch/pch.c,v 1.6 2008/08/10 23:35:40 joerg Exp $
- * $NetBSD: pch.c,v 1.27 2014/11/27 15:07:23 christos Exp $
+ * $NetBSD: pch.c,v 1.28 2015/07/30 21:47:51 christos Exp $
*/
/*
@@ -31,7 +31,7 @@
*/
#include <sys/cdefs.h>
-__RCSID("$NetBSD: pch.c,v 1.27 2014/11/27 15:07:23 christos Exp $");
+__RCSID("$NetBSD: pch.c,v 1.28 2015/07/30 21:47:51 christos Exp $");
#include <sys/types.h>
#include <sys/stat.h>
@@ -1407,6 +1407,7 @@ do_ed_script(void)
char *t;
long beginning_of_this_line;
FILE *pipefp = NULL;
+ int continuation;
if (!skip_rest_of_patch) {
if (copy_file(filearg[0], TMPOUTNAME) < 0) {
@@ -1431,7 +1432,19 @@ do_ed_script(void)
*t == 'd' || *t == 'i' || *t == 's')) {
if (pipefp != NULL)
fputs(buf, pipefp);
- if (*t != 'd') {
+ if (*t == 's') {
+ for (;;) {
+ continuation = 0;
+ t = strchr(buf, '\0') - 1;
+ while (--t >= buf && *t == '\\')
+ continuation = !continuation;
+ if (!continuation ||
+ pgets(buf, sizeof buf, pfp) == NULL)
+ break;
+ if (pipefp != NULL)
+ fputs(buf, pipefp);
+ }
+ } else if (*t != 'd') {
while (pgets(buf, buf_len, pfp) != NULL) {
p_input_line++;
if (pipefp != NULL)