Enforcing an arbitrary, implementation dependent, undocumented limit
authorschwarze <schwarze@openbsd.org>
Fri, 19 Dec 2014 17:10:42 +0000 (17:10 +0000)
committerschwarze <schwarze@openbsd.org>
Fri, 19 Dec 2014 17:10:42 +0000 (17:10 +0000)
by calling assert() when valid user input exceeds it is a bad idea.
Allocate the terminal font stack dynamically instead of crashing
above 10 entries.  Issue found by jsg@ with afl.

usr.bin/mandoc/term.c
usr.bin/mandoc/term.h
usr.bin/mandoc/term_ascii.c
usr.bin/mandoc/term_ps.c

index 5172d4b..79f0239 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: term.c,v 1.97 2014/12/02 10:07:17 schwarze Exp $ */
+/*     $OpenBSD: term.c,v 1.98 2014/12/19 17:10:42 schwarze Exp $ */
 /*
  * Copyright (c) 2008, 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
  * Copyright (c) 2010-2014 Ingo Schwarze <schwarze@openbsd.org>
@@ -41,6 +41,7 @@ term_free(struct termp *p)
 {
 
        free(p->buf);
+       free(p->fontq);
        free(p);
 }
 
@@ -327,6 +328,7 @@ term_vspace(struct termp *p)
                (*p->endline)(p);
 }
 
+/* Swap current and previous font; for \fP and .ft P */
 void
 term_fontlast(struct termp *p)
 {
@@ -337,6 +339,7 @@ term_fontlast(struct termp *p)
        p->fontq[p->fonti] = f;
 }
 
+/* Set font, save current, discard previous; for \f, .ft, .B etc. */
 void
 term_fontrepl(struct termp *p, enum termfont f)
 {
@@ -345,38 +348,39 @@ term_fontrepl(struct termp *p, enum termfont f)
        p->fontq[p->fonti] = f;
 }
 
+/* Set font, save previous. */
 void
 term_fontpush(struct termp *p, enum termfont f)
 {
 
-       assert(p->fonti + 1 < 10);
        p->fontl = p->fontq[p->fonti];
-       p->fontq[++p->fonti] = f;
+       if (++p->fonti == p->fontsz) {
+               p->fontsz += 8;
+               p->fontq = mandoc_reallocarray(p->fontq,
+                   p->fontsz, sizeof(enum termfont *));
+       }
+       p->fontq[p->fonti] = f;
 }
 
-const void *
+/* Retrieve pointer to current font. */
+const enum termfont *
 term_fontq(struct termp *p)
 {
 
        return(&p->fontq[p->fonti]);
 }
 
-enum termfont
-term_fonttop(struct termp *p)
-{
-
-       return(p->fontq[p->fonti]);
-}
-
+/* Flush to make the saved pointer current again. */
 void
-term_fontpopq(struct termp *p, const void *key)
+term_fontpopq(struct termp *p, const enum termfont *key)
 {
 
-       while (p->fonti >= 0 && key < (void *)(p->fontq + p->fonti))
+       while (p->fonti >= 0 && key < p->fontq + p->fonti)
                p->fonti--;
        assert(p->fonti >= 0);
 }
 
+/* Pop one font off the stack. */
 void
 term_fontpop(struct termp *p)
 {
@@ -552,7 +556,7 @@ encode1(struct termp *p, int c)
        if (p->col + 6 >= p->maxcols)
                adjbuf(p, p->col + 6);
 
-       f = term_fonttop(p);
+       f = *term_fontq(p);
 
        if (TERMFONT_UNDER == f || TERMFONT_BI == f) {
                p->buf[p->col++] = '_';
@@ -584,7 +588,7 @@ encode(struct termp *p, const char *word, size_t sz)
         * character by character.
         */
 
-       if (TERMFONT_NONE == term_fonttop(p)) {
+       if (*term_fontq(p) == TERMFONT_NONE) {
                if (p->col + sz >= p->maxcols)
                        adjbuf(p, p->col + sz);
                for (i = 0; i < sz; i++)
index 3c09886..afdffd0 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: term.h,v 1.52 2014/12/02 10:07:17 schwarze Exp $ */
+/*     $OpenBSD: term.h,v 1.53 2014/12/19 17:10:42 schwarze Exp $ */
 /*
  * Copyright (c) 2008, 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
  * Copyright (c) 2011, 2012, 2013, 2014 Ingo Schwarze <schwarze@openbsd.org>
@@ -84,7 +84,8 @@ struct        termp {
        enum termenc      enc;          /* Type of encoding. */
        const struct mchars *symtab;    /* Character table. */
        enum termfont     fontl;        /* Last font set. */
-       enum termfont     fontq[10];    /* Symmetric fonts. */
+       enum termfont    *fontq;        /* Symmetric fonts. */
+       int               fontsz;       /* Allocated size of font stack */
        int               fonti;        /* Index of font stack. */
        term_margin       headf;        /* invoked to print head */
        term_margin       footf;        /* invoked to print foot */
@@ -127,11 +128,10 @@ size_t              term_vspan(const struct termp *,
 size_t           term_strlen(const struct termp *, const char *);
 size_t           term_len(const struct termp *, size_t);
 
-enum termfont    term_fonttop(struct termp *);
-const void      *term_fontq(struct termp *);
+const enum termfont *term_fontq(struct termp *);
 void             term_fontpush(struct termp *, enum termfont);
 void             term_fontpop(struct termp *);
-void             term_fontpopq(struct termp *, const void *);
+void             term_fontpopq(struct termp *, const enum termfont *);
 void             term_fontrepl(struct termp *, enum termfont);
 void             term_fontlast(struct termp *);
 
index 98818e7..635c2e8 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: term_ascii.c,v 1.27 2014/11/20 13:55:23 schwarze Exp $ */
+/*     $OpenBSD: term_ascii.c,v 1.28 2014/12/19 17:10:42 schwarze Exp $ */
 /*
  * Copyright (c) 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
  * Copyright (c) 2014 Ingo Schwarze <schwarze@openbsd.org>
@@ -61,6 +61,9 @@ ascii_init(enum termenc enc, const struct mchars *mchars, char *outopts)
        p->symtab = mchars;
        p->tabwidth = 5;
        p->defrmargin = p->lastrmargin = 78;
+       p->fontq = mandoc_reallocarray(NULL,
+            (p->fontsz = 8), sizeof(enum termfont));
+       p->fontq[0] = p->fontl = TERMFONT_NONE;
 
        p->begin = ascii_begin;
        p->end = ascii_end;
index 1d803a2..08cefaf 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: term_ps.c,v 1.35 2014/12/01 08:05:02 schwarze Exp $ */
+/*     $OpenBSD: term_ps.c,v 1.36 2014/12/19 17:10:42 schwarze Exp $ */
 /*
  * Copyright (c) 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
  * Copyright (c) 2014 Ingo Schwarze <schwarze@openbsd.org>
@@ -535,6 +535,9 @@ pspdf_alloc(const struct mchars *mchars, char *outopts)
        p = mandoc_calloc(1, sizeof(struct termp));
        p->symtab = mchars;
        p->enc = TERMENC_ASCII;
+       p->fontq = mandoc_reallocarray(NULL,
+           (p->fontsz = 8), sizeof(enum termfont));
+       p->fontq[0] = p->fontl = TERMFONT_NONE;
        p->ps = mandoc_calloc(1, sizeof(struct termp_ps));
 
        p->advance = ps_advance;