diff options
author | Ingo Schwarze <schwarze@openbsd.org> | 2016-08-20 17:59:34 +0000 |
---|---|---|
committer | Ingo Schwarze <schwarze@openbsd.org> | 2016-08-20 17:59:34 +0000 |
commit | a47c2723999e135348912a7c9c9b2060866c3a44 (patch) | |
tree | ebe544c0ef33951478bb1b154a7d3f218edf3e74 | |
parent | fd0810563728ec789e1ffe4d07db646ce2543711 (diff) | |
download | mandoc-a47c2723999e135348912a7c9c9b2060866c3a44.tar.gz |
When a mismatching end macro occurs while at least two nested blocks
are open, all except the innermost open block got a bogus MDOC_ENDED
marker, in some situations triggering segfaults down the road
which tb@ found with afl(1).
Fix the logic error by figuring out up front whether an end macro
has a matching body, and if it hasn't, don't mark any blocks as broken.
-rw-r--r-- | mdoc_macro.c | 35 |
1 files changed, 22 insertions, 13 deletions
diff --git a/mdoc_macro.c b/mdoc_macro.c index ded91db4..d232b09e 100644 --- a/mdoc_macro.c +++ b/mdoc_macro.c @@ -1,7 +1,7 @@ /* $Id$ */ /* * Copyright (c) 2008-2012 Kristaps Dzonsons <kristaps@bsd.lv> - * Copyright (c) 2010, 2012-2015 Ingo Schwarze <schwarze@openbsd.org> + * Copyright (c) 2010, 2012-2016 Ingo Schwarze <schwarze@openbsd.org> * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -549,13 +549,24 @@ blk_exp_close(MACRO_PROT_ARGS) break; } + /* Search backwards for the beginning of our own body. */ + + atok = rew_alt(tok); + body = NULL; + for (n = mdoc->last; n; n = n->parent) { + if (n->flags & MDOC_ENDED || n->tok != atok || + n->type != ROFFT_BODY || n->end != ENDBODY_NOT) + continue; + body = n; + break; + } + /* * Search backwards for beginnings of blocks, * both of our own and of pending sub-blocks. */ - atok = rew_alt(tok); - body = endbody = itblk = later = NULL; + endbody = itblk = later = NULL; for (n = mdoc->last; n; n = n->parent) { if (n->flags & MDOC_ENDED) { if ( ! (n->flags & MDOC_VALID)) @@ -563,15 +574,15 @@ blk_exp_close(MACRO_PROT_ARGS) continue; } - /* Remember the start of our own body. */ - - if (n->type == ROFFT_BODY && atok == n->tok) { - if (n->end == ENDBODY_NOT) - body = n; - continue; - } + /* + * Mismatching end macros can never break anything, + * SYNOPSIS name blocks can never be broken, + * and we only care about the breaking of BLOCKs. + */ - if (n->type != ROFFT_BLOCK || n->tok == MDOC_Nm) + if (body == NULL || + n->tok == MDOC_Nm || + n->type != ROFFT_BLOCK) continue; if (n->tok == MDOC_It) { @@ -639,8 +650,6 @@ blk_exp_close(MACRO_PROT_ARGS) if (body == NULL) { mandoc_msg(MANDOCERR_BLK_NOTOPEN, mdoc->parse, line, ppos, mdoc_macronames[tok]); - if (later != NULL) - later->flags &= ~MDOC_BROKEN; if (maxargs && endbody == NULL) { /* * Stray .Ec without previous .Eo: |