On Thu, Jul 24, 2025 at 12:22:02PM +0200, Florian Westphal wrote: > chain_stmt_destroy is called from bison destructor, but it turns out > this function won't free the associated chain. > > There is no memory leak when bison can parse the input because the chain > statement evaluation step queues the embedded anon chain via cmd_alloc. > Then, a later cmd_free() releases the chain and the embedded statements. > > In case of a parser error, the evaluation step is never reached and the > chain object leaks, e.g. in > > foo bar jump { return } > > Bison calls the right destructor but the anonon chain and all > statements/expressions in it are not released: > > HEAP SUMMARY: > in use at exit: 1,136 bytes in 4 blocks > total heap usage: 98 allocs, 94 frees, 840,255 bytes allocated > > 1,136 (568 direct, 568 indirect) bytes in 1 blocks are definitely lost in loss record 4 of 4 > at: calloc (vg_replace_malloc.c:1675) > by: xzalloc (in libnftables.so.1.1.0) > by: chain_alloc (in libnftables.so.1.1.0) > by: nft_parse (in libnftables.so.1.1.0) > by: __nft_run_cmd_from_filename (in libnftables.so.1.1.0) > by: nft_run_cmd_from_filename (in libnftables.so.1.1.0) > > To resolve this, make chain_stmt_destroy also release the embedded > chain. This in turn requires chain refcount increases whenever a chain > is assocated with a chain statement, else we get double-free of the > chain. > > Signed-off-by: Florian Westphal <fw@xxxxxxxxx> Reviewed-by: Pablo Neira Ayuso <pablo@xxxxxxxxxxxxx>