gbranden pushed a commit to branch master
in repository groff.
commit 1e53037d5d3f934cf89081436f39f87ff2f2efad
Author: G. Branden Robinson <[email protected]>
AuthorDate: Mon Aug 19 14:11:56 2024 -0500
[troff]: Fix Savannah #63142 (newlines as delims).
Withdraw support for newlines as escape sequence delimiters. Only a few
(6) supported this, and the rationale behind it is unknown. DWB 3.3
troff didn't behave this way in any case.
* src/roff/troff/input.cpp (do_overstrike, do_bracket, do_name_test)
(do_zero_width_output, do_width, do_device_control): Do it. As a
bonus, check starting delimters for these escape sequences
(`\[obAZwX]`) for validity in general.
(do_overstrike, do_bracket, do_zero_width_output): When returning
early, delete the `new` node we just allocated to avoid leaking
memory.
(token:next): Be prepared for the `\b` and `\o` escape sequences
to return a null pointer (if the sequence doesn't even validly
get off the ground), as `\Z` and `\X` already do.
* src/roff/groff/tests/some_escapes_accept_newline_delimiters.sh:
Delete.
* src/roff/groff/groff.am (groff_TESTS): Drop test.
* doc/groff.texi.in (Delimiters):
* man/groff.7.man (Delimiters):
* NEWS: De-document support for newlines as delimiters.
Fixes <https://savannah.gnu.org/bugs/?63142>.
---
ChangeLog | 30 +++++
NEWS | 3 +
doc/groff.texi.in | 26 -----
man/groff.7.man | 17 ---
src/roff/groff/groff.am | 1 -
.../some_escapes_accept_newline_delimiters.sh | 124 ---------------------
src/roff/troff/input.cpp | 34 +++++-
7 files changed, 61 insertions(+), 174 deletions(-)
diff --git a/ChangeLog b/ChangeLog
index 8b46eaad4..28de0e25c 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,33 @@
+2024-08-19 G. Branden Robinson <[email protected]>
+
+ [troff]: Fix Savannah #63142 (newlines as delims).
+
+ Withdraw support for newlines as escape sequence delimiters.
+ Only a few (6) supported this, and the rationale behind it is
+ unknown. DWB 3.3 troff didn't behave this way in any case.
+
+ * src/roff/troff/input.cpp (do_overstrike, do_bracket)
+ (do_name_test, do_zero_width_output, do_width)
+ (do_device_control): Do it. As a bonus, check starting
+ delimters for these escape sequences (`\[obAZwX]`) for validity
+ in general.
+ (do_overstrike, do_bracket, do_zero_width_output): When
+ returning early, delete the `new` node we just allocated to
+ avoid leaking memory.
+ (token:next): Be prepared for the `\b` and `\o` escape sequences
+ to return a null pointer (if the sequence doesn't even validly
+ get off the ground), as `\Z` and `\X` already do.
+
+ * src/roff/groff/tests/\
+ some_escapes_accept_newline_delimiters.sh: Delete.
+ * src/roff/groff/groff.am (groff_TESTS): Drop test.
+
+ * doc/groff.texi.in (Delimiters):
+ * man/groff.7.man (Delimiters):
+ * NEWS: De-document support for newlines as delimiters.
+
+ Fixes <https://savannah.gnu.org/bugs/?63142>.
+
2024-08-19 G. Branden Robinson <[email protected]>
* src/roff/troff/input.cpp (token::is_usable_as_delimiter):
diff --git a/NEWS b/NEWS
index 1344eb4e6..0d0d96102 100644
--- a/NEWS
+++ b/NEWS
@@ -32,6 +32,9 @@ o GNU troff no longer accepts nonpositive page lengths.
Attempting to
motion quantum as `ll` does with the horizontal motion quantum in AT&T
and GNU troffs.
+o GNU troff no longer accepts a newline as a delimiter for the
+ parameterized escape sequences `\A`, `\b`, `\o`, `\w`, `\X`, and `\Z`.
+
o The `color`, `cp`, `linetabs`, and `vpt` requests now interpret
arguments with negative values as instructions to disable the
corresponding feature, using the *roff integer-to-Boolean conversion
diff --git a/doc/groff.texi.in b/doc/groff.texi.in
index 43d93f33d..a69ee55ef 100644
--- a/doc/groff.texi.in
+++ b/doc/groff.texi.in
@@ -7254,32 +7254,6 @@ as delimiters:
using them this way is discouraged; they can make the input confusing to
read.
-@cindex @code{\A}, delimiters allowed by
-@cindex @code{\b}, delimiters allowed by
-@cindex @code{\o}, delimiters allowed by
-@cindex @code{\w}, delimiters allowed by
-@cindex @code{\X}, delimiters allowed by
-@cindex @code{\Z}, delimiters allowed by
-@cindex newline, as delimiter
-A few escape sequences,
-@code{\A},
-@code{\b},
-@code{\o},
-@code{\w},
-@code{\X},
-and @code{\Z}, accept a newline as a delimiter. Newlines that serve
-as delimiters continue to be recognized as input line terminators.
-
-@Example
-A caf\o
-e\(aa
-in Paris
- @result{} A caf� in Paris
-@endExample
-
-@noindent
-Use of newlines as delimiters in escape sequences is also discouraged.
-
@cindex @code{\D}, delimiters allowed by
@cindex @code{\h}, delimiters allowed by
@cindex @code{\H}, delimiters allowed by
diff --git a/man/groff.7.man b/man/groff.7.man
index c36b89f1a..db6aafeec 100644
--- a/man/groff.7.man
+++ b/man/groff.7.man
@@ -1778,23 +1778,6 @@ using them this way is discouraged;
they can make the input confusing to read.
.
.
-.P
-A few escape sequences,
-.BR \[rs]A ,
-.BR \[rs]b ,
-.BR \[rs]o ,
-.BR \[rs]w ,
-.BR \[rs]X ,
-and
-.BR \[rs]Z ,
-accept a newline as a delimiter.
-.
-Newlines that serve as delimiters continue to be recognized as input
-line terminators.
-.
-Use of newlines as delimiters in escape sequences is also discouraged.
-.
-.
.br
.ne 2v
.P
diff --git a/src/roff/groff/groff.am b/src/roff/groff/groff.am
index f8aa46f88..ac472207d 100644
--- a/src/roff/groff/groff.am
+++ b/src/roff/groff/groff.am
@@ -83,7 +83,6 @@ groff_TESTS = \
src/roff/groff/tests/regression_savannah_59202.sh \
src/roff/groff/tests/set-stroke-thickness.sh \
src/roff/groff/tests/smoke-test_html_device.sh \
- src/roff/groff/tests/some_escapes_accept_newline_delimiters.sh \
src/roff/groff/tests/soquiet_works.sh \
src/roff/groff/tests/string_case_xform_errors.sh \
src/roff/groff/tests/string_case_xform_requests.sh \
diff --git a/src/roff/groff/tests/some_escapes_accept_newline_delimiters.sh
b/src/roff/groff/tests/some_escapes_accept_newline_delimiters.sh
deleted file mode 100755
index ccc0e826e..000000000
--- a/src/roff/groff/tests/some_escapes_accept_newline_delimiters.sh
+++ /dev/null
@@ -1,124 +0,0 @@
-#!/bin/sh
-#
-# Copyright (C) 2022-2024 Free Software Foundation, Inc.
-#
-# This file is part of groff.
-#
-# groff is free software; you can redistribute it and/or modify it under
-# the terms of the GNU General Public License as published by the Free
-# Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# groff is distributed in the hope that it will be useful, but WITHOUT
-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
-# for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program. If not, see <http://www.gnu.org/licenses/>.
-#
-
-groff="${abs_top_builddir:-.}/test-groff"
-
-fail=
-
-wail () {
- echo "...FAILED" >&2
- fail=yes
-}
-
-# Regression-test Savannah #63011.
-#
-# A handful of escape sequences bizarrely accept newlines as argument
-# delimiters. Don't throw diagnostics if they are used.
-
-input="\A
-ABC
-D
-.pl 1v>?\n(nlu"
-
-echo "checking that newline is accepted as delimiter to 'A' escape" >&2
-error=$(printf "%s\n" "$input" | "$groff" -Tascii -ww -z 2>&1)
-test -z "$error" || wail
-
-echo "checking correct handling of newline delimiter to 'A' escape" >&2
-output=$(printf "%s\n" "$input" | "$groff" -Tascii -ww)
-test "$output" = "1D" || wail
-
-input=".sp
-\b
-ABC
-D
-.pl 1v>?\n(nlu"
-
-echo "checking that newline is accepted as delimiter to 'b' escape" >&2
-error=$(printf "%s\n" "$input" | "$groff" -Tascii -ww -z 2>&1)
-test -z "$error" || wail
-
-echo "checking correct handling of newline delimiter to 'b' escape" >&2
-output=$(printf "%s\n" "$input" | "$groff" -Tascii -ww)
-echo "$output" | grep -Fqx "B D" || wail
-
-input="\o
-ABC
-D
-.pl 1v>?\n(nlu"
-
-echo "checking that newline is accepted as delimiter to 'o' escape" >&2
-error=$(printf "%s\n" "$input" | "$groff" -Tascii -ww -z 2>&1)
-test -z "$error" || wail
-
-echo "checking correct handling of newline delimiter to 'o' escape" >&2
-output=$(printf "%s\n" "$input" | "$groff" -Tascii -ww \
- | LC_ALL=C od -t c)
-# 7 spaces between C and D.
-printf "%s\n" "$output" \
- | grep -Eqx '0000000 +A +\\b +B +\\b +C D +\\n *' || wail
-
-input="\w
-ABC
-D
-.pl 1v>?\n(nlu"
-
-echo "checking that newline is accepted as delimiter to 'w' escape" >&2
-error=$(printf "%s\n" "$input" | "$groff" -Tascii -ww -z 2>&1)
-test -z "$error" || wail
-
-echo "checking correct handling of newline delimiter to 'w' escape" >&2
-output=$(printf "%s\n" "$input" | "$groff" -Tascii -ww)
-test "$output" = "72D" || wail
-
-input="\X
-tty: link http://example.com
-D
-.pl 1v>?\n(nlu"
-
-echo "checking that newline is accepted as delimiter to 'X' escape" >&2
-error=$(printf "%s\n" "$input" | "$groff" -Tascii -ww -z 2>&1)
-test -z "$error" || wail
-
-echo "checking correct handling of newline delimiter to 'X' escape" >&2
-output=$(printf "%s\n" "$input" | "$groff" -Tascii -ww -P -c)
-test "$output" = ' D' || wail
-
-input='.
-.ec @
-A@Z
-BCD
-E
-.pl 1v>?@n(nlu
-.'
-
-echo "checking that newline is accepted as delimiter to 'Z' escape" >&2
-error=$(printf "%s\n" "$input" | "$groff" -Tascii -ww -z 2>&1)
-test -z "$error" || wail
-
-echo "checking correct handling of newline delimiter to 'Z' escape" >&2
-output=$(printf "%s\n" "$input" | "$groff" -Tascii -ww \
- | LC_ALL=C od -t c)
-printf "%s\n" "$output" \
- | grep -Eqx '0000000 +A +B +\\b +E +C +D +\\n *' || wail
-
-test -z "$fail"
-
-# vim:set autoindent expandtab shiftwidth=2 tabstop=2 textwidth=72:
diff --git a/src/roff/troff/input.cpp b/src/roff/troff/input.cpp
index b9efd2a65..54425a0e3 100644
--- a/src/roff/troff/input.cpp
+++ b/src/roff/troff/input.cpp
@@ -1570,13 +1570,17 @@ node *do_overstrike() // \o
int start_level = input_stack::get_level();
token start_token;
start_token.next();
+ if (!start_token.is_usable_as_delimiter(true /* report error */)) {
+ delete osnode;
+ return 0 /* nullptr */;
+ }
for (;;) {
tok.next();
if (tok.is_newline()) {
input_stack::push(make_temp_iterator("\n"));
break;
}
- if (tok.is_eof()) {
+ if (tok.is_newline() || tok.is_eof()) {
// token::description() writes to static, class-wide storage, so
// we must allocate a copy of it before issuing the next
// diagnostic.
@@ -1617,13 +1621,17 @@ static node *do_bracket() // \b
int start_level = input_stack::get_level();
token start_token;
start_token.next();
+ if (!start_token.is_usable_as_delimiter(true /* report error */)) {
+ delete bracketnode;
+ return 0 /* nullptr */;
+ }
for (;;) {
tok.next();
if (tok.is_newline()) {
input_stack::push(make_temp_iterator("\n"));
break;
}
- if (tok.is_eof()) {
+ if (tok.is_newline() || tok.is_eof()) {
// token::description() writes to static, class-wide storage, so
// we must allocate a copy of it before issuing the next
// diagnostic.
@@ -1654,11 +1662,13 @@ static bool do_name_test() // \A
int start_level = input_stack::get_level();
token start_token;
start_token.next();
+ if (!start_token.is_usable_as_delimiter(true /* report error */))
+ return false;
bool got_bad_char = false;
bool got_some_char = false;
for (;;) {
tok.next();
- if (tok.is_eof()) {
+ if (tok.is_newline() || tok.is_eof()) {
// token::description() writes to static, class-wide storage, so
// we must allocate a copy of it before issuing the next
// diagnostic.
@@ -1762,9 +1772,13 @@ static node *do_zero_width_output() // \Z
int start_level = input_stack::get_level();
token start_token;
start_token.next();
+ if (!start_token.is_usable_as_delimiter(true /* report error */)) {
+ delete rev;
+ return 0 /* nullptr */;
+ }
for (;;) {
tok.next();
- if (tok.is_eof()) {
+ if (tok.is_newline() || tok.is_eof()) {
// token::description() writes to static, class-wide storage, so
// we must allocate a copy of it before issuing the next
// diagnostic.
@@ -2200,6 +2214,8 @@ void token::next()
return;
case 'b':
nd = do_bracket();
+ if (0 /* nullptr */ == nd)
+ break;
type = TOKEN_NODE;
return;
case 'B':
@@ -2344,6 +2360,8 @@ void token::next()
return;
case 'o':
nd = do_overstrike();
+ if (0 /* nullptr */ == nd)
+ break;
type = TOKEN_NODE;
return;
case 'O':
@@ -5502,12 +5520,14 @@ static void do_width() // \w
int start_level = input_stack::get_level();
token start_token;
start_token.next();
+ if (!start_token.is_usable_as_delimiter(true /* report error */))
+ return;
environment env(curenv);
environment *oldenv = curenv;
curenv = &env;
for (;;) {
tok.next();
- if (tok.is_eof()) {
+ if (tok.is_newline() || tok.is_eof()) {
// token::description() writes to static, class-wide storage, so
// we must allocate a copy of it before issuing the next
// diagnostic.
@@ -5726,6 +5746,8 @@ static node *do_device_control() // \X
int start_level = input_stack::get_level();
token start_token;
start_token.next();
+ if (!start_token.is_usable_as_delimiter(true /* report error */))
+ return 0 /* nullptr */;
macro mac;
for (;;) {
tok.next();
@@ -5733,7 +5755,7 @@ static node *do_device_control() // \X
input_stack::push(make_temp_iterator("\n"));
break;
}
- if (tok.is_eof()) {
+ if (tok.is_newline() || tok.is_eof()) {
// token::description() writes to static, class-wide storage, so
// we must allocate a copy of it before issuing the next
// diagnostic.
_______________________________________________
Groff-commit mailing list
[email protected]
https://lists.gnu.org/mailman/listinfo/groff-commit