]> 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)
committerFlorian Westphal <fw@strlen.de>
Sun, 22 Jun 2025 17:18:45 +0000 (19:18 +0200)
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 85a0d9c0b524b05199daeb75751db0962c624bda..e7e80a41506cb0b796dff0e3a6f3781eeddc4815 100644 (file)
@@ -756,6 +756,10 @@ extern void cmd_free(struct cmd *cmd);
 #include <payload.h>
 #include <expression.h>
 
+struct eval_recursion {
+       uint16_t binop;
+};
+
 /**
  * struct eval_ctx - evaluation context
  *
@@ -767,7 +771,7 @@ extern void cmd_free(struct cmd *cmd);
  * @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
@@ -783,7 +787,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[2];
        const struct proto_desc *inner_desc;
index 872a9e0d8c61cff4c391ed7f6f127a05e1363182..77bdb9cd74c5a977c1fd2c0ae854e7aeae79ec0c 100644 (file)
@@ -1520,11 +1520,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;
@@ -1609,7 +1609,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.
@@ -1617,7 +1617,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;