The existing recursion counter is only 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 first 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 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 to the new embedded structure in a followup patch. Signed-off-by: Florian Westphal <fw@xxxxxxxxx> --- include/rule.h | 8 ++++++-- src/evaluate.c | 10 +++++----- 2 files changed, 11 insertions(+), 7 deletions(-) diff --git a/include/rule.h b/include/rule.h index 85a0d9c0b524..e7e80a41506c 100644 --- a/include/rule.h +++ b/include/rule.h @@ -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; diff --git a/src/evaluate.c b/src/evaluate.c index f73edc916406..d099be137cb3 100644 --- a/src/evaluate.c +++ b/src/evaluate.c @@ -1518,11 +1518,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; @@ -1607,7 +1607,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. @@ -1615,7 +1615,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; -- 2.49.0