From: schwarze Date: Thu, 28 Apr 2022 10:17:37 +0000 (+0000) Subject: Element next-line scopes may nest, so man_breakscope() may have to X-Git-Url: http://artulab.com/gitweb/?a=commitdiff_plain;h=cfaf94d5064fa049c2bfa296896bce4800cc9600;p=openbsd Element next-line scopes may nest, so man_breakscope() may have to break multiple element next-line scopes at the same time, similar to what man_descope() already does for unconditional rewinding. This fixes an assertion failure that tb@ found with afl(1), caused by .SH .I .I .BI and similar sequences of macros without arguments. --- diff --git a/regress/usr.bin/mandoc/man/B/Makefile b/regress/usr.bin/mandoc/man/B/Makefile index ac010e1ba62..a3ac6257dd4 100644 --- a/regress/usr.bin/mandoc/man/B/Makefile +++ b/regress/usr.bin/mandoc/man/B/Makefile @@ -1,7 +1,7 @@ -# $OpenBSD: Makefile,v 1.2 2017/06/03 15:54:09 schwarze Exp $ +# $OpenBSD: Makefile,v 1.3 2022/04/28 10:17:38 schwarze Exp $ -REGRESS_TARGETS = args blank -LINT_TARGETS = args blank +REGRESS_TARGETS = args blank nest +LINT_TARGETS = args blank nest # groff-1.22.3 defect: # - A blank line in next line scope causes a blank line. diff --git a/regress/usr.bin/mandoc/man/B/nest.in b/regress/usr.bin/mandoc/man/B/nest.in new file mode 100644 index 00000000000..3edf2077394 --- /dev/null +++ b/regress/usr.bin/mandoc/man/B/nest.in @@ -0,0 +1,20 @@ +.\" $OpenBSD: nest.in,v 1.1 2022/04/28 10:17:38 schwarze Exp $ +.TH B-ARGS 1 "April 28, 2022" +.SH NAME +B-nest \- nested next-line scopes +.SH DESCRIPTION +initial text +.B +.SM +bold text +back to roman +.B +.SM +.IR italic roman +.B +.SM +.SH +.B +.B +.RI section header +final text diff --git a/regress/usr.bin/mandoc/man/B/nest.out_ascii b/regress/usr.bin/mandoc/man/B/nest.out_ascii new file mode 100644 index 00000000000..82ae6a7201b --- /dev/null +++ b/regress/usr.bin/mandoc/man/B/nest.out_ascii @@ -0,0 +1,12 @@ +B-ARGS(1) General Commands Manual B-ARGS(1) + +NNAAMMEE + B-nest - nested next-line scopes + +DDEESSCCRRIIPPTTIIOONN + initial text bboolldd tteexxtt back to roman _i_t_a_l_i_croman + +section_h_e_a_d_e_r + final text + +OpenBSD April 28, 2022 B-ARGS(1) diff --git a/regress/usr.bin/mandoc/man/B/nest.out_lint b/regress/usr.bin/mandoc/man/B/nest.out_lint new file mode 100644 index 00000000000..dd6ba7bd78b --- /dev/null +++ b/regress/usr.bin/mandoc/man/B/nest.out_lint @@ -0,0 +1,6 @@ +mandoc: nest.in:12:2: WARNING: line scope broken: IR breaks SM +mandoc: nest.in:11:2: WARNING: line scope broken: IR breaks B +mandoc: nest.in:15:2: WARNING: line scope broken: SH breaks SM +mandoc: nest.in:14:2: WARNING: line scope broken: SH breaks B +mandoc: nest.in:18:2: WARNING: line scope broken: RI breaks B +mandoc: nest.in:17:2: WARNING: line scope broken: RI breaks B diff --git a/usr.bin/mandoc/man.c b/usr.bin/mandoc/man.c index 934f2b36796..0a522b6dbf3 100644 --- a/usr.bin/mandoc/man.c +++ b/usr.bin/mandoc/man.c @@ -1,7 +1,7 @@ -/* $OpenBSD: man.c,v 1.135 2019/01/05 00:36:46 schwarze Exp $ */ +/* $OpenBSD: man.c,v 1.136 2022/04/28 10:17:37 schwarze Exp $ */ /* + * Copyright (c) 2013-2015,2017-2019,2022 Ingo Schwarze * Copyright (c) 2008, 2009, 2010, 2011 Kristaps Dzonsons - * Copyright (c) 2013-2015, 2017-2019 Ingo Schwarze * Copyright (c) 2011 Joerg Sonnenberger * * Permission to use, copy, modify, and distribute this software for any @@ -68,6 +68,9 @@ man_hasc(char *start) return (ep - cp) % 2 ? NULL : ep; } +/* + * Rewind all open next-line scopes. + */ void man_descope(struct roff_man *man, int line, int offs, char *start) { @@ -272,6 +275,10 @@ man_pmacro(struct roff_man *man, int ln, char *buf, int offs) return 1; } +/* + * Rewind open next-line scopes + * unless the tok request or macro is allowed inside them. + */ void man_breakscope(struct roff_man *man, int tok) { @@ -292,10 +299,15 @@ man_breakscope(struct roff_man *man, int tok) (man_macro(n->tok)->flags & (MAN_NSCOPED | MAN_ESCOPED)) == MAN_NSCOPED) n = n->parent; - - mandoc_msg(MANDOCERR_BLK_LINE, n->line, n->pos, - "%s breaks %s", roff_name[tok], roff_name[n->tok]); - + for (;;) { + mandoc_msg(MANDOCERR_BLK_LINE, n->line, n->pos, + "%s breaks %s", roff_name[tok], roff_name[n->tok]); + if (n->parent->type != ROFFT_ELEM || + (man_macro(n->parent->tok)->flags & + MAN_ESCOPED) == 0) + break; + n = n->parent; + } roff_node_delete(man, n); man->flags &= ~MAN_ELINE; }