diff options
author | Ingo Schwarze <schwarze@cvs.openbsd.org> | 2014-10-20 19:21:32 +0000 |
---|---|---|
committer | Ingo Schwarze <schwarze@cvs.openbsd.org> | 2014-10-20 19:21:32 +0000 |
commit | 15378b106261d4dcf96971b76263fbd61c8c785f (patch) | |
tree | 1a5c6c8fbf18375a1014c7c6b7332f9c59cb5510 /usr.bin/mandoc | |
parent | 6890ab396ffd97f9ea78fa443dd7fe49e4f09c71 (diff) |
protect the roff parser from dividing by zero;
issue found and patch written by kristaps@
Diffstat (limited to 'usr.bin/mandoc')
-rw-r--r-- | usr.bin/mandoc/mandoc.h | 3 | ||||
-rw-r--r-- | usr.bin/mandoc/read.c | 3 | ||||
-rw-r--r-- | usr.bin/mandoc/roff.c | 39 |
3 files changed, 29 insertions, 16 deletions
diff --git a/usr.bin/mandoc/mandoc.h b/usr.bin/mandoc/mandoc.h index e2c8975a478..2512e8b11d3 100644 --- a/usr.bin/mandoc/mandoc.h +++ b/usr.bin/mandoc/mandoc.h @@ -1,4 +1,4 @@ -/* $OpenBSD: mandoc.h,v 1.106 2014/10/14 02:16:02 schwarze Exp $ */ +/* $OpenBSD: mandoc.h,v 1.107 2014/10/20 19:21:31 schwarze Exp $ */ /* * Copyright (c) 2010, 2011, 2014 Kristaps Dzonsons <kristaps@bsd.lv> * Copyright (c) 2010-2014 Ingo Schwarze <schwarze@openbsd.org> @@ -166,6 +166,7 @@ enum mandocerr { MANDOCERR_IT_NONUM, /* skipping request without numeric argument */ MANDOCERR_ARG_SKIP, /* skipping all arguments: macro args */ MANDOCERR_ARG_EXCESS, /* skipping excess arguments: macro ... args */ + MANDOCERR_DIVZERO, /* divide by zero */ MANDOCERR_FATAL, /* ===== start of fatal errors ===== */ diff --git a/usr.bin/mandoc/read.c b/usr.bin/mandoc/read.c index 2ca7b519723..f45fb3bf28c 100644 --- a/usr.bin/mandoc/read.c +++ b/usr.bin/mandoc/read.c @@ -1,4 +1,4 @@ -/* $OpenBSD: read.c,v 1.67 2014/10/18 15:46:16 schwarze Exp $ */ +/* $OpenBSD: read.c,v 1.68 2014/10/20 19:21:31 schwarze Exp $ */ /* * Copyright (c) 2008, 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv> * Copyright (c) 2010-2014 Ingo Schwarze <schwarze@openbsd.org> @@ -205,6 +205,7 @@ static const char * const mandocerrs[MANDOCERR_MAX] = { "skipping request without numeric argument", "skipping all arguments", "skipping excess arguments", + "divide by zero", "generic fatal error", diff --git a/usr.bin/mandoc/roff.c b/usr.bin/mandoc/roff.c index c6f0338759f..685a85d9be2 100644 --- a/usr.bin/mandoc/roff.c +++ b/usr.bin/mandoc/roff.c @@ -1,4 +1,4 @@ -/* $OpenBSD: roff.c,v 1.105 2014/10/20 15:04:37 schwarze Exp $ */ +/* $OpenBSD: roff.c,v 1.106 2014/10/20 19:21:31 schwarze Exp $ */ /* * Copyright (c) 2010, 2011, 2012 Kristaps Dzonsons <kristaps@bsd.lv> * Copyright (c) 2010-2014 Ingo Schwarze <schwarze@openbsd.org> @@ -184,9 +184,12 @@ static enum rofferr roff_cond_sub(ROFF_ARGS); static enum rofferr roff_ds(ROFF_ARGS); static enum rofferr roff_eqndelim(struct roff *, char **, size_t *, int); -static int roff_evalcond(const char *, int *); -static int roff_evalnum(const char *, int *, int *, int); -static int roff_evalpar(const char *, int *, int *); +static int roff_evalcond(struct roff *r, int, + const char *, int *); +static int roff_evalnum(struct roff *, int, + const char *, int *, int *, int); +static int roff_evalpar(struct roff *, int, + const char *, int *, int *); static int roff_evalstrcond(const char *, int *); static void roff_free1(struct roff *); static void roff_freereg(struct roffreg *); @@ -620,7 +623,7 @@ roff_res(struct roff *r, char **bufp, size_t *szp, int ln, int pos) case 'B': npos = 0; ubuf[0] = arg_complete && - roff_evalnum(stnam, &npos, NULL, 0) && + roff_evalnum(r, ln, stnam, &npos, NULL, 0) && stnam + npos + 1 == cp ? '1' : '0'; ubuf[1] = '\0'; break; @@ -1238,7 +1241,7 @@ out: * or string condition. */ static int -roff_evalcond(const char *v, int *pos) +roff_evalcond(struct roff *r, int ln, const char *v, int *pos) { int wanttrue, number; @@ -1269,7 +1272,7 @@ roff_evalcond(const char *v, int *pos) break; } - if (roff_evalnum(v, pos, &number, 0)) + if (roff_evalnum(r, ln, v, pos, &number, 0)) return((number > 0) == wanttrue); else return(roff_evalstrcond(v, pos) == wanttrue); @@ -1298,7 +1301,7 @@ roff_cond(ROFF_ARGS) r->last->rule = ROFF_el == tok ? (r->rstackpos < 0 ? 0 : r->rstack[r->rstackpos--]) : - roff_evalcond(*bufp, &pos); + roff_evalcond(r, ln, *bufp, &pos); /* * An if-else will put the NEGATION of the current evaluated @@ -1464,14 +1467,15 @@ roff_getop(const char *v, int *pos, char *res) * or a single signed integer number. */ static int -roff_evalpar(const char *v, int *pos, int *res) +roff_evalpar(struct roff *r, int ln, + const char *v, int *pos, int *res) { if ('(' != v[*pos]) return(roff_getnum(v, pos, res)); (*pos)++; - if ( ! roff_evalnum(v, pos, res, 1)) + if ( ! roff_evalnum(r, ln, v, pos, res, 1)) return(0); /* @@ -1493,7 +1497,8 @@ roff_evalpar(const char *v, int *pos, int *res) * Proceed left to right, there is no concept of precedence. */ static int -roff_evalnum(const char *v, int *pos, int *res, int skipwhite) +roff_evalnum(struct roff *r, int ln, const char *v, + int *pos, int *res, int skipwhite) { int mypos, operand2; char operator; @@ -1507,7 +1512,7 @@ roff_evalnum(const char *v, int *pos, int *res, int skipwhite) while (isspace((unsigned char)v[*pos])) (*pos)++; - if ( ! roff_evalpar(v, pos, res)) + if ( ! roff_evalpar(r, ln, v, pos, res)) return(0); while (1) { @@ -1522,7 +1527,7 @@ roff_evalnum(const char *v, int *pos, int *res, int skipwhite) while (isspace((unsigned char)v[*pos])) (*pos)++; - if ( ! roff_evalpar(v, pos, &operand2)) + if ( ! roff_evalpar(r, ln, v, pos, &operand2)) return(0); if (skipwhite) @@ -1543,6 +1548,12 @@ roff_evalnum(const char *v, int *pos, int *res, int skipwhite) *res *= operand2; break; case '/': + if (0 == operand2) { + mandoc_msg(MANDOCERR_DIVZERO, + r->parse, ln, *pos, v); + *res = 0; + break; + } *res /= operand2; break; case '%': @@ -1717,7 +1728,7 @@ roff_nr(ROFF_ARGS) if ('+' == sign || '-' == sign) val++; - if (roff_evalnum(val, NULL, &iv, 0)) + if (roff_evalnum(r, ln, val, NULL, &iv, 0)) roff_setreg(r, key, iv, sign); return(ROFF_IGN); |