Fix two issues causing a class of assertion failures found by jsg@ with afl.
authorschwarze <schwarze@openbsd.org>
Sat, 20 Dec 2014 02:26:42 +0000 (02:26 +0000)
committerschwarze <schwarze@openbsd.org>
Sat, 20 Dec 2014 02:26:42 +0000 (02:26 +0000)
1) rew_sub(): Make sure REWIND_MORE is acted upon even when followed by
REWIND_NONE.  This prevents .It from ending up inside other children of .Bl.
2) blk_exp_close(): Only allow extension of .Bl when it has at least
one .It.  Otherwise, a broken child block could be moved in front of
the .Bl, effectively resulting in a .Bl that ended before it began.

regress/usr.bin/mandoc/mdoc/Bl/Makefile
regress/usr.bin/mandoc/mdoc/Bl/breakingIt.in [new file with mode: 0644]
regress/usr.bin/mandoc/mdoc/Bl/breakingIt.out_ascii [new file with mode: 0644]
regress/usr.bin/mandoc/mdoc/Bl/breakingIt.out_lint [new file with mode: 0644]
usr.bin/mandoc/mdoc_macro.c

index 4e37f57..299bf82 100644 (file)
@@ -1,24 +1,25 @@
-# $OpenBSD: Makefile,v 1.26 2014/11/10 21:54:29 schwarze Exp $
+# $OpenBSD: Makefile,v 1.27 2014/12/20 02:26:42 schwarze Exp $
 
 REGRESS_TARGETS  = item inset diag ohang bullet dash enum hang tag
 REGRESS_TARGETS += column extend nested offset secstart
 
 REGRESS_TARGETS += notype multitype badargs
 REGRESS_TARGETS += empty noIt emptyhead emptytag emptyitem multitag
-REGRESS_TARGETS += bareIt bareTa unclosed break broken
+REGRESS_TARGETS += bareIt bareTa unclosed break breakingIt broken
 
 LINT_TARGETS    = column notype badargs
 LINT_TARGETS   += noIt emptyhead emptytag emptyitem
-LINT_TARGETS   += bareIt bareTa break broken
+LINT_TARGETS   += bareIt bareTa break breakingIt broken
 
-# groff-1.22.2 defects:
+# groff-1.22.3 defects:
 # - lists with missing or late type ruin indentation
 # - empty lists ruin indentation and sometimes cause empty lines
 # - breaking lists continue indefinitely
+# - breaking items sometimes ruin indentation, sometimes abort processing
 # - breaking a list aborts processing
 # - empty -tag item heads lose the blank line and the indentation
 
-SKIP_GROFF ?= notype empty break broken emptytag
+SKIP_GROFF ?= notype empty break breakingIt broken emptytag
 
 SKIP_TMAN ?= column multitype multitag bareTa break broken
 
