The initial approach of keeping as much of lex/yacc-specific data local to the relevant parsing routines was flawed in that input descriptors which parsed commands' location information points at were freed after parsing (in scanner_destroy()) although they were required later for error reporting in case a command was rejected by the kernel. To overcome this, keep the scanner pointer in struct nft_ctx so that it can be kept in place until kernel communication has finished. Signed-off-by: Phil Sutter <phil@xxxxxx> --- include/nftables.h | 1 + src/libnftables.c | 43 +++++++++++++++++++++---------------------- 2 files changed, 22 insertions(+), 22 deletions(-) diff --git a/include/nftables.h b/include/nftables.h index f88d0530a963e..5e209b417d5a5 100644 --- a/include/nftables.h +++ b/include/nftables.h @@ -52,6 +52,7 @@ struct nft_ctx { struct nft_cache cache; uint32_t flags; struct parser_state *state; + void *scanner; }; enum nftables_exit_codes { diff --git a/src/libnftables.c b/src/libnftables.c index d9b2c0810988e..5bc7ba0d210ab 100644 --- a/src/libnftables.c +++ b/src/libnftables.c @@ -398,24 +398,20 @@ static int nft_parse_bison_buffer(struct nft_ctx *nft, char *buf, size_t buflen, struct list_head *msgs, struct list_head *cmds) { struct cmd *cmd; - void *scanner; int ret; parser_init(nft, nft->state, msgs, cmds); - scanner = scanner_init(nft->state); - scanner_push_buffer(scanner, &indesc_cmdline, buf); + nft->scanner = scanner_init(nft->state); + scanner_push_buffer(nft->scanner, &indesc_cmdline, buf); + + ret = nft_parse(nft, nft->scanner, nft->state); + if (ret != 0 || nft->state->nerrs > 0) + return -1; - ret = nft_parse(nft, scanner, nft->state); - if (ret != 0 || nft->state->nerrs > 0) { - ret = -1; - goto err; - } list_for_each_entry(cmd, cmds, list) nft_cmd_expand(cmd); -err: - scanner_destroy(scanner); - return ret; + return 0; } static int nft_parse_bison_filename(struct nft_ctx *nft, const char *filename, @@ -427,22 +423,17 @@ static int nft_parse_bison_filename(struct nft_ctx *nft, const char *filename, parser_init(nft, nft->state, msgs, cmds); scanner = scanner_init(nft->state); - if (scanner_read_file(scanner, filename, &internal_location) < 0) { - ret = -1; - goto err; - } + if (scanner_read_file(scanner, filename, &internal_location) < 0) + return -1; ret = nft_parse(nft, scanner, nft->state); - if (ret != 0 || nft->state->nerrs > 0) { - ret = -1; - goto err; - } + if (ret != 0 || nft->state->nerrs > 0) + return -1; + list_for_each_entry(cmd, cmds, list) nft_cmd_expand(cmd); -err: - scanner_destroy(scanner); - return ret; + return 0; } int nft_run_cmd_from_buffer(struct nft_ctx *nft, char *buf, size_t buflen) @@ -474,6 +465,10 @@ err: } erec_print_list(&nft->output, &msgs, nft->debug_mask); iface_cache_release(); + if (nft->scanner) { + scanner_destroy(nft->scanner); + nft->scanner = NULL; + } free(nlbuf); return rc; @@ -511,6 +506,10 @@ err: } erec_print_list(&nft->output, &msgs, nft->debug_mask); iface_cache_release(); + if (nft->scanner) { + scanner_destroy(nft->scanner); + nft->scanner = NULL; + } return rc; } -- 2.17.0 -- To unsubscribe from this list: send the line "unsubscribe netfilter-devel" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html