source@mandoc.bsd.lv
 help / color / mirror / Atom feed
From: schwarze@mdocml.bsd.lv
To: source@mdocml.bsd.lv
Subject: mdocml: The code is already careful to not add items to lists that were
Date: Wed, 17 Dec 2014 22:10:12 -0500 (EST)	[thread overview]
Message-ID: <5993863352338521604.enqueue@fantadrom.bsd.lv> (raw)

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

                 reply	other threads:[~2014-12-18  3:10 UTC|newest]

Thread overview: [no followups] expand[flat|nested]  mbox.gz  Atom feed

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=5993863352338521604.enqueue@fantadrom.bsd.lv \
    --to=schwarze@mdocml.bsd.lv \
    --cc=source@mdocml.bsd.lv \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
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).