summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorIngo Schwarze <schwarze@openbsd.org>2017-02-11 13:24:12 +0000
committerIngo Schwarze <schwarze@openbsd.org>2017-02-11 13:24:12 +0000
commit26e005b2a5827b112b2ff97f47feb025eaaf6b3e (patch)
tree39849241acc82f791ff872955bf76d0629f223b5
parentd315ab0f3840004d8ba2b2477aa3127454b46746 (diff)
downloadmandoc-26e005b2a5827b112b2ff97f47feb025eaaf6b3e.tar.gz
Do not prematurely mark intermediate blocks as broken while scanning
backwards. Only do so when a block is found that is actually broken. Logic error found while investigating crashes reported by tb@.
-rw-r--r--mdoc_macro.c25
1 files changed, 16 insertions, 9 deletions
diff --git a/mdoc_macro.c b/mdoc_macro.c
index 2b5cb419..570e5698 100644
--- a/mdoc_macro.c
+++ b/mdoc_macro.c
@@ -50,6 +50,8 @@ static int find_pending(struct roff_man *, int, int, int,
struct roff_node *);
static int lookup(struct roff_man *, int, int, int, const char *);
static int macro_or_word(MACRO_PROT_ARGS, int);
+static void break_intermediate(struct roff_node *,
+ struct roff_node *);
static int parse_rest(struct roff_man *, int, int, int *, char *);
static int rew_alt(int);
static void rew_elem(struct roff_man *, int);
@@ -376,6 +378,16 @@ rew_elem(struct roff_man *mdoc, int tok)
rew_last(mdoc, n);
}
+static void
+break_intermediate(struct roff_node *n, struct roff_node *breaker)
+{
+ while (n != breaker) {
+ if ( ! (n->flags & NODE_VALID))
+ n->flags |= NODE_BROKEN;
+ n = n->parent;
+ }
+}
+
/*
* If there is an open sub-block of the target requiring
* explicit close-out, postpone closing out the target until
@@ -390,14 +402,12 @@ find_pending(struct roff_man *mdoc, int tok, int line, int ppos,
irc = 0;
for (n = mdoc->last; n != NULL && n != target; n = n->parent) {
- if (n->flags & NODE_ENDED) {
- if ( ! (n->flags & NODE_VALID))
- n->flags |= NODE_BROKEN;
+ if (n->flags & NODE_ENDED)
continue;
- }
if (n->type == ROFFT_BLOCK &&
mdoc_macros[n->tok].flags & MDOC_EXPLICIT) {
irc = 1;
+ break_intermediate(mdoc->last, n);
n->flags |= NODE_BROKEN;
if (target->type == ROFFT_HEAD)
target->flags |= NODE_ENDED;
@@ -568,11 +578,8 @@ blk_exp_close(MACRO_PROT_ARGS)
endbody = itblk = later = NULL;
for (n = mdoc->last; n; n = n->parent) {
- if (n->flags & NODE_ENDED) {
- if ( ! (n->flags & NODE_VALID))
- n->flags |= NODE_BROKEN;
+ if (n->flags & NODE_ENDED)
continue;
- }
/*
* Mismatching end macros can never break anything
@@ -599,7 +606,6 @@ blk_exp_close(MACRO_PROT_ARGS)
}
if (atok == n->tok) {
- assert(body);
/*
* Found the start of our own block.
@@ -650,6 +656,7 @@ blk_exp_close(MACRO_PROT_ARGS)
/* Breaking an open sub block. */
+ break_intermediate(mdoc->last, body);
n->flags |= NODE_BROKEN;
if (later == NULL)
later = n;