]> git.ipfire.org Git - thirdparty/nftables.git/commitdiff
evaluate: do not skip mapping elements
authorPablo Neira Ayuso <pablo@netfilter.org>
Wed, 16 Jun 2021 17:00:50 +0000 (19:00 +0200)
committerPablo Neira Ayuso <pablo@netfilter.org>
Fri, 18 Jun 2021 07:40:20 +0000 (09:40 +0200)
Set element keys are of EXPR_SET_ELEM expression type, however, mappings
use the EXPR_MAPPING expression to wrap the EXPR_SET_ELEM key
(mapping->left) and the corresponding data (mapping->right).

This patch adds a wrapper function to fetch the EXPR_SET_ELEM expression
from the key in case of mappings and use it.

Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
src/evaluate.c

index aa7ec9bee4aeb577394c135a998b8e611c69255a..d220c8e391ac56c1e09835d47384a91c7a95b51b 100644 (file)
@@ -1414,27 +1414,39 @@ static int expr_evaluate_set_elem(struct eval_ctx *ctx, struct expr **expr)
        return 0;
 }
 
+static const struct expr *expr_set_elem(const struct expr *expr)
+{
+       if (expr->etype == EXPR_MAPPING)
+               return expr->left;
+
+       return expr;
+}
+
 static int expr_evaluate_set(struct eval_ctx *ctx, struct expr **expr)
 {
        struct expr *set = *expr, *i, *next;
+       const struct expr *elem;
 
        list_for_each_entry_safe(i, next, &set->expressions, list) {
                if (list_member_evaluate(ctx, &i) < 0)
                        return -1;
 
-               if (i->etype == EXPR_SET_ELEM &&
-                   i->key->etype == EXPR_SET_REF)
+               elem = expr_set_elem(i);
+
+               if (elem->etype == EXPR_SET_ELEM &&
+                   elem->key->etype == EXPR_SET_REF)
                        return expr_error(ctx->msgs, i,
                                          "Set reference cannot be part of another set");
 
-               if (i->etype == EXPR_SET_ELEM &&
-                   i->key->etype == EXPR_SET) {
-                       struct expr *new = expr_clone(i->key);
+               if (elem->etype == EXPR_SET_ELEM &&
+                   elem->key->etype == EXPR_SET) {
+                       struct expr *new = expr_clone(elem->key);
 
-                       set->set_flags |= i->key->set_flags;
+                       set->set_flags |= elem->key->set_flags;
                        list_replace(&i->list, &new->list);
                        expr_free(i);
                        i = new;
+                       elem = expr_set_elem(i);
                }
 
                if (!expr_is_constant(i))
@@ -1450,7 +1462,7 @@ static int expr_evaluate_set(struct eval_ctx *ctx, struct expr **expr)
                        expr_free(i);
                } else if (!expr_is_singleton(i)) {
                        set->set_flags |= NFT_SET_INTERVAL;
-                       if (i->key->etype == EXPR_CONCAT)
+                       if (elem->key->etype == EXPR_CONCAT)
                                set->set_flags |= NFT_SET_CONCAT;
                }
        }