summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorschwarze <schwarze@openbsd.org>2015-02-21 14:46:33 +0000
committerschwarze <schwarze@openbsd.org>2015-02-21 14:46:33 +0000
commit633c28f2066f3c11025ed4db6ccb45d824c1060e (patch)
tree34ec12de5416c9a4b544553b091a6c8588dc1d37
parentFix iwm(4) man page bug symptom description: If the MAC address is changed (diff)
downloadwireguard-openbsd-633c28f2066f3c11025ed4db6ccb45d824c1060e.tar.xz
wireguard-openbsd-633c28f2066f3c11025ed4db6ccb45d824c1060e.zip
Escape quotes when expanding macro arguments.
This fixes a bug naddy@ found in plan9/rc(1).
-rw-r--r--regress/usr.bin/mandoc/roff/args/roff.in8
-rw-r--r--regress/usr.bin/mandoc/roff/args/roff.out_ascii3
-rw-r--r--regress/usr.bin/mandoc/roff/args/roff.out_lint20
-rw-r--r--usr.bin/mandoc/roff.c94
4 files changed, 96 insertions, 29 deletions
diff --git a/regress/usr.bin/mandoc/roff/args/roff.in b/regress/usr.bin/mandoc/roff/args/roff.in
index ff9a5781cc5..a305d00ba6a 100644
--- a/regress/usr.bin/mandoc/roff/args/roff.in
+++ b/regress/usr.bin/mandoc/roff/args/roff.in
@@ -1,8 +1,14 @@
-.TH ARGS-ROFF 1 "January 1, 2011"
+.TH ARGS-ROFF 1 "February 21, 2015"
.SH NAME
args-roff - arguments to roff macros
.SH DESCRIPTION
.de test
+.BI (\\$1) "(\\$2)"
+.br
+..
+arguments containing quotes:
+.test a"b a"b
+.de test
(\\$1) (\\$2)
.br
..
diff --git a/regress/usr.bin/mandoc/roff/args/roff.out_ascii b/regress/usr.bin/mandoc/roff/args/roff.out_ascii
index c5566de2746..52385a4196e 100644
--- a/regress/usr.bin/mandoc/roff/args/roff.out_ascii
+++ b/regress/usr.bin/mandoc/roff/args/roff.out_ascii
@@ -6,6 +6,7 @@ NNAAMMEE
args-roff - arguments to roff macros
DDEESSCCRRIIPPTTIIOONN
+ arguments containing quotes: ((aa""bb))_(_a_"_b_)
standard unquoted: (one) (two)
escaped blanks: (one one) (two two)
escaped 'e' character: (one\one) (two)
@@ -36,4 +37,4 @@ DDEESSCCRRIIPPTTIIOONN
- January 1, 2011 ARGS-ROFF(1)
+ February 21, 2015 ARGS-ROFF(1)
diff --git a/regress/usr.bin/mandoc/roff/args/roff.out_lint b/regress/usr.bin/mandoc/roff/args/roff.out_lint
index 0a57316606a..7c20a0488bc 100644
--- a/regress/usr.bin/mandoc/roff/args/roff.out_lint
+++ b/regress/usr.bin/mandoc/roff/args/roff.out_lint
@@ -1,11 +1,11 @@
-mandoc: roff.in:24:15: WARNING: whitespace at end of input line
-mandoc: roff.in:26:16: WARNING: whitespace at end of input line
-mandoc: roff.in:28:17: WARNING: whitespace at end of input line
-mandoc: roff.in:48:27: WARNING: whitespace at end of input line
-mandoc: roff.in:50:28: WARNING: whitespace at end of input line
-mandoc: roff.in:52:29: WARNING: whitespace at end of input line
-mandoc: roff.in:57:11: WARNING: unterminated quoted argument
-mandoc: roff.in:60:11: WARNING: unterminated quoted argument
-mandoc: roff.in:60:16: WARNING: whitespace at end of input line
+mandoc: roff.in:30:15: WARNING: whitespace at end of input line
+mandoc: roff.in:32:16: WARNING: whitespace at end of input line
+mandoc: roff.in:34:17: WARNING: whitespace at end of input line
+mandoc: roff.in:54:27: WARNING: whitespace at end of input line
+mandoc: roff.in:56:28: WARNING: whitespace at end of input line
+mandoc: roff.in:58:29: WARNING: whitespace at end of input line
mandoc: roff.in:63:11: WARNING: unterminated quoted argument
-mandoc: roff.in:63:17: WARNING: whitespace at end of input line
+mandoc: roff.in:66:11: WARNING: unterminated quoted argument
+mandoc: roff.in:66:16: WARNING: whitespace at end of input line
+mandoc: roff.in:69:11: WARNING: unterminated quoted argument
+mandoc: roff.in:69:17: WARNING: whitespace at end of input line
diff --git a/usr.bin/mandoc/roff.c b/usr.bin/mandoc/roff.c
index 7f294e2ed4b..3835f1adbfa 100644
--- a/usr.bin/mandoc/roff.c
+++ b/usr.bin/mandoc/roff.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: roff.c,v 1.134 2015/02/17 17:55:12 schwarze Exp $ */
+/* $OpenBSD: roff.c,v 1.135 2015/02/21 14:46:33 schwarze Exp $ */
/*
* Copyright (c) 2010, 2011, 2012, 2014 Kristaps Dzonsons <kristaps@bsd.lv>
* Copyright (c) 2010-2015 Ingo Schwarze <schwarze@openbsd.org>
@@ -2651,14 +2651,16 @@ roff_so(ROFF_ARGS)
static enum rofferr
roff_userdef(ROFF_ARGS)
{
- const char *arg[9];
+ const char *arg[9], *ap;
char *cp, *n1, *n2;
int i;
+ size_t asz, rsz;
/*
* Collect pointers to macro argument strings
* and NUL-terminate them.
*/
+
cp = buf->buf + pos;
for (i = 0; i < 9; i++)
arg[i] = *cp == '\0' ? "" :
@@ -2667,31 +2669,89 @@ roff_userdef(ROFF_ARGS)
/*
* Expand macro arguments.
*/
- buf->sz = 0;
- n1 = cp = mandoc_strdup(r->current_string);
- while ((cp = strstr(cp, "\\$")) != NULL) {
- i = cp[2] - '1';
- if (0 > i || 8 < i) {
- /* Not an argument invocation. */
- cp += 2;
+
+ buf->sz = strlen(r->current_string) + 1;
+ n1 = cp = mandoc_malloc(buf->sz);
+ memcpy(n1, r->current_string, buf->sz);
+ while (*cp != '\0') {
+
+ /* Scan ahead for the next argument invocation. */
+
+ if (*cp++ != '\\')
+ continue;
+ if (*cp++ != '$')
continue;
+ i = *cp - '1';
+ if (0 > i || 8 < i)
+ continue;
+ cp -= 2;
+
+ /*
+ * Determine the size of the expanded argument,
+ * taking escaping of quotes into account.
+ */
+
+ asz = 0;
+ for (ap = arg[i]; *ap != '\0'; ap++) {
+ asz++;
+ if (*ap == '"')
+ asz += 3;
+ }
+ if (asz != 3) {
+
+ /*
+ * Determine the size of the rest of the
+ * unexpanded macro, including the NUL.
+ */
+
+ rsz = buf->sz - (cp - n1) - 3;
+
+ /*
+ * When shrinking, move before
+ * releasing the storage.
+ */
+
+ if (asz < 3)
+ memmove(cp + asz, cp + 3, rsz);
+
+ /*
+ * Resize the storage for the macro
+ * and readjust the parse pointer.
+ */
+
+ buf->sz += asz - 3;
+ n2 = mandoc_realloc(n1, buf->sz);
+ cp = n2 + (cp - n1);
+ n1 = n2;
+
+ /*
+ * When growing, make room
+ * for the expanded argument.
+ */
+
+ if (asz > 3)
+ memmove(cp + asz, cp + 3, rsz);
+ }
+
+ /* Copy the expanded argument, escaping quotes. */
+
+ n2 = cp;
+ for (ap = arg[i]; *ap != '\0'; ap++) {
+ if (*ap == '"') {
+ memcpy(n2, "\\(dq", 4);
+ n2 += 4;
+ } else
+ *n2++ = *ap;
}
- *cp = '\0';
- buf->sz = mandoc_asprintf(&n2, "%s%s%s",
- n1, arg[i], cp + 3) + 1;
- cp = n2 + (cp - n1);
- free(n1);
- n1 = n2;
}
/*
* Replace the macro invocation
* by the expanded macro.
*/
+
free(buf->buf);
buf->buf = n1;
- if (buf->sz == 0)
- buf->sz = strlen(buf->buf) + 1;
*offs = 0;
return(buf->sz > 1 && buf->buf[buf->sz - 2] == '\n' ?