warnings: don't complain about m4_foo and b4_foo when from the user

Currently, occurrences of these identifiers in the user's input yield
spurious warnings.

To tell the difference between a legitimate m4_foo from the user, and
a bad m4_foo coming from a non-evaluated macro of a skeleton, escape
the user's identifiers as m4@'_foo.  We already use @' as a special
sequence to be stripped from the skeleton's output.

See <https://lists.gnu.org/r/bug-bison/2021-10/msg00026.html> and
previous commit ("warnings: be less picky about occurrences of m4_/b4_
in the output").

* src/flex-scanner.h (OBSTACK_SGROW): New.
* src/output.c (output_escaped): Escape m4_ and b4_.
* src/scan-code.l: Likewise.
* src/system.h (obstack_escape): Likewise.
And rewrite as a function.
* tests/skeletons.at (Suspicious sequences): Make sure the user can
use m4_foo/b4_foo without spurious warnings.
This commit is contained in:
Akim Demaille
2021-11-07 09:27:52 +01:00
parent c95d0dd5f5
commit 6571c2d1b1
6 changed files with 94 additions and 25 deletions

3
NEWS
View File

@@ -2,6 +2,9 @@ GNU Bison NEWS
* Noteworthy changes in release ?.? (????-??-??) [?] * Noteworthy changes in release ?.? (????-??-??) [?]
Fixed portability issues of the test suite on Solaris.
Fixed spurious warnings about input containing `m4_` or `b4_`.
* Noteworthy changes in release 3.8.2 (2021-09-25) [stable] * Noteworthy changes in release 3.8.2 (2021-09-25) [stable]

View File

@@ -106,6 +106,9 @@ static struct obstack obstack_for_string;
# define STRING_GROW() \ # define STRING_GROW() \
obstack_grow (&obstack_for_string, yytext, yyleng) obstack_grow (&obstack_for_string, yytext, yyleng)
# define STRING_SGROW(String) \
obstack_sgrow (&obstack_for_string, String)
# define STRING_FINISH() \ # define STRING_FINISH() \
(last_string = obstack_finish0 (&obstack_for_string)) (last_string = obstack_finish0 (&obstack_for_string))

View File

@@ -104,20 +104,45 @@ GENERATE_MUSCLE_INSERT_TABLE (muscle_insert_symbol_number_table, symbol_number)
GENERATE_MUSCLE_INSERT_TABLE (muscle_insert_item_number_table, item_number) GENERATE_MUSCLE_INSERT_TABLE (muscle_insert_item_number_table, item_number)
GENERATE_MUSCLE_INSERT_TABLE (muscle_insert_state_number_table, state_number) GENERATE_MUSCLE_INSERT_TABLE (muscle_insert_state_number_table, state_number)
/*----------------------------------------------------------------. /*----------------------------------------------------------------.
| Print to OUT a representation of CP quoted and escaped for M4. | | Print to OUT a representation of CP quoted and escaped for M4. |
| |
| Keep sync'ed with obstack_escape. |
`----------------------------------------------------------------*/ `----------------------------------------------------------------*/
static void static void
output_escaped (FILE *out, const char *cp) output_escaped (FILE *out, const char *cp)
{ {
for (; *cp; cp++) for (; *cp; ++cp)
switch (*cp) switch (*cp)
{ {
case '$': fputs ("$][", out); break; case '$': fputs ("$][", out); break;
case '@': fputs ("@@", out); break; case '@': fputs ("@@", out); break;
case '[': fputs ("@{", out); break; case '[': fputs ("@{", out); break;
case ']': fputs ("@}", out); break; case ']': fputs ("@}", out); break;
case 'b':
if (STRPREFIX_LIT ("b4_", cp))
{
fputs ("b4@'_", out);
cp += strlen ("b4_") - 1;
break;
}
else
goto append;
case 'm':
if (STRPREFIX_LIT ("m4_", cp))
{
fputs ("m4@'_", out);
cp += strlen ("m4_") - 1;
break;
}
else
goto append;
append:
default: fputc (*cp, out); break; default: fputc (*cp, out); break;
} }
} }

View File

@@ -197,6 +197,9 @@ ref -?[0-9]+|{id}|"["{id}"]"|"$"
<*> <*>
{ {
"b4_" STRING_SGROW ("b4@'_");
"m4_" STRING_SGROW ("m4@'_");
/* Escape M4 quoting characters in C code. */ /* Escape M4 quoting characters in C code. */
[$@\[\]] obstack_escape (&obstack_for_string, yytext); [$@\[\]] obstack_escape (&obstack_for_string, yytext);

View File

@@ -204,24 +204,53 @@ max_int (int a, int b)
} while (0) } while (0)
/* Output Str escaped for our postprocessing (i.e., escape M4 special /* Output CP escaped for our postprocessing (i.e., escape M4 special
characters). characters).
For instance "[foo]" -> "@{foo@}", "$$" -> "$][$][". */ For instance "[foo]" -> "@{foo@}", "$$" -> "$][$][".
# define obstack_escape(Obs, Str) \ All the user's input passed to m4 is processed by this function or
do { \ by output_escaped, except user actions. Because of the specific
char const *p__; \ handling of @$, @1, etc., user actions are processed (and escaped)
for (p__ = Str; *p__; p__++) \ by scan-code.l.
switch (*p__) \
{ \ Keep output_escaped and obstack_escape sync'ed.
case '$': obstack_sgrow (Obs, "$]["); break; \ */
case '@': obstack_sgrow (Obs, "@@" ); break; \
case '[': obstack_sgrow (Obs, "@{" ); break; \ static inline void
case ']': obstack_sgrow (Obs, "@}" ); break; \ obstack_escape (struct obstack* obs, const char *cp)
default: obstack_1grow (Obs, *p__ ); break; \ {
} \ for (; *cp; ++cp)
} while (0) switch (*cp)
{
case '$': obstack_sgrow (obs, "$]["); break;
case '@': obstack_sgrow (obs, "@@" ); break;
case '[': obstack_sgrow (obs, "@{" ); break;
case ']': obstack_sgrow (obs, "@}" ); break;
case 'b':
if (STRPREFIX_LIT ("b4_", cp))
{
obstack_sgrow (obs, "b4@'_");
cp += strlen ("b4_") - 1;
break;
}
else
goto append;
case 'm':
if (STRPREFIX_LIT ("m4_", cp))
{
obstack_sgrow (obs, "m4@'_");
cp += strlen ("m4_") - 1;
break;
}
else
goto append;
append:
default: obstack_1grow (obs, *cp); break;
}
}
/* Output Str both quoted for M4 (i.e., embed in [[...]]), and escaped /* Output Str both quoted for M4 (i.e., embed in [[...]]), and escaped

View File

@@ -332,14 +332,18 @@ AT_CLEANUP
AT_SETUP([[Suspicious sequences]]) AT_SETUP([[Suspicious sequences]])
# <https://lists.gnu.org/r/bug-bison/2021-10/msg00026.html>.
# We must escape m4_foo as m4@&t@_foo to avoid Autotest's protection
# against its own suspicious sequences.
AT_DATA([[skel.c]], AT_DATA([[skel.c]],
[[m4@&t@_include(b4_skeletonsdir/[c.m4]) [[m4@&t@_include(b4_skeletonsdir/[c.m4])
m4@&t@_divert_push(0)d@&t@nl m4@&t@_divert_push(0)d@&t@nl
@output(b4_parser_file_name@)d@&t@nl @output(b4_parser_file_name@)d@&t@nl
]b4_user_pre_prologue[ ]b4_user_pre_prologue[
]b4_user_post_prologue[ ]b4_user_post_prologue[
b4_unevaluated b4_poison
m4@&t@_unevaluated m4@&t@_poison
]b4_epilogue[ ]b4_epilogue[
m4@&t@_divert_pop(0) m4@&t@_divert_pop(0)
@@ -348,19 +352,21 @@ m4@&t@_divert_pop(0)
AT_DATA([[input1.y]], AT_DATA([[input1.y]],
[[%skeleton "./skel.c" [[%skeleton "./skel.c"
%{ %{
myb4_unevaluated myb4_user
mym4_unevaluated mym4_user
b4_user
m4@&t@_user
%} %}
%% %%
start: ; b4_user: "b4_user";
%% %%
myb4_unevaluated b4_user
mym4_unevaluated m4@&t@_user
]]) ]])
AT_BISON_CHECK([[input1.y]], [], [], AT_BISON_CHECK([[input1.y]], [], [],
[[input1.tab.c:10: warning: suspicious sequence in the output: b4_unevaluated [-Wother] [[input1.tab.c:12: warning: suspicious sequence in the output: b4_poison [-Wother]
input1.tab.c:11: warning: suspicious sequence in the output: m4@&t@_unevaluated [-Wother] input1.tab.c:13: warning: suspicious sequence in the output: m4@&t@_poison [-Wother]
]]) ]])