]> git.cameronkatri.com Git - mandoc.git/commitdiff
Fix two issues causing a class of assertion failures found by jsg@ with afl.
authorIngo Schwarze <schwarze@openbsd.org>
Sat, 20 Dec 2014 02:26:57 +0000 (02:26 +0000)
committerIngo Schwarze <schwarze@openbsd.org>
Sat, 20 Dec 2014 02:26:57 +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.

mdoc_macro.c

index 6a9deaee8ae7f4c739c54192180c1823b1c5af45..92de591291ca76aece97b29a7064544ba873d950 100644 (file)
@@ -1,4 +1,4 @@
-/*     $Id: mdoc_macro.c,v 1.159 2014/12/18 20:58:32 schwarze Exp $ */
+/*     $Id: mdoc_macro.c,v 1.160 2014/12/20 02:26:57 schwarze Exp $ */
 /*
  * Copyright (c) 2008-2012 Kristaps Dzonsons <kristaps@bsd.lv>
  * Copyright (c) 2010, 2012, 2013, 2014 Ingo Schwarze <schwarze@openbsd.org>
@@ -550,13 +550,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 &&
@@ -571,6 +575,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:
@@ -713,7 +718,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;
@@ -737,6 +742,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) {
@@ -753,6 +759,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);
 
@@ -762,7 +774,8 @@ blk_exp_close(MACRO_PROT_ARGS)
                         * just proceed to closing out.
                         */
 
-                       if (later == NULL)
+                       if (later == NULL ||
+                           (tok == MDOC_El && !have_it))
                                break;
 
                        /*
@@ -801,10 +814,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);