]> git.ipfire.org Git - thirdparty/nftables.git/commitdiff
evaluate: rename recursion counter to recursion.binop
authorFlorian Westphal <fw@strlen.de>
Fri, 6 Jun 2025 12:12:36 +0000 (14:12 +0200)
committerPablo Neira Ayuso <pablo@netfilter.org>
Wed, 13 Aug 2025 18:10:05 +0000 (20:10 +0200)
commit 10b44319a53a131ed943e2b6eeb62d197178bf4d upstream.

The existing recursion counter is used by the binop expression to detect
if we've completely followed all the binops.

We can only chain up to NFT_MAX_EXPR_RECURSION binops, but the evaluation
step can perform constant-folding, so we must recurse until we found the
rightmost (last) binop in the chain.

Then we can check the post-eval chain to see if it is something that can
be serialized later (i.e., if we are within the NFT_MAX_EXPR_RECURSION
after constant folding) or not.

Thus we can't reuse the existing ctx->recursion counter for other
expressions; entering the initial expr_evaluate_binop with
ctx->recursion > 0 would break things.

Therefore rename this to an embedded structure.
This allows us to add a new recursion counter in a followup patch.

Signed-off-by: Florian Westphal <fw@strlen.de>
include/rule.h
src/evaluate.c

index 15bdce4770d27a2243d23484b7418b0846fb7114..2159d944e024760c2a76160bfb0183faea304c4b 100644 (file)
@@ -751,6 +751,10 @@ void cmd_add_loc(struct cmd *cmd, uint16_t offset, const struct location *loc);
 #include <payload.h>
 #include <expression.h>
 
+struct eval_recursion {
+       uint16_t binop;
+};
+
 /**
  * struct eval_ctx - evaluation context
  *
@@ -762,7 +766,7 @@ void cmd_add_loc(struct cmd *cmd, uint16_t offset, const struct location *loc);
  * @set:       current set
  * @stmt:      current statement
  * @stmt_len:  current statement template length
- * @recursion:  expr evaluation recursion counter
+ * @recursion:  expr evaluation recursion counters
  * @cache:     cache context
  * @debug_mask: debugging bitmask
  * @ectx:      expression context
@@ -778,7 +782,7 @@ struct eval_ctx {
        struct set              *set;
        struct stmt             *stmt;
        uint32_t                stmt_len;
-       uint32_t                recursion;
+       struct eval_recursion   recursion;
        struct expr_ctx         ectx;
        struct proto_ctx        pctx;
 };
index 25c55ba9d6581c8e5a67dafe72f95022c8e52e9e..3330987e8c9e8a5a695cb878a4511a4ce480bab8 100644 (file)
@@ -1410,11 +1410,11 @@ static int expr_evaluate_binop(struct eval_ctx *ctx, struct expr **expr)
        unsigned int max_shift_len = ctx->ectx.len;
        int ret = -1;
 
-       if (ctx->recursion >= USHRT_MAX)
+       if (ctx->recursion.binop >= USHRT_MAX)
                return expr_binary_error(ctx->msgs, op, NULL,
                                         "Binary operation limit %u reached ",
-                                        ctx->recursion);
-       ctx->recursion++;
+                                        ctx->recursion.binop);
+       ctx->recursion.binop++;
 
        if (expr_evaluate(ctx, &op->left) < 0)
                return -1;
@@ -1481,7 +1481,7 @@ static int expr_evaluate_binop(struct eval_ctx *ctx, struct expr **expr)
        }
 
 
-       if (ctx->recursion == 0)
+       if (ctx->recursion.binop == 0)
                BUG("recursion counter underflow");
 
        /* can't check earlier: evaluate functions might do constant-merging + expr_free.
@@ -1489,7 +1489,7 @@ static int expr_evaluate_binop(struct eval_ctx *ctx, struct expr **expr)
         * So once we've evaluate everything check for remaining length of the
         * binop chain.
         */
-       if (--ctx->recursion == 0) {
+       if (--ctx->recursion.binop == 0) {
                unsigned int to_linearize = 0;
 
                op = *expr;