From 7f4d7fef31bd282b8e37d6d401208535a1e74d17 Mon Sep 17 00:00:00 2001 From: Florian Westphal Date: Thu, 26 Jun 2025 16:52:31 +0200 Subject: [PATCH] evaluate: check element key vs. set definition Included bogon asserts with: src/datatype.c:253: symbolic_constant_print: Assertion `expr->len / BITS_PER_BYTE <= sizeof(val)' failed. Resolve this by validating that the set element key matches the set key definition. After this, loading the bogon file gives: Error: Element mismatches set definition, expected concatenation of (IPv4 address, integer), not 'ICMP type' elements = {redirect } ^^^^^^^^ Signed-off-by: Florian Westphal --- src/evaluate.c | 30 ++++++++++++++----- .../nft-f/symbolic_constant_print_assert | 7 +++++ 2 files changed, 30 insertions(+), 7 deletions(-) create mode 100644 tests/shell/testcases/bogons/nft-f/symbolic_constant_print_assert diff --git a/src/evaluate.c b/src/evaluate.c index 1fa4cb78..9c905908 100644 --- a/src/evaluate.c +++ b/src/evaluate.c @@ -1917,6 +1917,23 @@ static int __expr_evaluate_set_elem(struct eval_ctx *ctx, struct expr *elem) return 0; } +static bool datatype_compatible(const struct datatype *a, const struct datatype *b) +{ + return (a->type == TYPE_MARK && + datatype_equal(datatype_basetype(a), datatype_basetype(b))) || + datatype_equal(a, b); +} + +static bool elem_key_compatible(const struct expr *set_key, + const struct expr *elem_key) +{ + /* Catchall element is always compatible with the set key declaration */ + if (elem_key->etype == EXPR_SET_ELEM_CATCHALL) + return true; + + return datatype_compatible(set_key->dtype, elem_key->dtype); +} + static int expr_evaluate_set_elem(struct eval_ctx *ctx, struct expr **expr) { struct expr *elem = *expr; @@ -1959,6 +1976,12 @@ static int expr_evaluate_set_elem(struct eval_ctx *ctx, struct expr **expr) } } + if (ctx->set && !elem_key_compatible(ctx->ectx.key, elem->key)) + return expr_error(ctx->msgs, elem, + "Element mismatches %s definition, expected %s, not '%s'", + set_is_map(ctx->set->flags) ? "map" : "set", + ctx->ectx.key->dtype->desc, elem->key->dtype->desc); + datatype_set(elem, elem->key->dtype); elem->len = elem->key->len; elem->flags = elem->key->flags; @@ -2171,13 +2194,6 @@ static int mapping_expr_expand(struct eval_ctx *ctx) return 0; } -static bool datatype_compatible(const struct datatype *a, const struct datatype *b) -{ - return (a->type == TYPE_MARK && - datatype_equal(datatype_basetype(a), datatype_basetype(b))) || - datatype_equal(a, b); -} - static int expr_evaluate_map(struct eval_ctx *ctx, struct expr **expr) { struct expr *map = *expr, *mappings; diff --git a/tests/shell/testcases/bogons/nft-f/symbolic_constant_print_assert b/tests/shell/testcases/bogons/nft-f/symbolic_constant_print_assert new file mode 100644 index 00000000..e01fb3be --- /dev/null +++ b/tests/shell/testcases/bogons/nft-f/symbolic_constant_print_assert @@ -0,0 +1,7 @@ +table inet t { + set y { + typeof ip daddr . @ih,32,35 + elements = {redirect } + } +} +reset rules -- 2.39.5