diff --git a/regress/usr.bin/mandoc/mdoc/Bl/breakingIt.in b/regress/usr.bin/mandoc/mdoc/Bl/breakingIt.in
new file mode 100644 (file)
index 0000000..bcae378
--- /dev/null
@@ -0,0 +1,37 @@
+.Dd December 19, 2014
+.Dt BL-BREAKINGIT 1
+.Os OpenBSD
+.Sh NAME
+.Nm Bl-breakingIt
+.Nd items breaking other blocks
+.Sh DESCRIPTION
+.Ss Breaking partial explicit macros
+.Bl -tag -width Ds
+Stray text.
+.Ao
+More stray text.
+.It tag
+Tagged text.
+.El
+.Bl -bullet
+Stray text.
+.Ao
+More stray text.
+.It
+Bullet point.
+.El
+.Ss Breaking full explicit macros
+.Bl -tag -width Ds
+Stray text.
+.Bd -ragged -offset indent
+More stray text.
+.It tag
+Tagged text.
+.El
+.Bl -bullet
+Stray text.
+.Bd -ragged -offset indent
+More stray text.
+.It
+Bullet point.
+.El
diff --git a/regress/usr.bin/mandoc/mdoc/Bl/breakingIt.out_ascii b/regress/usr.bin/mandoc/mdoc/Bl/breakingIt.out_ascii
new file mode 100644 (file)
index 0000000..0013bba
--- /dev/null
@@ -0,0 +1,27 @@
+BL-BREAKINGIT(1)            General Commands Manual           BL-BREAKINGIT(1)
+
+N\bNA\bAM\bME\bE
+     B\bBl\bl-\b-b\bbr\bre\bea\bak\bki\bin\bng\bgI\bIt\bt - items breaking other blocks
+
+D\bDE\bES\bSC\bCR\bRI\bIP\bPT\bTI\bIO\bON\bN
+   B\bBr\bre\bea\bak\bki\bin\bng\bg p\bpa\bar\brt\bti\bia\bal\bl e\bex\bxp\bpl\bli\bic\bci\bit\bt m\bma\bac\bcr\bro\bos\bs
+     Stray text.  <More stray text.>
+
+     tag     Tagged text.
+     Stray text.  <More stray text.>
+
+     +\b+\bo\bo   Bullet point.
+
+   B\bBr\bre\bea\bak\bki\bin\bng\bg f\bfu\bul\bll\bl e\bex\bxp\bpl\bli\bic\bci\bit\bt m\bma\bac\bcr\bro\bos\bs
+     Stray text.
+
+           More stray text.
+
+     tag     Tagged text.
+     Stray text.
+
+           More stray text.
+
+     +\b+\bo\bo   Bullet point.
+
+OpenBSD                        December 19, 2014                       OpenBSD
diff --git a/regress/usr.bin/mandoc/mdoc/Bl/breakingIt.out_lint b/regress/usr.bin/mandoc/mdoc/Bl/breakingIt.out_lint
new file mode 100644 (file)
index 0000000..50b9dcb
--- /dev/null
@@ -0,0 +1,12 @@
+mandoc: breakingIt.in:13:2: ERROR: inserting missing end of block: It breaks Ao
+mandoc: breakingIt.in:10:1: WARNING: moving content out of list: text
+mandoc: breakingIt.in:11:2: WARNING: moving content out of list: Ao
+mandoc: breakingIt.in:20:2: ERROR: inserting missing end of block: It breaks Ao
+mandoc: breakingIt.in:17:1: WARNING: moving content out of list: text
+mandoc: breakingIt.in:18:2: WARNING: moving content out of list: Ao
+mandoc: breakingIt.in:28:2: ERROR: inserting missing end of block: It breaks Bd
+mandoc: breakingIt.in:25:1: WARNING: moving content out of list: text
+mandoc: breakingIt.in:26:2: WARNING: moving content out of list: Bd
+mandoc: breakingIt.in:35:2: ERROR: inserting missing end of block: It breaks Bd
+mandoc: breakingIt.in:32:1: WARNING: moving content out of list: text
+mandoc: breakingIt.in:33:2: WARNING: moving content out of list: Bd
index eb4fa30..14c686f 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: mdoc_macro.c,v 1.115 2014/12/18 20:58:00 schwarze Exp $ */
+/*     $OpenBSD: mdoc_macro.c,v 1.116 2014/12/20 02:26:42 schwarze Exp $ */
 /*
  * Copyright (c) 2008-2012 Kristaps Dzonsons <kristaps@bsd.lv>
  * Copyright (c) 2010, 2012, 2013, 2014 Ingo Schwarze <schwarze@openbsd.org>
@@ -548,13 +548,17 @@ static void
 rew_sub(enum mdoc_type t, struct mdoc *mdoc,
                enum mdoct tok, int line, int ppos)
 {
-       struct mdoc_node *n;
+       struct mdoc_node *n, *to;
 
+       to = NULL;
        n = mdoc->last;
        while (n) {
                switch (rew_dohalt(tok, t, n)) {
                case REWIND_NONE:
-                       return;
+                       if (to == NULL)
+                               return;
+                       n = to;
+                       break;
                case REWIND_THIS:
                        n->lastline = line -
                            (mdoc->flags & MDOC_NEWLINE &&
@@ -569,6 +573,7 @@ rew_sub(enum mdoc_type t, struct mdoc *mdoc,
                case REWIND_MORE:
                        n->lastline = line -
                            (mdoc->flags & MDOC_NEWLINE ? 1 : 0);
+                       to = n;
                        n = n->parent;
                        continue;
                case REWIND_LATER:
@@ -711,7 +716,7 @@ blk_exp_close(MACRO_PROT_ARGS)
        struct mdoc_node *later;        /* A sub-block starting later. */
        struct mdoc_node *n;            /* For searching backwards. */
 
-       int              j, lastarg, maxargs, flushed, nl;
+       int              flushed, have_it, j, lastarg, maxargs, nl;
        enum margserr    ac;
        enum mdoct       atok, ntok;
        char            *p;
@@ -735,6 +740,7 @@ blk_exp_close(MACRO_PROT_ARGS)
         * both of our own and of pending sub-blocks.
         */
 
+       have_it = 0;
        atok = rew_alt(tok);
        body = endbody = later = NULL;
        for (n = mdoc->last; n; n = n->parent) {
@@ -751,6 +757,12 @@ blk_exp_close(MACRO_PROT_ARGS)
 
                if (n->type != MDOC_BLOCK || n->tok == MDOC_Nm)
                        continue;
+
+               if (n->tok == MDOC_It) {
+                       have_it = 1;
+                       continue;
+               }
+
                if (atok == n->tok) {
                        assert(body);
 
@@ -760,7 +772,8 @@ blk_exp_close(MACRO_PROT_ARGS)
                         * just proceed to closing out.
                         */
 
-                       if (later == NULL)
+                       if (later == NULL ||
+                           (tok == MDOC_El && !have_it))
                                break;
 
                        /*
@@ -799,10 +812,8 @@ blk_exp_close(MACRO_PROT_ARGS)
                 * implicit ones, the first open implicit block.
                 */
 
-               if (later &&
-                   mdoc_macros[later->tok].flags & MDOC_EXPLICIT)
-                       continue;
-               if (n->tok != MDOC_It)
+               if (later == NULL ||
+                   ! (mdoc_macros[later->tok].flags & MDOC_EXPLICIT))
                        later = n;
        }
        rew_sub(MDOC_BODY, mdoc, tok, line, ppos);