From: Florian Westphal Date: Fri, 6 Jun 2025 12:12:36 +0000 (+0200) Subject: evaluate: rename recursion counter to recursion.binop X-Git-Tag: v1.0.6.1~47 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=3da5b12751576eec4fb564970c34c8dee3f4f8d2;p=thirdparty%2Fnftables.git evaluate: rename recursion counter to recursion.binop 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 --- diff --git a/include/rule.h b/include/rule.h index 15bdce47..2159d944 100644 --- a/include/rule.h +++ b/include/rule.h @@ -751,6 +751,10 @@ void cmd_add_loc(struct cmd *cmd, uint16_t offset, const struct location *loc); #include #include +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; }; diff --git a/src/evaluate.c b/src/evaluate.c index 25c55ba9..3330987e 100644 --- a/src/evaluate.c +++ b/src/evaluate.c @@ -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;