]> git.ipfire.org Git - thirdparty/nftables.git/commitdiff
optimize: Fix verdict expression comparison
authorPhil Sutter <phil@nwl.cc>
Wed, 22 Oct 2025 12:03:37 +0000 (14:03 +0200)
committerPhil Sutter <phil@nwl.cc>
Thu, 23 Oct 2025 20:48:50 +0000 (22:48 +0200)
In verdict expression, 'chain' points at a constant expression of
verdict_type, not a symbol expression. Therefore 'chain->identifier'
points eight bytes (on 64bit systems) into the mpz_t 'value' holding the
chain name. This matches the '_mp_d' data pointer, so works by accident.

Fix this by copying what verdict_jump_chain_print() does and export
chain names before comparing.

Fixes: fb298877ece27 ("src: add ruleset optimization infrastructure")
Signed-off-by: Phil Sutter <phil@nwl.cc>
src/optimize.c

index cdd6913a306dd8ecc4b104e99fa5d819737628f8..ffc06480d4ee5a587716f3846c67f729f5c0bf1b 100644 (file)
@@ -341,13 +341,18 @@ static bool __stmt_type_eq(const struct stmt *stmt_a, const struct stmt *stmt_b,
 
 static bool expr_verdict_eq(const struct expr *expr_a, const struct expr *expr_b)
 {
+       char chain_a[NFT_CHAIN_MAXNAMELEN];
+       char chain_b[NFT_CHAIN_MAXNAMELEN];
+
        if (expr_a->verdict != expr_b->verdict)
                return false;
        if (expr_a->chain && expr_b->chain) {
-               if (expr_a->chain->etype != expr_b->chain->etype)
+               if (expr_a->chain->etype != EXPR_VALUE ||
+                   expr_a->chain->etype != expr_b->chain->etype)
                        return false;
-               if (expr_a->chain->etype == EXPR_VALUE &&
-                   strcmp(expr_a->chain->identifier, expr_b->chain->identifier))
+               expr_chain_export(expr_a->chain, chain_a);
+               expr_chain_export(expr_b->chain, chain_b);
+               if (strcmp(chain_a, chain_b))
                        return false;
        } else if (expr_a->chain || expr_b->chain) {
                return false;