=================================================================== RCS file: /cvs/mandoc/roff.c,v retrieving revision 1.242 retrieving revision 1.250 diff -u -p -r1.242 -r1.250 --- mandoc/roff.c 2014/12/16 03:53:43 1.242 +++ mandoc/roff.c 2015/01/16 16:53:49 1.250 @@ -1,7 +1,7 @@ -/* $Id: roff.c,v 1.242 2014/12/16 03:53:43 schwarze Exp $ */ +/* $Id: roff.c,v 1.250 2015/01/16 16:53:49 schwarze Exp $ */ /* - * Copyright (c) 2010, 2011, 2012 Kristaps Dzonsons - * Copyright (c) 2010-2014 Ingo Schwarze + * Copyright (c) 2010, 2011, 2012, 2014 Kristaps Dzonsons + * Copyright (c) 2010-2015 Ingo Schwarze * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -21,6 +21,7 @@ #include #include +#include #include #include #include @@ -74,6 +75,7 @@ enum rofft { ROFF_T_, ROFF_EQ, ROFF_EN, + ROFF_IX, ROFF_cblock, ROFF_USERDEF, ROFF_MAX @@ -273,6 +275,7 @@ static struct roffmac roffs[ROFF_MAX] = { { "T&", roff_T_, NULL, NULL, 0, NULL }, { "EQ", roff_EQ, NULL, NULL, 0, NULL }, { "EN", roff_EN, NULL, NULL, 0, NULL }, + { "IX", roff_line_ignore, NULL, NULL, 0, NULL }, { ".", roff_cblock, NULL, NULL, 0, NULL }, { NULL, roff_userdef, NULL, NULL, 0, NULL }, }; @@ -650,6 +653,10 @@ roff_res(struct roff *r, struct buf *buf, int ln, int r->parse, ln, (int)(stesc - buf->buf), "%.*s", (int)naml, stnam); res = ""; + } else if (buf->sz + strlen(res) > SHRT_MAX) { + mandoc_msg(MANDOCERR_ROFFLOOP, r->parse, + ln, (int)(stesc - buf->buf), NULL); + return(ROFF_IGN); } /* Replace the escape sequence by the string. */ @@ -730,6 +737,7 @@ roff_parseln(struct roff *r, int ln, struct buf *buf, enum rofft t; enum rofferr e; int pos; /* parse point */ + int spos; /* saved parse point for messages */ int ppos; /* original offset in buf->buf */ int ctl; /* macro line (boolean) */ @@ -800,15 +808,29 @@ roff_parseln(struct roff *r, int ln, struct buf *buf, return((*roffs[t].sub)(r, t, buf, ln, ppos, pos, offs)); } + /* No scope is open. This is a new request or macro. */ + + spos = pos; + t = roff_parse(r, buf->buf, &pos, ln, ppos); + + /* Tables ignore most macros. */ + + if (r->tbl != NULL && (t == ROFF_MAX || t == ROFF_TS)) { + mandoc_msg(MANDOCERR_TBLMACRO, r->parse, + ln, pos, buf->buf + spos); + return(ROFF_IGN); + } + /* - * Lastly, as we've no scope open, try to look up and execute - * the new macro. If no macro is found, simply return and let - * the compilers handle it. + * This is neither a roff request nor a user-defined macro. + * Let the standard macro set parsers handle it. */ - if ((t = roff_parse(r, buf->buf, &pos, ln, ppos)) == ROFF_MAX) + if (t == ROFF_MAX) return(ROFF_CONT); + /* Execute a roff request or a user defined macro. */ + assert(roffs[t].proc); return((*roffs[t].proc)(r, t, buf, ln, ppos, pos, offs)); } @@ -1143,7 +1165,8 @@ roff_cond_sub(ROFF_ARGS) *ep = '&'; roff_ccond(r, ln, ep - buf->buf - 1); } - ++ep; + if (*ep != '\0') + ++ep; } return(rr ? ROFF_CONT : ROFF_IGN); } @@ -1163,7 +1186,8 @@ roff_cond_text(ROFF_ARGS) *ep = '&'; roff_ccond(r, ln, ep - buf->buf - 1); } - ++ep; + if (*ep != '\0') + ++ep; } return(rr ? ROFF_CONT : ROFF_IGN); } @@ -1561,7 +1585,7 @@ roff_evalnum(struct roff *r, int ln, const char *v, *res *= operand2; break; case '/': - if (0 == operand2) { + if (operand2 == 0) { mandoc_msg(MANDOCERR_DIVZERO, r->parse, ln, *pos, v); *res = 0; @@ -1570,6 +1594,12 @@ roff_evalnum(struct roff *r, int ln, const char *v, *res /= operand2; break; case '%': + if (operand2 == 0) { + mandoc_msg(MANDOCERR_DIVZERO, + r->parse, ln, *pos, v); + *res = 0; + break; + } *res %= operand2; break; case '<': @@ -2075,7 +2105,7 @@ roff_tr(ROFF_ARGS) static enum rofferr roff_so(ROFF_ARGS) { - char *name; + char *name, *cp; name = buf->buf + pos; mandoc_vmsg(MANDOCERR_SO, r->parse, ln, ppos, "so %s", name); @@ -2090,7 +2120,12 @@ roff_so(ROFF_ARGS) if (*name == '/' || strstr(name, "../") || strstr(name, "/..")) { mandoc_vmsg(MANDOCERR_SO_PATH, r->parse, ln, ppos, ".so %s", name); - return(ROFF_ERR); + buf->sz = mandoc_asprintf(&cp, + ".sp\nSee the file %s.\n.sp", name) + 1; + free(buf->buf); + buf->buf = cp; + *offs = 0; + return(ROFF_REPARSE); } *offs = pos; @@ -2141,6 +2176,7 @@ roff_userdef(ROFF_ARGS) 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' ? ROFF_REPARSE : ROFF_APPEND);