aboutsummaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
authorIngo Schwarze <schwarze@openbsd.org>2014-11-21 01:52:53 +0000
committerIngo Schwarze <schwarze@openbsd.org>2014-11-21 01:52:53 +0000
commit6242a9efa48427465988912bdb7e56c75b239acf (patch)
tree0ddf5283f0848a0c7880a54f9e8c00f1519a5a91
parentb300a4ff9ca15ee75ac8b05afd9d5817390384ae (diff)
downloadmandoc-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.c30
-rw-r--r--mdoc_term.c20
-rw-r--r--term.c22
3 files changed, 33 insertions, 39 deletions
diff --git a/man_term.c b/man_term.c
index 790d3135..2531f816 100644
--- a/man_term.c
+++ b/man_term.c
@@ -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);
}
diff --git a/term.c b/term.c
index 085d254b..5b01aa68 100644
--- a/term.c
+++ b/term.c
@@ -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;