summaryrefslogtreecommitdiff
path: root/usr.bin/patch
diff options
context:
space:
mode:
authorTodd C. Miller <millert@cvs.openbsd.org>2015-07-31 00:24:15 +0000
committerTodd C. Miller <millert@cvs.openbsd.org>2015-07-31 00:24:15 +0000
commit1c735ccd758b440a4e17bc2b6bf406deb6d3a940 (patch)
treeb7f0f84e1c46843b74a04676b47cb4c3ba2ce1f1 /usr.bin/patch
parente406ddef5cb3926a5baff42b644aaa3b6e52fe06 (diff)
Account for newlines in substitution (s///) commands. 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. From Martin Natano. OK deraadt@
Diffstat (limited to 'usr.bin/patch')
-rw-r--r--usr.bin/patch/pch.c16
1 files changed, 14 insertions, 2 deletions
diff --git a/usr.bin/patch/pch.c b/usr.bin/patch/pch.c
index 36cd608bc5e..bd434f40bbc 100644
--- a/usr.bin/patch/pch.c
+++ b/usr.bin/patch/pch.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: pch.c,v 1.52 2015/07/26 14:32:19 millert Exp $ */
+/* $OpenBSD: pch.c,v 1.53 2015/07/31 00:24:14 millert Exp $ */
/*
* patch - a program to apply diffs to original files
@@ -1402,7 +1402,19 @@ do_ed_script(void)
*t != '\0' && strchr("acdis", *t) != NULL) {
if (pipefp != NULL)
fputs(buf, pipefp);
- if (*t != 'd' && *t != 's') {
+ if (*t == 's') {
+ for (;;) {
+ bool continued = false;
+ t = buf + strlen(buf) - 1;
+ while (--t >= buf && *t == '\\')
+ continued = !continued;
+ if (!continued ||
+ pgets(buf, sizeof buf, pfp) == NULL)
+ break;
+ if (pipefp != NULL)
+ fputs(buf, pipefp);
+ }
+ } else if (*t != 'd') {
while (pgets(buf, sizeof buf, pfp) != NULL) {
p_input_line++;
if (pipefp != NULL)