From c48a07355a7037b7b7963b62e6147321f85ce34d Mon Sep 17 00:00:00 2001 From: schwarze Date: Fri, 19 Dec 2014 17:10:42 +0000 Subject: [PATCH] Enforcing an arbitrary, implementation dependent, undocumented limit 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 | 34 +++++++++++++++++++--------------- usr.bin/mandoc/term.h | 10 +++++----- usr.bin/mandoc/term_ascii.c | 5 ++++- usr.bin/mandoc/term_ps.c | 5 ++++- 4 files changed, 32 insertions(+), 22 deletions(-) diff --git a/usr.bin/mandoc/term.c b/usr.bin/mandoc/term.c index 5172d4b84ca..79f02395ba1 100644 --- a/usr.bin/mandoc/term.c +++ b/usr.bin/mandoc/term.c @@ -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 * Copyright (c) 2010-2014 Ingo Schwarze @@ -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++) diff --git a/usr.bin/mandoc/term.h b/usr.bin/mandoc/term.h index 3c09886acbe..afdffd0f857 100644 --- a/usr.bin/mandoc/term.h +++ b/usr.bin/mandoc/term.h @@ -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 * Copyright (c) 2011, 2012, 2013, 2014 Ingo Schwarze @@ -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 *); diff --git a/usr.bin/mandoc/term_ascii.c b/usr.bin/mandoc/term_ascii.c index 98818e7c25c..635c2e8ab3a 100644 --- a/usr.bin/mandoc/term_ascii.c +++ b/usr.bin/mandoc/term_ascii.c @@ -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 * Copyright (c) 2014 Ingo Schwarze @@ -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; diff --git a/usr.bin/mandoc/term_ps.c b/usr.bin/mandoc/term_ps.c index 1d803a2f7a9..08cefafae09 100644 --- a/usr.bin/mandoc/term_ps.c +++ b/usr.bin/mandoc/term_ps.c @@ -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 * Copyright (c) 2014 Ingo Schwarze @@ -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; -- 2.20.1