diff options
author | Ingo Schwarze <schwarze@openbsd.org> | 2017-02-10 16:20:34 +0000 |
---|---|---|
committer | Ingo Schwarze <schwarze@openbsd.org> | 2017-02-10 16:20:34 +0000 |
commit | 129204d2b6e8eb95a79408a2653069d26ec852d7 (patch) | |
tree | d9186b8e7011c50d4fb39c5095211049de7aad18 /mdoc_macro.c | |
parent | a4aa2b1f59e2f2354dd17be89ef5ebc595a4bfc0 (diff) | |
download | mandoc-129204d2b6e8eb95a79408a2653069d26ec852d7.tar.gz mandoc-129204d2b6e8eb95a79408a2653069d26ec852d7.tar.zst mandoc-129204d2b6e8eb95a79408a2653069d26ec852d7.zip |
In the SYNOPSIS, .Nm blocks can get broken if one of their children
gets broken. In that case, mark them as BROKEN and ENDED and make
sure they get closed out together with the child.
Fixes tree corruption leeding to a NULL dereference found by tb@
with afl(1) in: .Sh SYNOPSIS .Bl .Oo .Nm .Bk .Oc .It (where .Bk is
the child and .Oo is the breaker).
A simpler form of the same corruption (without crash) is visible in:
.Sh SYNOPSIS .Ao .Nm .Bo .Ac .Bc text
where the text ended up inside the .Nm (child .Bo, breaker .Ao).
Diffstat (limited to 'mdoc_macro.c')
-rw-r--r-- | mdoc_macro.c | 22 |
1 files changed, 15 insertions, 7 deletions
diff --git a/mdoc_macro.c b/mdoc_macro.c index d4edcea1..aa3f4cde 100644 --- a/mdoc_macro.c +++ b/mdoc_macro.c @@ -1,4 +1,4 @@ -/* $Id: mdoc_macro.c,v 1.210 2017/01/10 13:47:00 schwarze Exp $ */ +/* $Id: mdoc_macro.c,v 1.211 2017/02/10 16:20:34 schwarze Exp $ */ /* * Copyright (c) 2008-2012 Kristaps Dzonsons <kristaps@bsd.lv> * Copyright (c) 2010, 2012-2016 Ingo Schwarze <schwarze@openbsd.org> @@ -575,16 +575,24 @@ blk_exp_close(MACRO_PROT_ARGS) } /* - * Mismatching end macros can never break anything, - * SYNOPSIS name blocks can never be broken, + * Mismatching end macros can never break anything * and we only care about the breaking of BLOCKs. */ - if (body == NULL || - n->tok == MDOC_Nm || - n->type != ROFFT_BLOCK) + if (body == NULL || n->type != ROFFT_BLOCK) continue; + /* + * SYNOPSIS name blocks can not be broken themselves, + * but they do get broken together with a broken child. + */ + + if (n->tok == MDOC_Nm) { + if (later != NULL) + n->flags |= NODE_BROKEN | NODE_ENDED; + continue; + } + if (n->tok == MDOC_It) { itblk = n; continue; @@ -987,7 +995,7 @@ blk_full(MACRO_PROT_ARGS) /* Close out prior implicit scopes. */ - rew_last(mdoc, n); + rew_pending(mdoc, n); } /* Skip items outside lists. */ |