diff options
author | Ingo Schwarze <schwarze@openbsd.org> | 2014-11-21 01:52:53 +0000 |
---|---|---|
committer | Ingo Schwarze <schwarze@openbsd.org> | 2014-11-21 01:52:53 +0000 |
commit | 6242a9efa48427465988912bdb7e56c75b239acf (patch) | |
tree | 0ddf5283f0848a0c7880a54f9e8c00f1519a5a91 | |
parent | b300a4ff9ca15ee75ac8b05afd9d5817390384ae (diff) | |
download | mandoc-6242a9efa48427465988912bdb7e56c75b239acf.tar.gz mandoc-6242a9efa48427465988912bdb7e56c75b239acf.tar.zst mandoc-6242a9efa48427465988912bdb7e56c75b239acf.zip |
We repeatedly observed assertion crashes in the low-level terminal
output handler because the high level terminal formatters could be
tricked into setting the left margin further to the right than the
right margin. Today, jsg@ found more of these with afl.
Change the internal interface between both levels, aiming for
simplicity and robustness of the code. Treat both margins as
*independent* settings: Now, termp.offset is the requested left
margin, and termp.rmargin is the available space. Let the lower
level cope with that case of insufficient space.
Obviously, high level code that does centering or flush right
still has to do careful checks, so i did a full audit of margin
settings in the terminal formatters.
Fixes crashes caused by excessively long title or date strings in
the man(7) footer, operating system or date strings in the mdoc(7)
footer, volume strings in the man(7) or mdoc(7) header, and a few
cases related to some non-prologue macros.
-rw-r--r-- | man_term.c | 30 | ||||
-rw-r--r-- | mdoc_term.c | 20 | ||||
-rw-r--r-- | term.c | 22 |
3 files changed, 33 insertions, 39 deletions
@@ -1,4 +1,4 @@ -/* $Id: man_term.c,v 1.155 2014/10/28 17:36:19 schwarze Exp $ */ +/* $Id: man_term.c,v 1.156 2014/11/21 01:52:53 schwarze Exp $ */ /* * Copyright (c) 2008-2012 Kristaps Dzonsons <kristaps@bsd.lv> * Copyright (c) 2010-2014 Ingo Schwarze <schwarze@openbsd.org> @@ -456,11 +456,6 @@ pre_in(DECL_ARGS) else p->offset = v; - /* Don't let this creep beyond the right margin. */ - - if (p->offset > p->rmargin) - p->offset = p->rmargin; - return(0); } @@ -654,8 +649,7 @@ pre_IP(DECL_ARGS) return(0); case MAN_BODY: p->offset = mt->offset + len; - p->rmargin = p->maxrmargin > p->offset ? - p->maxrmargin : p->offset; + p->rmargin = p->maxrmargin; break; default: break; @@ -746,8 +740,7 @@ pre_TP(DECL_ARGS) return(0); case MAN_BODY: p->offset = mt->offset + len; - p->rmargin = p->maxrmargin > p->offset ? - p->maxrmargin : p->offset; + p->rmargin = p->maxrmargin; p->trailspace = 0; p->flags &= ~TERMP_NOBREAK; break; @@ -898,8 +891,7 @@ pre_RS(DECL_ARGS) mt->offset += sz; p->offset = mt->offset; - p->rmargin = p->maxrmargin > p->offset ? - p->maxrmargin : p->offset; + p->rmargin = p->maxrmargin; if (++mt->lmarginsz < MAXMARGINS) mt->lmargincur = mt->lmarginsz; @@ -1063,7 +1055,7 @@ print_man_foot(struct termp *p, const void *arg) { const struct man_meta *meta; char *title; - size_t datelen; + size_t datelen, titlen; meta = (const struct man_meta *)arg; assert(meta->title); @@ -1100,7 +1092,8 @@ print_man_foot(struct termp *p, const void *arg) p->flags |= TERMP_NOSPACE | TERMP_NOBREAK; p->trailspace = 1; p->offset = 0; - p->rmargin = (p->maxrmargin - datelen + term_len(p, 1)) / 2; + p->rmargin = p->maxrmargin > datelen ? + (p->maxrmargin + term_len(p, 1) - datelen) / 2 : 0; if (meta->source) term_word(p, meta->source); @@ -1108,11 +1101,10 @@ print_man_foot(struct termp *p, const void *arg) /* At the bottom in the middle: manual date. */ - p->flags |= TERMP_NOSPACE; p->offset = p->rmargin; - p->rmargin = p->maxrmargin - term_strlen(p, title); - if (p->offset + datelen >= p->rmargin) - p->rmargin = p->offset + datelen; + titlen = term_strlen(p, title); + p->rmargin = p->maxrmargin > titlen ? p->maxrmargin - titlen : 0; + p->flags |= TERMP_NOSPACE; term_word(p, meta->date); term_flushln(p); @@ -1155,7 +1147,7 @@ print_man_head(struct termp *p, const void *arg) p->offset = 0; p->rmargin = 2 * (titlen+1) + vollen < p->maxrmargin ? (p->maxrmargin - vollen + term_len(p, 1)) / 2 : - p->maxrmargin - vollen; + vollen < p->maxrmargin ? p->maxrmargin - vollen : 0; term_word(p, title); term_flushln(p); diff --git a/mdoc_term.c b/mdoc_term.c index 9940c58b..8db43b97 100644 --- a/mdoc_term.c +++ b/mdoc_term.c @@ -1,4 +1,4 @@ -/* $Id: mdoc_term.c,v 1.291 2014/11/19 22:00:37 schwarze Exp $ */ +/* $Id: mdoc_term.c,v 1.292 2014/11/21 01:52:53 schwarze Exp $ */ /* * Copyright (c) 2008, 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv> * Copyright (c) 2010, 2012, 2013, 2014 Ingo Schwarze <schwarze@openbsd.org> @@ -405,6 +405,7 @@ static void print_mdoc_foot(struct termp *p, const void *arg) { const struct mdoc_meta *meta; + size_t sz; meta = (const struct mdoc_meta *)arg; @@ -421,8 +422,9 @@ print_mdoc_foot(struct termp *p, const void *arg) term_vspace(p); p->offset = 0; - p->rmargin = (p->maxrmargin - - term_strlen(p, meta->date) + term_len(p, 1)) / 2; + sz = term_strlen(p, meta->date); + p->rmargin = p->maxrmargin > sz ? + (p->maxrmargin + term_len(p, 1) - sz) / 2 : 0; p->trailspace = 1; p->flags |= TERMP_NOSPACE | TERMP_NOBREAK; @@ -430,7 +432,8 @@ print_mdoc_foot(struct termp *p, const void *arg) term_flushln(p); p->offset = p->rmargin; - p->rmargin = p->maxrmargin - term_strlen(p, meta->os); + sz = term_strlen(p, meta->os); + p->rmargin = p->maxrmargin > sz ? p->maxrmargin - sz : 0; p->flags |= TERMP_NOSPACE; term_word(p, meta->date); @@ -492,7 +495,7 @@ print_mdoc_head(struct termp *p, const void *arg) p->offset = 0; p->rmargin = 2 * (titlen+1) + vollen < p->maxrmargin ? (p->maxrmargin - vollen + term_len(p, 1)) / 2 : - p->maxrmargin - vollen; + vollen < p->maxrmargin ? p->maxrmargin - vollen : 0; term_word(p, title); term_flushln(p); @@ -873,11 +876,8 @@ termp_it_pre(DECL_ARGS) assert(width); if (MDOC_HEAD == n->type) p->rmargin = p->offset + width; - else { + else p->offset += width; - if (p->rmargin < p->offset) - p->rmargin = p->offset; - } break; case LIST_column: assert(width); @@ -1010,8 +1010,6 @@ termp_nm_pre(DECL_ARGS) MDOC_TEXT == n->prev->child->type ? term_strlen(p, n->prev->child->string) : term_len(p, 5)); - if (p->rmargin < p->offset) - p->rmargin = p->offset; return(1); } @@ -1,4 +1,4 @@ -/* $Id: term.c,v 1.235 2014/11/16 21:29:35 schwarze Exp $ */ +/* $Id: term.c,v 1.236 2014/11/21 01:52:53 schwarze Exp $ */ /* * Copyright (c) 2008, 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv> * Copyright (c) 2010-2014 Ingo Schwarze <schwarze@openbsd.org> @@ -100,7 +100,7 @@ term_flushln(struct termp *p) size_t j; /* temporary loop index for p->buf */ size_t jhy; /* last hyph before overflow w/r/t j */ size_t maxvis; /* output position of visible boundary */ - size_t mmax; /* used in calculating bp */ + size_t rmargin; /* the rightmost of the two margins */ /* * First, establish the maximum columns of "visible" content. @@ -113,13 +113,17 @@ term_flushln(struct termp *p) * is negative, it gets sign extended. Subtracting that * very large size_t effectively adds a small number to dv. */ - assert (p->rmargin >= p->offset); - dv = p->rmargin - p->offset; + rmargin = p->rmargin > p->offset ? p->rmargin : p->offset; + dv = p->rmargin - p->offset; maxvis = (int)dv > p->overstep ? dv - (size_t)p->overstep : 0; - dv = p->maxrmargin - p->offset; - mmax = (int)dv > p->overstep ? dv - (size_t)p->overstep : 0; - bp = TERMP_NOBREAK & p->flags ? mmax : maxvis; + if (p->flags & TERMP_NOBREAK) { + dv = p->maxrmargin > p->offset ? + p->maxrmargin - p->offset : 0; + bp = (int)dv > p->overstep ? + dv - (size_t)p->overstep : 0; + } else + bp = maxvis; /* * Calculate the required amount of padding. @@ -188,8 +192,8 @@ term_flushln(struct termp *p) (*p->endline)(p); p->viscol = 0; if (TERMP_BRIND & p->flags) { - vbl = p->rmargin; - vend += p->rmargin - p->offset; + vbl = rmargin; + vend += rmargin - p->offset; } else vbl = p->offset; |