summaryrefslogtreecommitdiffstats
path: root/roff.c
diff options
context:
space:
mode:
authorIngo Schwarze <schwarze@openbsd.org>2019-02-06 21:11:43 +0000
committerIngo Schwarze <schwarze@openbsd.org>2019-02-06 21:11:43 +0000
commit386d70b32810ee1090f13d0944310eb93a0ba0fc (patch)
tree3f894d3f306d64ebe183d2f08edc2f8b7ffe8dcc /roff.c
parent3b603764164fcabf9c701ff02e59f9410c580ae8 (diff)
downloadmandoc-386d70b32810ee1090f13d0944310eb93a0ba0fc.tar.gz
Let roff_getname() end the roff identifier at a tab character
and audit all its callers whether termination is handled correctly. Resulting improvements: * An escape or tab ending the macro name in a macro invocation is discarded, and argument processing is started after it. * An escape or tab ending a name in ".if d" and ".if r" is preserved. * An escape ending a name in ".ds" causes the whole request to be ignored. * A tab ending a name in ".ds" becomes part of the string. * An escape or tab ending a name in ".rm" causes the rest of the line to be ignored. * An escape or tab ending the first name in ".als", ".rn", or ".nr" causes the whole request to be ignored. Kurt Jaeger <pi at FreeBSD> made me aware of https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=235456#c0 and in that bug report, comment 0 item (3) is a special case of this class of issues. Yes, the "mh" manual pages are no doubt among the worst on the planet.
Diffstat (limited to 'roff.c')
-rw-r--r--roff.c25
1 files changed, 18 insertions, 7 deletions
diff --git a/roff.c b/roff.c
index d0156977..0766abad 100644
--- a/roff.c
+++ b/roff.c
@@ -2537,7 +2537,7 @@ roff_evalcond(struct roff *r, int ln, char *v, int *pos)
roff_getstrn(r, name, sz, &deftype);
istrue = !!deftype;
}
- *pos = cp - v;
+ *pos = (name + sz) - v;
return istrue == wanttrue;
default:
break;
@@ -2683,8 +2683,15 @@ roff_ds(ROFF_ARGS)
return ROFF_IGN;
namesz = roff_getname(r, &string, ln, pos);
- if (name[namesz] == '\\')
+ switch (name[namesz]) {
+ case '\\':
return ROFF_IGN;
+ case '\t':
+ string = buf->buf + pos + namesz;
+ break;
+ default:
+ break;
+ }
/* Read past the initial double-quote, if any. */
if (*string == '"')
@@ -3060,7 +3067,7 @@ roff_nr(ROFF_ARGS)
return ROFF_IGN;
keysz = roff_getname(r, &val, ln, pos);
- if (key[keysz] == '\\')
+ if (key[keysz] == '\\' || key[keysz] == '\t')
return ROFF_IGN;
sign = *val;
@@ -3124,7 +3131,7 @@ roff_rm(ROFF_ARGS)
namesz = roff_getname(r, &cp, ln, (int)(cp - buf->buf));
roff_setstrn(&r->strtab, name, namesz, NULL, 0, 0);
roff_setstrn(&r->rentab, name, namesz, NULL, 0, 0);
- if (name[namesz] == '\\')
+ if (name[namesz] == '\\' || name[namesz] == '\t')
break;
}
return ROFF_IGN;
@@ -3459,7 +3466,7 @@ roff_als(ROFF_ARGS)
return ROFF_IGN;
newsz = roff_getname(r, &oldn, ln, pos);
- if (newn[newsz] == '\\' || *oldn == '\0')
+ if (newn[newsz] == '\\' || newn[newsz] == '\t' || *oldn == '\0')
return ROFF_IGN;
end = oldn;
@@ -3689,7 +3696,7 @@ roff_rn(ROFF_ARGS)
return ROFF_IGN;
oldsz = roff_getname(r, &newn, ln, pos);
- if (oldn[oldsz] == '\\' || *newn == '\0')
+ if (oldn[oldsz] == '\\' || oldn[oldsz] == '\t' || *newn == '\0')
return ROFF_IGN;
end = newn;
@@ -3883,8 +3890,12 @@ roff_getname(struct roff *r, char **cpp, int ln, int pos)
for (cp = name; 1; cp++) {
namesz = cp - name;
- if (*cp == '\0' || *cp == ' ')
+ if (*cp == '\0')
break;
+ if (*cp == ' ' || *cp == '\t') {
+ cp++;
+ break;
+ }
if (*cp != '\\')
continue;
if (cp[1] == '{' || cp[1] == '}')