diff options
author | Ingo Schwarze <schwarze@openbsd.org> | 2010-06-30 04:05:02 +0000 |
---|---|---|
committer | Ingo Schwarze <schwarze@openbsd.org> | 2010-06-30 04:05:02 +0000 |
commit | 25b3bcbde4cab98bd4a3175d20053187201d2dce (patch) | |
tree | 87ee4f656dcc58da214d2b0190916785fae6b479 | |
parent | 72452c8d8f8859768d309309a7ebca1cb366e063 (diff) | |
download | mandoc-25b3bcbde4cab98bd4a3175d20053187201d2dce.tar.gz |
Closing of full blocks (Bd Bf Bk Bl It Fo Nd Rs Sh Ss) may never be
delayed: It must either succeed right away or fail outright.
As noticed by Kristaps, neglecting to fail properly when required
could make invalid input screw up the syntax tree and ultimately
trigger assertions in other, unrelated parts of the program.
This fix tested by and OK by kristaps@.
While here, comment the rather tricky function rew_dohalt().
This function will probably need more tweaks later on.
-rw-r--r-- | mdoc_macro.c | 45 |
1 files changed, 42 insertions, 3 deletions
diff --git a/mdoc_macro.c b/mdoc_macro.c index f292affc..10baaec7 100644 --- a/mdoc_macro.c +++ b/mdoc_macro.c @@ -335,21 +335,44 @@ rew_dohalt(enum mdoct tok, enum mdoc_type type, const struct mdoc_node *p) { + /* + * No matching token, no delimiting block, no broken block. + * This can happen when full implicit macros are called for + * the first time but try to rewind their previous + * instance anyway. + */ if (MDOC_ROOT == p->type) return(MDOC_BLOCK == type && MDOC_EXPLICIT & mdoc_macros[tok].flags ? REWIND_ERROR : REWIND_NONE); + + /* + * When starting to rewind, skip plain text + * and nodes that have already been rewound. + */ if (MDOC_TEXT == p->type || MDOC_VALID & p->flags) return(REWIND_MORE); + /* + * The easiest case: Found a matching token. + * This applies to both blocks and elements. + */ tok = rew_alt(tok); if (tok == p->tok) return(p->end ? REWIND_NONE : type == p->type ? REWIND_THIS : REWIND_MORE); + /* + * While elements do require rewinding for themselves, + * they never affect rewinding of other nodes. + */ if (MDOC_ELEM == p->type) return(REWIND_MORE); + /* + * Blocks delimited by our target token get REWIND_MORE. + * Blocks delimiting our target token get REWIND_NONE. + */ switch (tok) { case (MDOC_Bl): if (MDOC_It == p->tok) @@ -384,9 +407,25 @@ rew_dohalt(enum mdoct tok, enum mdoc_type type, break; } - return(p->end || (MDOC_BLOCK == p->type && - ! (MDOC_EXPLICIT & mdoc_macros[tok].flags)) ? - REWIND_MORE : REWIND_LATER); + /* + * Default block rewinding rules. + * In particular, always skip block end markers. + */ + if (p->end || (MDOC_BLOCK == p->type && + ! (MDOC_EXPLICIT & mdoc_macros[tok].flags))) + return(REWIND_MORE); + + /* + * Partial blocks allow delayed rewinding by default. + */ + if (&blk_full != mdoc_macros[tok].fp) + return (REWIND_LATER); + + /* + * Full blocks can only be rewound when matching + * or when there is an explicit rule. + */ + return(REWIND_ERROR); } |