]> git.cameronkatri.com Git - mandoc.git/blobdiff - roff.c
Simplify handling of system errors: just exit(3).
[mandoc.git] / roff.c
diff --git a/roff.c b/roff.c
index 37a036214dfd9b3cc248190de2fd45465c28cfb9..ab1cbfeaae8244175c640867f0dc9754bbbc4ea2 100644 (file)
--- a/roff.c
+++ b/roff.c
@@ -1,7 +1,7 @@
-/*     $Id: roff.c,v 1.241 2014/12/16 01:22:59 schwarze Exp $ */
+/*     $Id: roff.c,v 1.248 2015/01/07 12:19:46 schwarze Exp $ */
 /*
- * Copyright (c) 2010, 2011, 2012 Kristaps Dzonsons <kristaps@bsd.lv>
- * Copyright (c) 2010-2014 Ingo Schwarze <schwarze@openbsd.org>
+ * Copyright (c) 2010, 2011, 2012, 2014 Kristaps Dzonsons <kristaps@bsd.lv>
+ * Copyright (c) 2010-2015 Ingo Schwarze <schwarze@openbsd.org>
  *
  * 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 <assert.h>
 #include <ctype.h>
+#include <limits.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
@@ -650,6 +651,10 @@ roff_res(struct roff *r, struct buf *buf, int ln, int pos)
                            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 +735,7 @@ roff_parseln(struct roff *r, int ln, struct buf *buf, int *offs)
        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 +806,29 @@ roff_parseln(struct roff *r, int ln, struct buf *buf, int *offs)
                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 +1163,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 +1184,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);
 }
@@ -1236,7 +1258,7 @@ roff_evalstrcond(const char *v, int *pos)
 out:
        if (NULL == s3)
                s3 = strchr(s2, '\0');
-       else
+       else if (*s3 != '\0')
                s3++;
        *pos = s3 - v;
        return(match);
@@ -1561,7 +1583,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 +1592,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 '<':
@@ -2141,6 +2169,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);