source@mandoc.bsd.lv
 help / color / mirror / Atom feed
* mdocml: We repeatedly observed assertion crashes in the low-level
@ 2014-11-21  1:52 schwarze
  0 siblings, 0 replies; only message in thread
From: schwarze @ 2014-11-21  1:52 UTC (permalink / raw)
  To: source

Log Message:
-----------
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.

Modified Files:
--------------
    mdocml:
        man_term.c
        mdoc_term.c
        term.c

Revision Data
-------------
Index: term.c
===================================================================
RCS file: /usr/vhosts/mdocml.bsd.lv/cvs/mdocml/term.c,v
retrieving revision 1.235
retrieving revision 1.236
diff -Lterm.c -Lterm.c -u -p -r1.235 -r1.236
--- term.c
+++ term.c
@@ -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;
 
Index: man_term.c
===================================================================
RCS file: /usr/vhosts/mdocml.bsd.lv/cvs/mdocml/man_term.c,v
retrieving revision 1.155
retrieving revision 1.156
diff -Lman_term.c -Lman_term.c -u -p -r1.155 -r1.156
--- man_term.c
+++ man_term.c
@@ -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 vo
 {
 	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 vo
 	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 vo
 
 	/* 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 vo
 	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);
Index: mdoc_term.c
===================================================================
RCS file: /usr/vhosts/mdocml.bsd.lv/cvs/mdocml/mdoc_term.c,v
retrieving revision 1.291
retrieving revision 1.292
diff -Lmdoc_term.c -Lmdoc_term.c -u -p -r1.291 -r1.292
--- mdoc_term.c
+++ mdoc_term.c
@@ -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 v
 	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 v
 	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 v
 	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);
 	}
 
--
 To unsubscribe send an email to source+unsubscribe@mdocml.bsd.lv

^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2014-11-21  1:52 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2014-11-21  1:52 mdocml: We repeatedly observed assertion crashes in the low-level schwarze

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).