]> git.ipfire.org Git - thirdparty/nftables.git/commitdiff
parser_bison: Fix for bison < 3.6 master
authorPhil Sutter <phil@nwl.cc>
Tue, 2 Jun 2026 15:15:48 +0000 (17:15 +0200)
committerPhil Sutter <phil@nwl.cc>
Thu, 23 Jul 2026 10:08:43 +0000 (12:08 +0200)
Support for 'custom' parse.error value was added in bison-3.6. Fall back
to previous value for earlier versions.

This is harder to get right than it seems: On one hand, preprocessor
macros can't be used in parser_bison.y's declaration section and
automake forbids conditional changes to AM_YFLAGS on the other.

Another aspect complicating things is compiling with (an up to date)
parser_bison.c in place vs. without: Dist tarballs generally have it in
place, relieving users from having to provide a YACC when compiling. The
existing parser_bison.c either uses parse.error=custom or not which does
not (should not) change when compiling. Hiding yyreport_syntax_error()
behind a CPPFLAG which may be set or not depending on bison presence and
version then causes trouble if it doesn't match how parser_bison.c was
created.

Avoid these pitfalls by:
- Not relying upon a preprocessor define to control parser_bison.c
  compilation, instead check existence of the bison-internal
  YY_LAC_ESTABLISH macro
- Exporting the above macro existence check in a variable for use by
  main.c (thereby crossing the libnftables library boundary)

Also:
- Introduce have_prebuilt_bison variable in configure.ac, unifying the
  parser_bison.c existence check and solidify the latter by also
  comparing its timestamp
- Report extended parser errors enableval in configure only if
  parser_bison.c will be recreated, otherwise we can't quite tell if it
  will turn out to be enabled or not

Suggested-by: Jan Kończak <jan.konczak@cs.put.poznan.pl>
Fixes: 67b822f2b2624 ("parser_bison: on syntax errors, output expected tokens")
Signed-off-by: Phil Sutter <phil@nwl.cc>
Makefile.am
configure.ac
include/nftables/libnftables.h
src/libnftables.map
src/main.c
src/parser_bison.y

index fa71e06eefee5098fcb82cde2ac83e5f5825da2e..5778dd29828e1d69703f92e75d9312afeaed1c02 100644 (file)
@@ -164,6 +164,11 @@ AM_CFLAGS = \
        $(NULL)
 
 AM_YFLAGS = -d -Wno-yacc
        $(NULL)
 
 AM_YFLAGS = -d -Wno-yacc
+if BISON_CUSTOM_ERROR
+YACC += -D parse.error=custom -D parse.lac=full
+else
+YACC += -D parse.error=verbose
+endif
 
 if BUILD_PROFILING
 AM_CFLAGS += --coverage
 
 if BUILD_PROFILING
 AM_CFLAGS += --coverage
index 0d3ee2ac89f699248596736fd4c995eec60330d5..d0eb7829bf604a4dac50b574cf9a7da173a3df28 100644 (file)
@@ -32,7 +32,11 @@ AC_PROG_SED
 AC_PROG_LEX([noyywrap])
 AC_PROG_YACC
 
 AC_PROG_LEX([noyywrap])
 AC_PROG_YACC
 
-if test -z "$ac_cv_prog_YACC" -a ! -f "${srcdir}/src/parser_bison.c"
+p_bison_pfx="${srcdir}/src/parser_bison"
+if test -f "${p_bison_pfx}.c" -a "${p_bison_pfx}.c" -nt "${p_bison_pfx}.y"
+then
+       have_prebuilt_bison="yes"
+elif test -z "$ac_cv_prog_YACC"
 then
         echo "*** Error: No suitable bison/yacc found. ***"
         echo "    Please install the 'bison' package."
 then
         echo "*** Error: No suitable bison/yacc found. ***"
         echo "    Please install the 'bison' package."
@@ -45,6 +49,18 @@ then
         exit 1
 fi
 
         exit 1
 fi
 
+AC_ARG_ENABLE([extended_parser_errors],
+             AS_HELP_STRING([--disable-extended-parser-errors],
+                            [Disable use of parse.error=custom and LAC in Bison]),
+             [], [
+                       enable_extended_parser_errors=no
+                       AC_SUBST([BISON], [$ac_cv_prog_YACC])
+                       AX_PROG_BISON_VERSION([3.6],
+                                             [enable_extended_parser_errors=yes])
+             ])
+AM_CONDITIONAL([BISON_CUSTOM_ERROR],
+              [test "x$enable_extended_parser_errors" != xno])
+
 AM_PROG_AR
 LT_INIT([disable-static])
 AC_EXEEXT
 AM_PROG_AR
 LT_INIT([disable-static])
 AC_EXEEXT
@@ -180,6 +196,10 @@ nft configuration:
   json output support:          ${with_json}
   collect profiling data:       ${enable_profiling}"
 
   json output support:          ${with_json}
   collect profiling data:       ${enable_profiling}"
 
