From: Pablo Neira Ayuso <pablo@netfilter.org>
To: netfilter-devel@vger.kernel.org
Subject: [PATCH nft 3/7] src: assert on EXPR_SET only contains EXPR_SET_ELEM in the expressions list
Date: Fri, 5 Sep 2025 17:36:23 +0200 [thread overview]
Message-ID: <20250905153627.1315405-4-pablo@netfilter.org> (raw)
In-Reply-To: <20250905153627.1315405-1-pablo@netfilter.org>
Normalize the representation so the expressions list in EXPR_SET always
contains EXPR_SET_ELEM. Add assert() to validate this.
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
---
src/evaluate.c | 23 +++++++++--------------
src/expression.c | 16 ++++++++++++----
src/intervals.c | 14 ++++++++++++++
src/json.c | 10 ++++++++--
src/netlink.c | 2 ++
src/netlink_delinearize.c | 9 ++++++---
src/optimize.c | 3 +++
src/segtree.c | 6 ++++++
8 files changed, 60 insertions(+), 23 deletions(-)
diff --git a/src/evaluate.c b/src/evaluate.c
index b0a3e990e476..0b7508a18ede 100644
--- a/src/evaluate.c
+++ b/src/evaluate.c
@@ -2069,6 +2069,8 @@ static int expr_evaluate_set(struct eval_ctx *ctx, struct expr **expr)
struct expr *new, *j;
list_for_each_entry(j, &expr_set(i->key->left)->expressions, list) {
+ assert(j->etype == EXPR_SET_ELEM);
+
new = mapping_expr_alloc(&i->location,
expr_get(j->key),
expr_get(i->key->right));
@@ -2770,9 +2772,9 @@ static void optimize_singleton_set(struct expr *rel, struct expr **expr)
struct expr *set = rel->right, *i;
i = list_first_entry(&expr_set(set)->expressions, struct expr, list);
- if (i->etype == EXPR_SET_ELEM &&
- list_empty(&i->stmt_list)) {
+ assert (i->etype == EXPR_SET_ELEM);
+ if (list_empty(&i->stmt_list)) {
switch (i->key->etype) {
case EXPR_PREFIX:
case EXPR_RANGE:
@@ -5476,19 +5478,12 @@ static struct expr *expr_set_to_list(struct eval_ctx *ctx, struct expr *dev_expr
LIST_HEAD(tmp);
list_for_each_entry_safe(expr, next, &expr_set(dev_expr)->expressions, list) {
- list_del(&expr->list);
-
- switch (expr->etype) {
- case EXPR_SET_ELEM:
- key = expr_clone(expr->key);
- expr_free(expr);
- expr = key;
- break;
- default:
- BUG("invalid expression type %s\n", expr_name(expr));
- break;
- }
+ assert(expr->etype == EXPR_SET_ELEM);
+ list_del(&expr->list);
+ key = expr_clone(expr->key);
+ expr_free(expr);
+ expr = key;
list_add(&expr->list, &tmp);
}
diff --git a/src/expression.c b/src/expression.c
index 8b54b6a38ae5..68e2fec192b2 100644
--- a/src/expression.c
+++ b/src/expression.c
@@ -941,8 +941,9 @@ void relational_expr_pctx_update(struct proto_ctx *ctx,
ops->pctx_update(ctx, &expr->location, left, right);
else if (right->etype == EXPR_SET) {
list_for_each_entry(i, &expr_set(right)->expressions, list) {
- if (i->etype == EXPR_SET_ELEM &&
- i->key->etype == EXPR_VALUE)
+ assert(i->etype == EXPR_SET_ELEM);
+
+ if (i->key->etype == EXPR_VALUE)
ops->pctx_update(ctx, &expr->location, left, i->key);
}
} else if (ops == &meta_expr_ops &&
@@ -1378,6 +1379,8 @@ static void set_expr_print(const struct expr *expr, struct output_ctx *octx)
nft_print(octx, "{ ");
list_for_each_entry(i, &expr_set(expr)->expressions, list) {
+ assert(i->etype == EXPR_SET_ELEM);
+
nft_print(octx, "%s", d);
expr_print(i, octx);
count++;
@@ -1400,8 +1403,10 @@ static void set_expr_destroy(struct expr *expr)
{
struct expr *i, *next;
- list_for_each_entry_safe(i, next, &expr_set(expr)->expressions, list)
+ list_for_each_entry_safe(i, next, &expr_set(expr)->expressions, list) {
+ assert(i->etype == EXPR_SET_ELEM);
expr_free(i);
+ }
}
static void set_expr_set_type(const struct expr *expr,
@@ -1410,8 +1415,11 @@ static void set_expr_set_type(const struct expr *expr,
{
struct expr *i;
- list_for_each_entry(i, &expr_set(expr)->expressions, list)
+ list_for_each_entry(i, &expr_set(expr)->expressions, list) {
+ assert(i->etype == EXPR_SET_ELEM);
+
expr_set_type(i, dtype, byteorder);
+ }
}
static const struct expr_ops set_expr_ops = {
diff --git a/src/intervals.c b/src/intervals.c
index 7df5ce2ab4db..3ac45cf29abd 100644
--- a/src/intervals.c
+++ b/src/intervals.c
@@ -183,6 +183,8 @@ static void setelem_automerge(struct set_automerge_ctx *ctx)
mpz_init(rop);
list_for_each_entry_safe(i, next, &expr_set(ctx->init)->expressions, list) {
+ assert(i->etype == EXPR_SET_ELEM);
+
if (expr_type_catchall(i->key))
continue;
@@ -243,6 +245,8 @@ static void set_to_range(struct expr *init)
struct expr *i, *elem;
list_for_each_entry(i, &expr_set(init)->expressions, list) {
+ assert(i->etype == EXPR_SET_ELEM);
+
elem = interval_expr_key(i);
setelem_expr_to_range(elem);
}
@@ -274,6 +278,8 @@ int set_automerge(struct list_head *msgs, struct cmd *cmd, struct set *set,
setelem_automerge(&ctx);
list_for_each_entry_safe(i, next, &expr_set(init)->expressions, list) {
+ assert(i->etype == EXPR_SET_ELEM);
+
if (i->flags & EXPR_F_KERNEL) {
list_move_tail(&i->list, &expr_set(existing_set->init)->expressions);
} else if (existing_set) {
@@ -413,6 +419,8 @@ static int setelem_delete(struct list_head *msgs, struct set *set,
mpz_init(rop);
list_for_each_entry_safe(elem, next, &expr_set(elems)->expressions, list) {
+ assert(elem->etype == EXPR_SET_ELEM);
+
i = interval_expr_key(elem);
if (expr_type_catchall(i->key)) {
@@ -585,6 +593,8 @@ static int setelem_overlap(struct list_head *msgs, struct set *set,
mpz_init(rop);
list_for_each_entry_safe(elem, next, &expr_set(init)->expressions, list) {
+ assert(elem->etype == EXPR_SET_ELEM);
+
i = interval_expr_key(elem);
if (expr_type_catchall(i->key))
@@ -654,6 +664,8 @@ int set_overlap(struct list_head *msgs, struct set *set, struct expr *init)
err = setelem_overlap(msgs, set, init);
list_for_each_entry_safe(i, n, &expr_set(init)->expressions, list) {
+ assert(i->etype == EXPR_SET_ELEM);
+
if (i->flags & EXPR_F_KERNEL)
list_move_tail(&i->list, &expr_set(existing_set->init)->expressions);
else if (existing_set) {
@@ -711,6 +723,8 @@ int set_to_intervals(const struct set *set, struct expr *init, bool add)
mpz_t p;
list_for_each_entry_safe(i, n, &expr_set(init)->expressions, list) {
+ assert(i->etype == EXPR_SET_ELEM);
+
elem = interval_expr_key(i);
if (expr_type_catchall(elem->key))
diff --git a/src/json.c b/src/json.c
index 36c03e581b4a..612e8e6999eb 100644
--- a/src/json.c
+++ b/src/json.c
@@ -232,8 +232,11 @@ static json_t *set_print_json(struct output_ctx *octx, const struct set *set)
json_t *array = json_array();
const struct expr *i;
- list_for_each_entry(i, &expr_set(set->init)->expressions, list)
+ list_for_each_entry(i, &expr_set(set->init)->expressions, list) {
+ assert(i->etype == EXPR_SET_ELEM);
+
json_array_append_new(array, expr_print_json(i, octx));
+ }
json_object_set_new(root, "elem", array);
}
@@ -763,8 +766,11 @@ json_t *set_expr_json(const struct expr *expr, struct output_ctx *octx)
json_t *array = json_array();
const struct expr *i;
- list_for_each_entry(i, &expr_set(expr)->expressions, list)
+ list_for_each_entry(i, &expr_set(expr)->expressions, list) {
+ assert(i->etype == EXPR_SET_ELEM);
+
json_array_append_new(array, expr_print_json(i, octx));
+ }
return nft_json_pack("{s:o}", "set", array);
}
diff --git a/src/netlink.c b/src/netlink.c
index 10817e5cfb53..7a17f394c69f 100644
--- a/src/netlink.c
+++ b/src/netlink.c
@@ -1219,6 +1219,8 @@ void alloc_setelem_cache(const struct expr *set, struct nftnl_set *nls)
const struct expr *expr;
list_for_each_entry(expr, &expr_set(set)->expressions, list) {
+ assert(expr->etype == EXPR_SET_ELEM);
+
nlse = alloc_nftnl_setelem(set, expr);
nftnl_set_elem_add(nls, nlse);
}
diff --git a/src/netlink_delinearize.c b/src/netlink_delinearize.c
index f4ebdfcbf2f3..3db5502910ad 100644
--- a/src/netlink_delinearize.c
+++ b/src/netlink_delinearize.c
@@ -2206,9 +2206,9 @@ static void payload_match_postprocess(struct rule_pp_ctx *ctx,
struct expr *elem;
elem = list_first_entry(&expr_set(set->init)->expressions, struct expr, list);
+ assert(elem->etype == EXPR_SET_ELEM);
- if (elem->etype == EXPR_SET_ELEM &&
- elem->key->etype == EXPR_VALUE)
+ if (elem->key->etype == EXPR_VALUE)
payload_icmp_check(ctx, payload, elem->key);
}
}
@@ -2882,8 +2882,11 @@ static void expr_postprocess(struct rule_pp_ctx *ctx, struct expr **exprp)
expr_postprocess(ctx, &expr->right);
break;
case EXPR_SET:
- list_for_each_entry(i, &expr_set(expr)->expressions, list)
+ list_for_each_entry(i, &expr_set(expr)->expressions, list) {
+ assert(i->etype == EXPR_SET);
+
expr_postprocess(ctx, &i);
+ }
break;
case EXPR_CONCAT:
expr_postprocess_concat(ctx, exprp);
diff --git a/src/optimize.c b/src/optimize.c
index 422990d1ca6f..e537f48adf58 100644
--- a/src/optimize.c
+++ b/src/optimize.c
@@ -589,6 +589,7 @@ static void merge_vmap(const struct optimize_ctx *ctx,
mappings = stmt_b->expr->mappings;
list_for_each_entry(expr, &expr_set(mappings)->expressions, list) {
+ assert(expr->etype == EXPR_SET_ELEM);
mapping = expr_clone(expr);
set_expr_add(stmt_a->expr->mappings, mapping);
}
@@ -655,6 +656,7 @@ static void __merge_concat(const struct optimize_ctx *ctx, uint32_t i,
switch (stmt_a->expr->right->etype) {
case EXPR_SET:
list_for_each_entry(expr, &expr_set(stmt_a->expr->right)->expressions, list) {
+ assert(expr->etype == EXPR_SET_ELEM);
concat_clone = expr_clone(concat);
clone = expr_clone(expr->key);
concat_expr_add(concat_clone, clone);
@@ -766,6 +768,7 @@ static void build_verdict_map(struct expr *expr, struct stmt *verdict,
break;
case EXPR_SET:
list_for_each_entry(item, &expr_set(expr)->expressions, list) {
+ assert(item->etype == EXPR_SET_ELEM);
mapping = mapping_expr_alloc(&internal_location, expr_get(item->key),
expr_get(verdict->expr));
diff --git a/src/segtree.c b/src/segtree.c
index b5be0005d1ea..f95a7ce1c8a8 100644
--- a/src/segtree.c
+++ b/src/segtree.c
@@ -80,6 +80,8 @@ struct expr *get_set_intervals(const struct set *set, const struct expr *init)
new_init = set_expr_alloc(&internal_location, NULL);
list_for_each_entry(i, &expr_set(init)->expressions, list) {
+ assert(i->etype == EXPR_SET_ELEM);
+
switch (i->key->etype) {
case EXPR_VALUE:
set_elem_add(set, new_init, i->key->value,
@@ -137,6 +139,8 @@ static struct expr *get_set_interval_find(const struct set *cache_set,
mpz_init2(val, set->key->len);
list_for_each_entry(i, &expr_set(set->init)->expressions, list) {
+ assert(i->etype == EXPR_SET_ELEM);
+
key = expr_value(i);
switch (key->etype) {
case EXPR_VALUE:
@@ -357,6 +361,8 @@ void concat_range_aggregate(struct expr *set)
mpz_t range, p;
list_for_each_entry_safe(i, next, &expr_set(set)->expressions, list) {
+ assert(i->etype == EXPR_SET_ELEM);
+
if (!start) {
start = i;
continue;
--
2.30.2
next prev parent reply other threads:[~2025-09-05 15:45 UTC|newest]
Thread overview: 10+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-09-05 15:36 [PATCH nft 0/7] prepare for EXPR_SET_ELEM removal Pablo Neira Ayuso
2025-09-05 15:36 ` [PATCH nft 1/7] src: normalize set element with EXPR_MAPPING Pablo Neira Ayuso
2025-09-07 14:10 ` Florian Westphal
2025-09-08 7:59 ` Pablo Neira Ayuso
2025-09-05 15:36 ` [PATCH nft 2/7] src: allocate EXPR_SET_ELEM for EXPR_SET in embedded set declaration in sets Pablo Neira Ayuso
2025-09-05 15:36 ` Pablo Neira Ayuso [this message]
2025-09-05 15:36 ` [PATCH nft 4/7] evaluate: simplify sets as set elems evaluation Pablo Neira Ayuso
2025-09-05 15:36 ` [PATCH nft 5/7] evaluate: clean up expr_evaluate_set() Pablo Neira Ayuso
2025-09-05 15:36 ` [PATCH nft 6/7] segtree: rename set_elem_add() to set_elem_expr_add() Pablo Neira Ayuso
2025-09-05 15:36 ` [PATCH nft 7/7] src: move flags from EXPR_SET_ELEM to key Pablo Neira Ayuso
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20250905153627.1315405-4-pablo@netfilter.org \
--to=pablo@netfilter.org \
--cc=netfilter-devel@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox