From f0f9cd656c005ba9a17cd3cef5769c285064b202 Mon Sep 17 00:00:00 2001 From: Jeremy Sowden Date: Fri, 16 Dec 2022 20:27:14 +0000 Subject: scanner: treat invalid octal strings as strings 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 Signed-off-by: Pablo Neira Ayuso --- src/scanner.l | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) (limited to 'src/scanner.l') diff --git a/src/scanner.l b/src/scanner.l index 583c2511..b4315b8f 100644 --- a/src/scanner.l +++ b/src/scanner.l @@ -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; -- cgit v1.2.3