source@mandoc.bsd.lv
 help / color / mirror / Atom feed
* mdocml: The code is already careful to not add items to lists that were
@ 2014-12-18  3:10 schwarze
  0 siblings, 0 replies; only message in thread
From: schwarze @ 2014-12-18  3:10 UTC (permalink / raw)
  To: source

Log Message:
-----------
The code is already careful to not add items to lists that were 
already closed.  In this respect, also consider lists closed
that have broken another block, their closure pending until the
end of the broken block.  This avoids syntax tree corruption
leading to a NULL pointer access found by jsg@ with afl.

Modified Files:
--------------
    mdocml:
        mdoc.h
        mdoc_macro.c

Revision Data
-------------
Index: mdoc_macro.c
===================================================================
RCS file: /home/cvs/mdocml/mdocml/mdoc_macro.c,v
retrieving revision 1.157
retrieving revision 1.158
diff -Lmdoc_macro.c -Lmdoc_macro.c -u -p -r1.157 -r1.158
--- mdoc_macro.c
+++ mdoc_macro.c
@@ -478,12 +478,16 @@ make_pending(struct mdoc_node *broken, e
 	for (breaker = broken->parent; breaker; breaker = breaker->parent) {
 
 		/*
-		 * If the *broken block had already been broken before
-		 * and we encounter its breaker, make the tok block
-		 * pending on the inner breaker.
-		 * Graphically, "[A breaker=[B broken=[C->B B] tok=A] C]"
-		 * becomes "[A broken=[B [C->B B] tok=A] C]"
-		 * and finally "[A [B->A [C->B B] A] C]".
+		 * If the *broken block (Z) is already broken and we
+		 * encounter its breaker (B), make the tok block (A)
+		 * pending on that inner breaker (B).
+		 * Graphically, [A breaker=[B! broken=[Z->B B] tok=A] Z]
+		 * becomes breaker=[A broken=[B! [Z->B B] tok=A] Z]
+		 * and finally [A! [B!->A [Z->B B] A] Z].
+		 * In these graphics, "->" indicates the "pending"
+		 * pointer and "!" indicates the MDOC_BREAK flag.
+		 * Each of the cases gets one additional pointer (B->A)
+		 * and one additional flag (A!).
 		 */
 		if (breaker == broken->pending) {
 			broken = breaker;
@@ -497,31 +501,38 @@ make_pending(struct mdoc_node *broken, e
 
 		/*
 		 * Found the breaker.
-		 * If another, outer breaker is already pending on
-		 * the *broken block, we must not clobber the link
+		 * If another, outer breaker (X) is already pending on
+		 * the *broken block (B), we must not clobber the link
 		 * to the outer breaker, but make it pending on the
-		 * new, now inner breaker.
-		 * Graphically, "[A breaker=[B broken=[C->A A] tok=B] C]"
-		 * becomes "[A breaker=[B->A broken=[C A] tok=B] C]"
-		 * and finally "[A [B->A [C->B A] B] C]".
+		 * new, now inner breaker (A).
+		 * Graphically, [X! breaker=[A broken=[B->X X] tok=A] B]
+		 * becomes [X! breaker=[A->X broken=[B X] tok=A] B]
+		 * and finally [X! [A!->X [B->A X] A] B].
 		 */
 		if (broken->pending) {
 			struct mdoc_node *taker;
 
 			/*
-			 * If the breaker had also been broken before,
-			 * it cannot take on the outer breaker itself,
-			 * but must hand it on to its own breakers.
-			 * Graphically, this is the following situation:
-			 * "[A [B breaker=[C->B B] broken=[D->A A] tok=C] D]"
-			 * "[A taker=[B->A breaker=[C->B B] [D->C A] C] D]"
+			 * If the inner breaker (A) is already broken,
+			 * too, it cannot take on the outer breaker (X)
+			 * but must hand it on to its own breakers (Y):
+			 * [X! [Y! breaker=[A->Y Y] broken=[B->X X] tok=A] B]
+			 * [X! take=[Y!->X brea=[A->Y Y] brok=[B X] tok=A] B]
+			 * and finally [X! [Y!->X [A!->Y Y] [B->A X] A] B].
 			 */
 			taker = breaker;
 			while (taker->pending)
 				taker = taker->pending;
 			taker->pending = broken->pending;
 		}
+
+		/*
+		 * Now we have reduced the situation to the simplest
+		 * case, which is just breaker=[A broken=[B tok=A] B]
+		 * and becomes [A! [B->A A] B].
+		 */
 		broken->pending = breaker;
+		breaker->flags |= MDOC_BREAK;
 		mandoc_vmsg(MANDOCERR_BLK_NEST, mdoc->parse, line, ppos,
 		    "%s breaks %s", mdoc_macronames[tok],
 		    mdoc_macronames[broken->tok]);
@@ -1067,8 +1078,8 @@ blk_full(MACRO_PROT_ARGS)
 
 	if (tok == MDOC_It) {
 		for (n = mdoc->last; n; n = n->parent)
-			if (n->tok == MDOC_Bl &&
-			    ! (n->flags & MDOC_VALID))
+			if (n->tok == MDOC_Bl && n->type == MDOC_BLOCK &&
+			    ! (n->flags & (MDOC_VALID | MDOC_BREAK)))
 				break;
 		if (n == NULL) {
 			mandoc_vmsg(MANDOCERR_IT_STRAY, mdoc->parse,
Index: mdoc.h
===================================================================
RCS file: /home/cvs/mdocml/mdocml/mdoc.h,v
retrieving revision 1.132
retrieving revision 1.133
diff -Lmdoc.h -Lmdoc.h -u -p -r1.132 -r1.133
--- mdoc.h
+++ mdoc.h
@@ -356,6 +356,7 @@ struct	mdoc_node {
 	enum mdoct	  tok; /* tok or MDOC__MAX if none */
 	int		  flags;
 #define	MDOC_VALID	 (1 << 0) /* has been validated */
+#define	MDOC_BREAK	 (1 << 1) /* has broken another block */
 #define	MDOC_EOS	 (1 << 2) /* at sentence boundary */
 #define	MDOC_LINE	 (1 << 3) /* first macro/text on line */
 #define	MDOC_SYNPRETTY	 (1 << 4) /* SYNOPSIS-style formatting */
--
 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-12-18  3:10 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2014-12-18  3:10 mdocml: The code is already careful to not add items to lists that were 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).