]> git.ipfire.org Git - thirdparty/nftables.git/commitdiff
evaluate: clone variable expression if there is more than one reference
authorPablo Neira Ayuso <pablo@netfilter.org>
Fri, 5 Nov 2021 13:43:17 +0000 (14:43 +0100)
committerPablo Neira Ayuso <pablo@netfilter.org>
Mon, 8 Nov 2021 09:59:33 +0000 (10:59 +0100)
Clone the expression that defines the variable value if there are
multiple references to it in the ruleset. This saves heap memory
consumption in case the variable defines a set with a huge number of
elements.

Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
src/evaluate.c
tests/shell/testcases/nft-f/0030variable_reuse_0 [new file with mode: 0755]
tests/shell/testcases/nft-f/dumps/0030variable_reuse_0.nft [new file with mode: 0644]

index a268b3cb9ee2d177d2817ad7014ab7c1c014ddc9..fd7818da1116f4f738985339f6d31e68f4ced5b3 100644 (file)
@@ -2187,7 +2187,16 @@ static int expr_evaluate_osf(struct eval_ctx *ctx, struct expr **expr)
 
 static int expr_evaluate_variable(struct eval_ctx *ctx, struct expr **exprp)
 {
-       struct expr *new = expr_clone((*exprp)->sym->expr);
+       struct symbol *sym = (*exprp)->sym;
+       struct expr *new;
+
+       /* If variable is reused from different locations in the ruleset, then
+        * clone expression.
+        */
+       if (sym->refcnt > 2)
+               new = expr_clone(sym->expr);
+       else
+               new = expr_get(sym->expr);
 
        if (expr_evaluate(ctx, &new) < 0) {
                expr_free(new);
diff --git a/tests/shell/testcases/nft-f/0030variable_reuse_0 b/tests/shell/testcases/nft-f/0030variable_reuse_0
new file mode 100755 (executable)
index 0000000..8afc54a
--- /dev/null
@@ -0,0 +1,19 @@
+#!/bin/bash
+
+set -e
+
+RULESET="define test = { 1.1.1.1 }
+
+table ip x {
+        set y {
+                type ipv4_addr
+                elements = { 2.2.2.2, \$test }
+        }
+
+        set z {
+                type ipv4_addr
+                elements = { 3.3.3.3, \$test }
+        }
+}"
+
+$NFT -f - <<< "$RULESET"
diff --git a/tests/shell/testcases/nft-f/dumps/0030variable_reuse_0.nft b/tests/shell/testcases/nft-f/dumps/0030variable_reuse_0.nft
new file mode 100644 (file)
index 0000000..635901f
--- /dev/null
@@ -0,0 +1,11 @@
+table ip x {
+       set y {
+               type ipv4_addr
+               elements = { 1.1.1.1, 2.2.2.2 }
+       }
+
+       set z {
+               type ipv4_addr
+               elements = { 1.1.1.1, 3.3.3.3 }
+       }
+}