When a man(7) document contains unreasonably large numbers for
authorschwarze <schwarze@openbsd.org>
Wed, 24 Dec 2014 09:57:41 +0000 (09:57 +0000)
committerschwarze <schwarze@openbsd.org>
Wed, 24 Dec 2014 09:57:41 +0000 (09:57 +0000)
indentations or paragraph distances, large output may be generated,
which is practically the same as an endless loop; found by jsg@
with afl.
Reject such unreasonably large numbers beyond arbitrary limits
similar to those used by groff (max. 65 blank lines between paragraphs
and max. SHRT_MAX characters per output line) and fall back to
defaults when exceeded.  Having the limits behave in exactly the
same way is not relevant.

usr.bin/mandoc/man_term.c
usr.bin/mandoc/term.c

index 68324f2..314f8fd 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: man_term.c,v 1.116 2014/12/23 13:48:15 schwarze Exp $ */
+/*     $OpenBSD: man_term.c,v 1.117 2014/12/24 09:57:41 schwarze Exp $ */
 /*
  * Copyright (c) 2008-2012 Kristaps Dzonsons <kristaps@bsd.lv>
  * Copyright (c) 2010-2014 Ingo Schwarze <schwarze@openbsd.org>
@@ -19,6 +19,7 @@
 
 #include <assert.h>
 #include <ctype.h>
+#include <limits.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
@@ -430,6 +431,8 @@ pre_in(DECL_ARGS)
                p->offset += v;
        else
                p->offset = v;
+       if (p->offset > SHRT_MAX)
+               p->offset = term_len(p, p->defindent);
 
        return(0);
 }
@@ -506,16 +509,16 @@ pre_HP(DECL_ARGS)
        if ((nn = n->parent->head->child) != NULL &&
            a2roffsu(nn->string, &su, SCALE_EN)) {
                len = term_hspan(p, &su);
+               if (len < 0 && (size_t)(-len) > mt->offset)
+                       len = -mt->offset;
+               else if (len > SHRT_MAX)
+                       len = term_len(p, p->defindent);
                mt->lmargin[mt->lmargincur] = len;
        } else
                len = mt->lmargin[mt->lmargincur];
 
        p->offset = mt->offset;
-       if (len > 0 || (size_t)(-len) < mt->offset)
-               p->rmargin = mt->offset + len;
-       else
-               p->rmargin = 0;
-
+       p->rmargin = mt->offset + len;
        return(1);
 }
 
@@ -580,9 +583,11 @@ pre_IP(DECL_ARGS)
            (nn = nn->next) != NULL &&
            a2roffsu(nn->string, &su, SCALE_EN)) {
                len = term_hspan(p, &su);
-               mt->lmargin[mt->lmargincur] = len;
                if (len < 0 && (size_t)(-len) > mt->offset)
                        len = -mt->offset;
+               else if (len > SHRT_MAX)
+                       len = term_len(p, p->defindent);
+               mt->lmargin[mt->lmargincur] = len;
        } else
                len = mt->lmargin[mt->lmargincur];
 
@@ -660,9 +665,11 @@ pre_TP(DECL_ARGS)
            nn->string != NULL && ! (MAN_LINE & nn->flags) &&
            a2roffsu(nn->string, &su, SCALE_EN)) {
                len = term_hspan(p, &su);
-               mt->lmargin[mt->lmargincur] = len;
                if (len < 0 && (size_t)(-len) > mt->offset)
                        len = -mt->offset;
+               else if (len > SHRT_MAX)
+                       len = term_len(p, p->defindent);
+               mt->lmargin[mt->lmargincur] = len;
        } else
                len = mt->lmargin[mt->lmargincur];
 
@@ -843,10 +850,11 @@ pre_RS(DECL_ARGS)
                break;
        }
 
+       len = SHRT_MAX + 1;
        if ((n = n->parent->head->child) != NULL &&
            a2roffsu(n->string, &su, SCALE_EN))
                len = term_hspan(p, &su);
-       else
+       if (len > SHRT_MAX)
                len = term_len(p, p->defindent);
 
        if (len > 0 || (size_t)(-len) < mt->offset)
@@ -879,10 +887,11 @@ post_RS(DECL_ARGS)
                break;
        }
 
+       len = SHRT_MAX + 1;
        if ((n = n->parent->head->child) != NULL &&
            a2roffsu(n->string, &su, SCALE_EN))
                len = term_hspan(p, &su);
-       else
+       if (len > SHRT_MAX)
                len = term_len(p, p->defindent);
 
        if (len < 0 || (size_t)len < mt->offset)
index 21443c7..76836aa 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: term.c,v 1.100 2014/12/23 13:48:15 schwarze Exp $ */
+/*     $OpenBSD: term.c,v 1.101 2014/12/24 09:57:41 schwarze Exp $ */
 /*
  * Copyright (c) 2008, 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
  * Copyright (c) 2010-2014 Ingo Schwarze <schwarze@openbsd.org>
@@ -771,6 +771,7 @@ int
 term_vspan(const struct termp *p, const struct roffsu *su)
 {
        double           r;
+       int              ri;
 
        switch (su->unit) {
        case SCALE_BU:
@@ -806,7 +807,8 @@ term_vspan(const struct termp *p, const struct roffsu *su)
                abort();
                /* NOTREACHED */
        }
-       return(r > 0.0 ? r + 0.4995 : r - 0.4995);
+       ri = r > 0.0 ? r + 0.4995 : r - 0.4995;
+       return(ri < 66 ? ri : 1);
 }
 
 int