]> git.cameronkatri.com Git - mandoc.git/commitdiff
Protect the roff parser from dividing by zero. ok schwarze@
authorKristaps Dzonsons <kristaps@bsd.lv>
Mon, 20 Oct 2014 19:04:45 +0000 (19:04 +0000)
committerKristaps Dzonsons <kristaps@bsd.lv>
Mon, 20 Oct 2014 19:04:45 +0000 (19:04 +0000)
mandoc.h
read.c
roff.c

index e7eefc07060fb1e534c0742e7cf545e0b4c595d6..b7493f4b63455e0e1e252b7e17f7de0f3b0d5315 100644 (file)
--- a/mandoc.h
+++ b/mandoc.h
@@ -1,4 +1,4 @@
-/*     $Id: mandoc.h,v 1.163 2014/10/14 02:16:06 schwarze Exp $ */
+/*     $Id: mandoc.h,v 1.164 2014/10/20 19:04:45 kristaps 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/read.c b/read.c
index 1bcc8cac4a856e911c16d25ad50d8344e0477b72..6c042e3f628fd534ad01eb6b6f172a66837346a5 100644 (file)
--- a/read.c
+++ b/read.c
@@ -1,4 +1,4 @@
-/*     $Id: read.c,v 1.91 2014/10/18 15:57:34 schwarze Exp $ */
+/*     $Id: read.c,v 1.92 2014/10/20 19:04:45 kristaps Exp $ */
 /*
  * Copyright (c) 2008, 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
  * Copyright (c) 2010-2014 Ingo Schwarze <schwarze@openbsd.org>
@@ -211,6 +211,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/roff.c b/roff.c
index 1dde1d4c4934f5976a983209f47277f60bb7fc18..7bd7b484449a602f577124166233eabaa6b726b2 100644 (file)
--- a/roff.c
+++ b/roff.c
@@ -1,4 +1,4 @@
-/*     $Id: roff.c,v 1.233 2014/10/20 15:04:56 schwarze Exp $ */
+/*     $Id: roff.c,v 1.234 2014/10/20 19:04:45 kristaps Exp $ */
 /*
  * Copyright (c) 2010, 2011, 2012 Kristaps Dzonsons <kristaps@bsd.lv>
  * Copyright (c) 2010-2014 Ingo Schwarze <schwarze@openbsd.org>
@@ -186,9 +186,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 *);
@@ -622,7 +625,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;
@@ -1240,7 +1243,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;
 
@@ -1271,7 +1274,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);
@@ -1300,7 +1303,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
@@ -1466,14 +1469,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);
 
        /*
@@ -1495,7 +1499,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;
@@ -1509,7 +1514,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) {
@@ -1524,7 +1529,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)
@@ -1545,6 +1550,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 '%':
@@ -1719,7 +1730,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);