From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from krisdoz.my.domain (schwarze@localhost [127.0.0.1]) by krisdoz.my.domain (8.14.5/8.14.5) with ESMTP id s7IGatax010087 for ; Mon, 18 Aug 2014 12:36:55 -0400 (EDT) Received: (from schwarze@localhost) by krisdoz.my.domain (8.14.5/8.14.3/Submit) id s7IGasuC015009; Mon, 18 Aug 2014 12:36:54 -0400 (EDT) Date: Mon, 18 Aug 2014 12:36:54 -0400 (EDT) Message-Id: <201408181636.s7IGasuC015009@krisdoz.my.domain> X-Mailinglist: mdocml-source Reply-To: source@mdocml.bsd.lv MIME-Version: 1.0 From: schwarze@mdocml.bsd.lv To: source@mdocml.bsd.lv Subject: mdocml: When the first child of the node being validated gets deleted X-Mailer: activitymail 1.26, http://search.cpan.org/dist/activitymail/ Content-Type: text/plain; charset=utf-8 Log Message: ----------- When the first child of the node being validated gets deleted during validation, man_node_unlink() switches to MAN_NEXT_CHILD. After that, we have to switch back to MAN_NEXT_SIBLING after completing validation, or subsequent parsing would add content into an already closed node, clobbering potentially existing children, causing information loss and a memory leak. Bug found by kristaps@ with valgrind in groff(7) on Mac OS X. Note that the switch back must be conditional, for if the node being validated itself gets deleted, we must *not* go to MAN_NEXT_SIBLING, which would not only yield wrong results in general but also crash in malformed manuals having an empty paragraph before the first .SH, for example OpenBSD c++filt(1). Modified Files: -------------- mdocml: man_macro.c Revision Data ------------- Index: man_macro.c =================================================================== RCS file: /usr/vhosts/mdocml.bsd.lv/cvs/mdocml/man_macro.c,v retrieving revision 1.88 retrieving revision 1.89 diff -Lman_macro.c -Lman_macro.c -u -p -r1.88 -r1.89 --- man_macro.c +++ man_macro.c @@ -100,7 +100,6 @@ man_unscope(struct man *man, const struc { struct man_node *n; - man->next = MAN_NEXT_SIBLING; to = to->parent; n = man->last; while (n != to) { @@ -139,11 +138,23 @@ man_unscope(struct man *man, const struc * Save a pointer to the parent such that * we know where to continue the iteration. */ + man->last = n; n = n->parent; if ( ! man_valid_post(man)) return(0); } + + /* + * If we ended up at the parent of the node we were + * supposed to rewind to, that means the target node + * got deleted, so add the next node we parse as a child + * of the parent instead of as a sibling of the target. + */ + + man->next = (man->last == to) ? + MAN_NEXT_CHILD : MAN_NEXT_SIBLING; + return(1); } -- To unsubscribe send an email to source+unsubscribe@mdocml.bsd.lv