]> git.ipfire.org Git - thirdparty/nftables.git/commitdiff
scanner: treat invalid octal strings as strings
authorJeremy Sowden <jeremy@azazel.net>
Fri, 16 Dec 2022 20:27:14 +0000 (20:27 +0000)
committerPablo Neira Ayuso <pablo@netfilter.org>
Thu, 22 Dec 2022 11:24:47 +0000 (12:24 +0100)
The action associated with the `{numberstring}` pattern, passes `yytext`
to `strtoull` with base 0:

errno = 0;
yylval->val = strtoull(yytext, NULL, 0);
if (errno != 0) {
yylval->string = xstrdup(yytext);
return STRING;
}
return NUM;

If `yytext` begins with '0', it will be parsed as octal.  However, this
has unexpected consequences if the token contains non-octal characters.
`09` will be parsed as 0; `0308` will be parsed as 24, because
`strtoull` and its siblings stop parsing as soon as they reach a
character in the input which is not valid for the base.

Replace the `{numberstring}` match with separate `{hexstring}` and
`{decstring}` matches.  For `{decstring}` set the base to 8 if the
leading character is '0', and handle an incompletely parsed token in
the same way as one that causes `strtoull` to set `errno`.

Thus, instead of:

  $ sudo nft -f - <<<'
    table x {
      chain y {
        ip saddr 0308 continue comment "parsed as 0.0.0.24/32"
      }
    }
  '
  $ sudo nft list chain x y
  table ip x {
    chain y {
      ip saddr 0.0.0.24 continue comment "parsed as 0.0.0.24/32"
    }
  }

We get:

  $ sudo ./src/nft -f - <<<'
  > table x {
  >   chain y {
  >     ip saddr 0308 continue comment "error"
  >   }
  > }
  > '
  /dev/stdin:4:14-17: Error: Could not resolve hostname: Name or service not known
      ip saddr 0308 continue comment "error"
               ^^^^

Add a test-case.

Link: https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=932880
Link: https://bugzilla.netfilter.org/show_bug.cgi?id=1363
Signed-off-by: Jeremy Sowden <jeremy@azazel.net>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
src/scanner.l
tests/shell/testcases/parsing/octal [new file with mode: 0755]

index 583c251171fd7551af9625cba661e9e5fe5fe75d..b4315b8f8860b036550bfc8e6c3a648541158840 100644 (file)
@@ -118,7 +118,6 @@ digit               [0-9]
 hexdigit       [0-9a-fA-F]
 decstring      {digit}+
 hexstring      0[xX]{hexdigit}+
-numberstring   ({decstring}|{hexstring})
 letter         [a-zA-Z]
 string         ({letter}|[_.])({letter}|{digit}|[/\-_\.])*
 quotedstring   \"[^"]*\"
@@ -819,9 +818,9 @@ addrstring  ({macaddr}|{ip4addr}|{ip6addr})
                                return STRING;
                        }
 
-{numberstring}         {
+{hexstring}            {
                                errno = 0;
-                               yylval->val = strtoull(yytext, NULL, 0);
+                               yylval->val = strtoull(yytext, NULL, 16);
                                if (errno != 0) {
                                        yylval->string = xstrdup(yytext);
                                        return STRING;
@@ -829,6 +828,19 @@ addrstring ({macaddr}|{ip4addr}|{ip6addr})
                                return NUM;
                        }
 
+{decstring}            {
+                               int base = yytext[0] == '0' ? 8 : 10;
+                               char *end;
+
+                               errno = 0;
+                               yylval->val = strtoull(yytext, &end, base);
+                               if (errno != 0 || *end) {
+                                       yylval->string = xstrdup(yytext);
+                                       return STRING;
+                               }
+                               return NUM;
+                       }
+
 {classid}/[ \t\n:\-},] {
                                yylval->string = xstrdup(yytext);
                                return STRING;
diff --git a/tests/shell/testcases/parsing/octal b/tests/shell/testcases/parsing/octal
new file mode 100755 (executable)
index 0000000..09ac26e
--- /dev/null
@@ -0,0 +1,13 @@
+#!/bin/bash
+
+$NFT add table t || exit 1
+$NFT add chain t c || exit 1
+$NFT add rule t c 'ip saddr 01 continue comment "0.0.0.1"' || exit 1
+$NFT add rule t c 'ip saddr 08 continue comment "error"' && {
+  echo "'"ip saddr 08"'" not rejected 1>&2
+  exit 1
+}
+$NFT delete table t || exit 1
+
+exit 0
+