diff options
author | Ingo Schwarze <schwarze@openbsd.org> | 2014-12-20 02:26:57 +0000 |
---|---|---|
committer | Ingo Schwarze <schwarze@openbsd.org> | 2014-12-20 02:26:57 +0000 |
commit | c3d62d28a2dc71f5ab706428016e254508dd7d10 (patch) | |
tree | 8aedf5481adb64488e20b4317e5c9587380da9e4 /mdoc_macro.c | |
parent | d5da66336e312513b51e1424af9b9d2de63bc594 (diff) | |
download | mandoc-c3d62d28a2dc71f5ab706428016e254508dd7d10.tar.gz |
Fix two issues causing a class of assertion failures found by jsg@ with afl.
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.
Diffstat (limited to 'mdoc_macro.c')
-rw-r--r-- | mdoc_macro.c | 27 |
1 files changed, 19 insertions, 8 deletions
diff --git a/mdoc_macro.c b/mdoc_macro.c index 0906e939..4ab58182 100644 --- a/mdoc_macro.c +++ b/mdoc_macro.c @@ -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); |