346 lines
9.9 KiB
Diff
346 lines
9.9 KiB
Diff
From f120f2c4a4a4c95c66ba1a90647b146cdf2aca57 Mon Sep 17 00:00:00 2001
|
|
From: Phil Sutter <psutter@redhat.com>
|
|
Date: Tue, 24 Feb 2026 15:53:22 +0100
|
|
Subject: [PATCH] mergesort: Fix sorting of string values
|
|
|
|
JIRA: https://issues.redhat.com/browse/RHEL-128553
|
|
Upstream Status: nftables commit 340d904a974ed206fcc4d8ca32540762fd8e59e0
|
|
|
|
commit 340d904a974ed206fcc4d8ca32540762fd8e59e0
|
|
Author: Phil Sutter <phil@nwl.cc>
|
|
Date: Thu Nov 13 00:03:37 2025 +0100
|
|
|
|
mergesort: Fix sorting of string values
|
|
|
|
Sorting order was obviously wrong, e.g. "ppp0" ordered before "eth1".
|
|
Moreover, this happened on Little Endian only so sorting order actually
|
|
depended on host's byteorder. By reimporting string values as Big
|
|
Endian, both issues are fixed: On one hand, GMP-internal byteorder no
|
|
longer depends on host's byteorder, on the other comparing strings
|
|
really starts with the first character, not the last.
|
|
|
|
Fixes: 14ee0a979b622 ("src: sort set elements in netlink_get_setelems()")
|
|
Signed-off-by: Phil Sutter <phil@nwl.cc>
|
|
|
|
Signed-off-by: Phil Sutter <psutter@redhat.com>
|
|
---
|
|
src/mergesort.c | 7 +++
|
|
tests/py/any/meta.t.json.output | 54 -------------------
|
|
tests/py/any/queue.t.json.output | 4 +-
|
|
tests/py/inet/osf.t.json.output | 54 +++++++++++++++++++
|
|
.../testcases/maps/dumps/0012map_0.json-nft | 20 +++----
|
|
.../shell/testcases/maps/dumps/0012map_0.nft | 8 +--
|
|
.../maps/dumps/named_ct_objects.json-nft | 4 +-
|
|
.../testcases/maps/dumps/named_ct_objects.nft | 4 +-
|
|
.../sets/dumps/sets_with_ifnames.json-nft | 4 +-
|
|
.../sets/dumps/sets_with_ifnames.nft | 2 +-
|
|
10 files changed, 84 insertions(+), 77 deletions(-)
|
|
|
|
diff --git a/src/mergesort.c b/src/mergesort.c
|
|
index bd1c218..4e15a8b 100644
|
|
--- a/src/mergesort.c
|
|
+++ b/src/mergesort.c
|
|
@@ -37,6 +37,13 @@ static mpz_srcptr expr_msort_value(const struct expr *expr, mpz_t value)
|
|
case EXPR_RANGE:
|
|
return expr_msort_value(expr->left, value);
|
|
case EXPR_VALUE:
|
|
+ if (expr_basetype(expr)->type == TYPE_STRING) {
|
|
+ char buf[expr->len];
|
|
+
|
|
+ mpz_export_data(buf, expr->value, BYTEORDER_HOST_ENDIAN, expr->len);
|
|
+ mpz_import_data(value, buf, BYTEORDER_BIG_ENDIAN, expr->len);
|
|
+ return value;
|
|
+ }
|
|
return expr->value;
|
|
case EXPR_RANGE_VALUE:
|
|
return expr->range.low;
|
|
diff --git a/tests/py/any/meta.t.json.output b/tests/py/any/meta.t.json.output
|
|
index 8f4d597..4454bb9 100644
|
|
--- a/tests/py/any/meta.t.json.output
|
|
+++ b/tests/py/any/meta.t.json.output
|
|
@@ -233,60 +233,6 @@
|
|
}
|
|
]
|
|
|
|
-# meta iifname {"dummy0", "lo"}
|
|
-[
|
|
- {
|
|
- "match": {
|
|
- "left": {
|
|
- "meta": { "key": "iifname" }
|
|
- },
|
|
- "op": "==",
|
|
- "right": {
|
|
- "set": [
|
|
- "lo",
|
|
- "dummy0"
|
|
- ]
|
|
- }
|
|
- }
|
|
- }
|
|
-]
|
|
-
|
|
-# meta iifname != {"dummy0", "lo"}
|
|
-[
|
|
- {
|
|
- "match": {
|
|
- "left": {
|
|
- "meta": { "key": "iifname" }
|
|
- },
|
|
- "op": "!=",
|
|
- "right": {
|
|
- "set": [
|
|
- "lo",
|
|
- "dummy0"
|
|
- ]
|
|
- }
|
|
- }
|
|
- }
|
|
-]
|
|
-
|
|
-# meta oifname { "dummy0", "lo"}
|
|
-[
|
|
- {
|
|
- "match": {
|
|
- "left": {
|
|
- "meta": { "key": "oifname" }
|
|
- },
|
|
- "op": "==",
|
|
- "right": {
|
|
- "set": [
|
|
- "lo",
|
|
- "dummy0"
|
|
- ]
|
|
- }
|
|
- }
|
|
- }
|
|
-]
|
|
-
|
|
# meta skuid {"bin", "root", "daemon"} accept
|
|
[
|
|
{
|
|
diff --git a/tests/py/any/queue.t.json.output b/tests/py/any/queue.t.json.output
|
|
index ea37223..90670cc 100644
|
|
--- a/tests/py/any/queue.t.json.output
|
|
+++ b/tests/py/any/queue.t.json.output
|
|
@@ -104,11 +104,11 @@
|
|
0
|
|
],
|
|
[
|
|
- "ppp0",
|
|
+ "eth1",
|
|
2
|
|
],
|
|
[
|
|
- "eth1",
|
|
+ "ppp0",
|
|
2
|
|
]
|
|
]
|
|
diff --git a/tests/py/inet/osf.t.json.output b/tests/py/inet/osf.t.json.output
|
|
index 922e395..77ca7e3 100644
|
|
--- a/tests/py/inet/osf.t.json.output
|
|
+++ b/tests/py/inet/osf.t.json.output
|
|
@@ -18,6 +18,26 @@
|
|
}
|
|
]
|
|
|
|
+# osf version { "Windows:XP", "MacOs:Sierra" }
|
|
+[
|
|
+ {
|
|
+ "match": {
|
|
+ "left": {
|
|
+ "osf": {
|
|
+ "key": "version"
|
|
+ }
|
|
+ },
|
|
+ "op": "==",
|
|
+ "right": {
|
|
+ "set": [
|
|
+ "MacOs:Sierra",
|
|
+ "Windows:XP"
|
|
+ ]
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+]
|
|
+
|
|
# ct mark set osf name map { "Windows" : 0x00000001, "MacOs" : 0x00000002 }
|
|
[
|
|
{
|
|
@@ -51,3 +71,37 @@
|
|
}
|
|
}
|
|
]
|
|
+
|
|
+# ct mark set osf version map { "Windows:XP" : 0x00000003, "MacOs:Sierra" : 0x00000004 }
|
|
+[
|
|
+ {
|
|
+ "mangle": {
|
|
+ "key": {
|
|
+ "ct": {
|
|
+ "key": "mark"
|
|
+ }
|
|
+ },
|
|
+ "value": {
|
|
+ "map": {
|
|
+ "data": {
|
|
+ "set": [
|
|
+ [
|
|
+ "MacOs:Sierra",
|
|
+ 4
|
|
+ ],
|
|
+ [
|
|
+ "Windows:XP",
|
|
+ 3
|
|
+ ]
|
|
+ ]
|
|
+ },
|
|
+ "key": {
|
|
+ "osf": {
|
|
+ "key": "version"
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+]
|
|
diff --git a/tests/shell/testcases/maps/dumps/0012map_0.json-nft b/tests/shell/testcases/maps/dumps/0012map_0.json-nft
|
|
index 2892e11..6c88570 100644
|
|
--- a/tests/shell/testcases/maps/dumps/0012map_0.json-nft
|
|
+++ b/tests/shell/testcases/maps/dumps/0012map_0.json-nft
|
|
@@ -32,21 +32,21 @@
|
|
"map": "verdict",
|
|
"elem": [
|
|
[
|
|
- "lo",
|
|
+ "eth0",
|
|
{
|
|
- "accept": null
|
|
+ "drop": null
|
|
}
|
|
],
|
|
[
|
|
- "eth0",
|
|
+ "eth1",
|
|
{
|
|
"drop": null
|
|
}
|
|
],
|
|
[
|
|
- "eth1",
|
|
+ "lo",
|
|
{
|
|
- "drop": null
|
|
+ "accept": null
|
|
}
|
|
]
|
|
]
|
|
@@ -69,21 +69,21 @@
|
|
"data": {
|
|
"set": [
|
|
[
|
|
- "lo",
|
|
+ "eth0",
|
|
{
|
|
- "accept": null
|
|
+ "drop": null
|
|
}
|
|
],
|
|
[
|
|
- "eth0",
|
|
+ "eth1",
|
|
{
|
|
"drop": null
|
|
}
|
|
],
|
|
[
|
|
- "eth1",
|
|
+ "lo",
|
|
{
|
|
- "drop": null
|
|
+ "accept": null
|
|
}
|
|
]
|
|
]
|
|
diff --git a/tests/shell/testcases/maps/dumps/0012map_0.nft b/tests/shell/testcases/maps/dumps/0012map_0.nft
|
|
index e734fc1..0df329a 100644
|
|
--- a/tests/shell/testcases/maps/dumps/0012map_0.nft
|
|
+++ b/tests/shell/testcases/maps/dumps/0012map_0.nft
|
|
@@ -1,12 +1,12 @@
|
|
table ip x {
|
|
map z {
|
|
type ifname : verdict
|
|
- elements = { "lo" : accept,
|
|
- "eth0" : drop,
|
|
- "eth1" : drop }
|
|
+ elements = { "eth0" : drop,
|
|
+ "eth1" : drop,
|
|
+ "lo" : accept }
|
|
}
|
|
|
|
chain y {
|
|
- iifname vmap { "lo" : accept, "eth0" : drop, "eth1" : drop }
|
|
+ iifname vmap { "eth0" : drop, "eth1" : drop, "lo" : accept }
|
|
}
|
|
}
|
|
diff --git a/tests/shell/testcases/maps/dumps/named_ct_objects.json-nft b/tests/shell/testcases/maps/dumps/named_ct_objects.json-nft
|
|
index c0f270e..34c8798 100644
|
|
--- a/tests/shell/testcases/maps/dumps/named_ct_objects.json-nft
|
|
+++ b/tests/shell/testcases/maps/dumps/named_ct_objects.json-nft
|
|
@@ -195,8 +195,8 @@
|
|
},
|
|
"handle": 0,
|
|
"elem": [
|
|
- "sip",
|
|
- "ftp"
|
|
+ "ftp",
|
|
+ "sip"
|
|
]
|
|
}
|
|
},
|
|
diff --git a/tests/shell/testcases/maps/dumps/named_ct_objects.nft b/tests/shell/testcases/maps/dumps/named_ct_objects.nft
|
|
index 59f1893..dab683b 100644
|
|
--- a/tests/shell/testcases/maps/dumps/named_ct_objects.nft
|
|
+++ b/tests/shell/testcases/maps/dumps/named_ct_objects.nft
|
|
@@ -50,8 +50,8 @@ table inet t {
|
|
|
|
set helpname {
|
|
typeof ct helper
|
|
- elements = { "sip",
|
|
- "ftp" }
|
|
+ elements = { "ftp",
|
|
+ "sip" }
|
|
}
|
|
|
|
chain y {
|
|
diff --git a/tests/shell/testcases/sets/dumps/sets_with_ifnames.json-nft b/tests/shell/testcases/sets/dumps/sets_with_ifnames.json-nft
|
|
index ac42842..7b4849e 100644
|
|
--- a/tests/shell/testcases/sets/dumps/sets_with_ifnames.json-nft
|
|
+++ b/tests/shell/testcases/sets/dumps/sets_with_ifnames.json-nft
|
|
@@ -260,8 +260,8 @@
|
|
},
|
|
"right": {
|
|
"set": [
|
|
- "eth0",
|
|
- "abcdef0"
|
|
+ "abcdef0",
|
|
+ "eth0"
|
|
]
|
|
}
|
|
}
|
|
diff --git a/tests/shell/testcases/sets/dumps/sets_with_ifnames.nft b/tests/shell/testcases/sets/dumps/sets_with_ifnames.nft
|
|
index 77a8baf..8abca03 100644
|
|
--- a/tests/shell/testcases/sets/dumps/sets_with_ifnames.nft
|
|
+++ b/tests/shell/testcases/sets/dumps/sets_with_ifnames.nft
|
|
@@ -39,7 +39,7 @@ table inet testifsets {
|
|
chain v4icmp {
|
|
iifname @simple counter packets 0 bytes 0
|
|
iifname @simple_wild counter packets 0 bytes 0
|
|
- iifname { "eth0", "abcdef0" } counter packets 0 bytes 0
|
|
+ iifname { "abcdef0", "eth0" } counter packets 0 bytes 0
|
|
iifname { "abcdef*", "eth0" } counter packets 0 bytes 0
|
|
iifname vmap @map_wild
|
|
}
|