]> git.ipfire.org Git - thirdparty/nftables.git/commitdiff
netlink_delinearize: Fix for escaped asterisk strings on Big Endian
authorPhil Sutter <phil@nwl.cc>
Wed, 10 Mar 2021 18:46:08 +0000 (19:46 +0100)
committerPhil Sutter <phil@nwl.cc>
Tue, 30 Nov 2021 13:57:46 +0000 (14:57 +0100)
The original nul-char detection was not functional on Big Endian.
Instead, go a simpler route by exporting the string and working on the
exported data to check for a nul-char and escape a trailing asterisk if
present. With the data export already happening in the caller, fold
escaped_string_wildcard_expr_alloc() into it as well.

Fixes: b851ba4731d9f ("src: add interface wildcard matching")
Signed-off-by: Phil Sutter <phil@nwl.cc>
src/netlink_delinearize.c

index 0c2b439eac6fbafded417e89c486b229f01ab974..db58e8c386c006683cf642d7f7ecca8d1681afb8 100644 (file)
@@ -2422,56 +2422,33 @@ static struct expr *string_wildcard_expr_alloc(struct location *loc,
                                   expr->len + BITS_PER_BYTE, data);
 }
 
-static void escaped_string_wildcard_expr_alloc(struct expr **exprp,
-                                              unsigned int len)
-{
-       struct expr *expr = *exprp, *tmp;
-       char data[len + 3];
-       int pos;
-
-       mpz_export_data(data, expr->value, BYTEORDER_HOST_ENDIAN, len);
-       pos = div_round_up(len, BITS_PER_BYTE);
-       data[pos - 1] = '\\';
-       data[pos] = '*';
-
-       tmp = constant_expr_alloc(&expr->location, expr->dtype,
-                                 BYTEORDER_HOST_ENDIAN,
-                                 expr->len + BITS_PER_BYTE, data);
-       expr_free(expr);
-       *exprp = tmp;
-}
-
 /* This calculates the string length and checks if it is nul-terminated, this
  * function is quite a hack :)
  */
 static bool __expr_postprocess_string(struct expr **exprp)
 {
        struct expr *expr = *exprp;
-       unsigned int len = expr->len;
-       bool nulterminated = false;
-       mpz_t tmp;
-
-       mpz_init(tmp);
-       while (len >= BITS_PER_BYTE) {
-               mpz_bitmask(tmp, BITS_PER_BYTE);
-               mpz_lshift_ui(tmp, len - BITS_PER_BYTE);
-               mpz_and(tmp, tmp, expr->value);
-               if (mpz_cmp_ui(tmp, 0))
-                       break;
-               else
-                       nulterminated = true;
-               len -= BITS_PER_BYTE;
-       }
+       unsigned int len = div_round_up(expr->len, BITS_PER_BYTE);
+       char data[len + 1];
 
-       mpz_rshift_ui(tmp, len - BITS_PER_BYTE);
+       mpz_export_data(data, expr->value, BYTEORDER_HOST_ENDIAN, len);
 
-       if (nulterminated &&
-           mpz_cmp_ui(tmp, '*') == 0)
-               escaped_string_wildcard_expr_alloc(exprp, len);
+       if (data[len - 1] != '\0')
+               return false;
 
-       mpz_clear(tmp);
+       len = strlen(data);
+       if (len && data[len - 1] == '*') {
+               data[len - 1]   = '\\';
+               data[len]       = '*';
+               data[len + 1]   = '\0';
+               expr = constant_expr_alloc(&expr->location, expr->dtype,
+                                          BYTEORDER_HOST_ENDIAN,
+                                          (len + 2) * BITS_PER_BYTE, data);
+               expr_free(*exprp);
+               *exprp = expr;
+       }
 
-       return nulterminated;
+       return true;
 }
 
 static struct expr *expr_postprocess_string(struct expr *expr)