+if test "x$have_prebuilt_bison" != "xyes"; then
+echo "  extended parser errors:       ${enable_extended_parser_errors}"
+fi
+
 if test "x$unitdir" != "x"; then
 AC_SUBST([unitdir])
 echo "  systemd unit:                 ${unitdir}"
 if test "x$unitdir" != "x"; then
 AC_SUBST([unitdir])
 echo "  systemd unit:                 ${unitdir}"
index c1d48d765a423f8ca5a48507e3353d9f8e3d1c5d..90b3f1b84a66f44b0943567ca059c8d621a859dc 100644 (file)
@@ -99,6 +99,8 @@ void nft_ctx_clear_vars(struct nft_ctx *ctx);
 int nft_run_cmd_from_buffer(struct nft_ctx *nft, const char *buf);
 int nft_run_cmd_from_filename(struct nft_ctx *nft, const char *filename);
 
 int nft_run_cmd_from_buffer(struct nft_ctx *nft, const char *buf);
 int nft_run_cmd_from_filename(struct nft_ctx *nft, const char *filename);
 
+extern bool nft_bison_have_extended_errors;
+
 #ifdef __cplusplus
 } /* extern "C" */
 #endif
 #ifdef __cplusplus
 } /* extern "C" */
 #endif
index 9369f44f3536745f529fb5ea1ecb4dd0098400a5..55c64f40e6a283ce64fe564122c2b022e2239a96 100644 (file)
@@ -38,3 +38,7 @@ LIBNFTABLES_4 {
   nft_ctx_input_get_flags;
   nft_ctx_input_set_flags;
 } LIBNFTABLES_3;
   nft_ctx_input_get_flags;
   nft_ctx_input_set_flags;
 } LIBNFTABLES_3;
+
+LIBNFTABLES_5 {
+  nft_bison_have_extended_errors;
+} LIBNFTABLES_4;
index 4cb51ff7f5fef70af0011d284027c16361128e59..976410b05fba8a72362a0550962a98297bfa2b96 100644 (file)
@@ -237,7 +237,7 @@ static void show_help(const char *name)
 
 static void show_version(void)
 {
 
 static void show_version(void)
 {
-       const char *cli, *minigmp, *json, *xt;
+       const char *cli, *minigmp, *json, *xt, *ext_bsn_err;
 
 #if defined(HAVE_LIBREADLINE)
        cli = "readline";
 
 #if defined(HAVE_LIBREADLINE)
        cli = "readline";
@@ -266,14 +266,16 @@ static void show_version(void)
 #else
        xt = "no";
 #endif
 #else
        xt = "no";
 #endif
+       ext_bsn_err = nft_bison_have_extended_errors ? "yes" : "no";
 
        printf("%s v%s (%s)\n"
 
        printf("%s v%s (%s)\n"
-              "  cli:          %s\n"
-              "  json:         %s\n"
-              "  minigmp:      %s\n"
-              "  libxtables:   %s\n",
+              "  cli:                          %s\n"
+              "  json:                         %s\n"
+              "  minigmp:                      %s\n"
+              "  libxtables:                   %s\n"
+              "  extended parser errors:       %s\n",
               PACKAGE_NAME, PACKAGE_VERSION, RELEASE_NAME,
               PACKAGE_NAME, PACKAGE_VERSION, RELEASE_NAME,
-              cli, json, minigmp, xt);
+              cli, json, minigmp, xt, ext_bsn_err);
 
 }
 
 
 }
 
index 5a334bf0c4997a80327867c2ac6b9c578b9ac056..800a4bda3760fc4c5e0b1613cadb20e6b78c54d8 100644 (file)
@@ -221,8 +221,6 @@ int nft_lex(void *, void *, void *);
 %parse-param           { void *scanner }
 %parse-param           { struct parser_state *state }
 %lex-param             { scanner }
 %parse-param           { void *scanner }
 %parse-param           { struct parser_state *state }
 %lex-param             { scanner }
-%define parse.error custom
-%define parse.lac full
 %locations
 
 %initial-action {
 %locations
 
 %initial-action {
@@ -6537,6 +6535,7 @@ exthdr_key                :       HBH     close_scope_hbh { $$ = IPPROTO_HOPOPTS; }
 
 %%
 
 
 %%
 
+#ifdef YY_LAC_ESTABLISH
 static int
 yyreport_syntax_error(const yypcontext_t *yyctx, struct nft_ctx *nft,
                       void *scanner, struct parser_state *state)
 static int
 yyreport_syntax_error(const yypcontext_t *yyctx, struct nft_ctx *nft,
                       void *scanner, struct parser_state *state)
@@ -6592,3 +6591,9 @@ yyreport_syntax_error(const yypcontext_t *yyctx, struct nft_ctx *nft,
        free(msg);
        return 0;
 }
        free(msg);
        return 0;
 }
+
+bool nft_bison_have_extended_errors = true;
+#else /* ! YY_LAC_ESTABLISH */
+bool nft_bison_have_extended_errors = false;
+#endif /* YY_LAC_ESTABLISH */
+EXPORT_SYMBOL(nft_bison_have_extended_errors);