dfilter: Refactor some scanner patterns

Revert to the original design of having a single pattern to catch
everything as unparsed and also try to be less hackish and fragile
parsing "..".

Strings like "80..90" are tricky because it can be parsed as
INTEGER DOTDOT INTEGER or FLOAT FLOAT.
This commit is contained in:
João Valverde 2021-10-29 11:43:23 +01:00
parent d95935d969
commit e876d499d1
2 changed files with 31 additions and 17 deletions

View File

@ -352,26 +352,28 @@ static int set_lval_str(int token, const char *token_value);
/* None of the patterns below can match ".." anywhere in the token string. */
[[:digit:]]{1,3}\.[[:digit:]]{1,3}\.[[:digit:]]{1,3}\.[[:digit:]]{1,3}(\/[[:digit:]]+)* {
/* IPv4 CIDR */
return set_lval_str(TOKEN_UNPARSED, yytext);
}
[[:xdigit:]:]+(\/[[:digit:]]+)* {
/* IPv6 CIDR or bytes-: or integer... */
return set_lval_str(TOKEN_UNPARSED, yytext);
}
[-+[:alnum:]_:./]+ {
char *s, *value;
([.][-+[:alnum:]_:]+)+[.]{0,2} |
[-+[:alnum:]_:]+([.][-+[:alnum:]_:]+)*[.]{0,2} {
/* Hack (but lesser) to make sure that ".." is interpreted as a token on its own. */
if ((s = strstr(yytext, "..")) != NULL) {
/* If it starts with ".." it is its own token. */
if (yytext[0] == '.' && yytext[1] == '.') {
yyless(2);
df_lval->value = g_strdup("..");
return TOKEN_DOTDOT;
}
/* Trailing dot is allowed for floats, but make sure that trailing ".."
* is interpreted as a token on its own. */
if (strstr(yytext, "..")) {
yyless(yyleng-2);
/* Match only the prefix before "..". */
*s = '\0';
value = g_strdup(yytext);
*s = '.'; /* Restore */
yyless(strlen(value));
df_lval->value = value;
return TOKEN_UNPARSED;
}
/* It is a field name or some other value (float, bytes, ...). */
/* It is a variable or a literal value (CIDR, bytes, number, ...). */
return set_lval_str(TOKEN_UNPARSED, yytext);
}

View File

@ -31,10 +31,22 @@ class case_membership(unittest.TestCase):
dfilter = 'tcp.port in { 80 , 3267 }'
checkDFilterCount(dfilter, 1)
def test_membership_2_range_match(self, checkDFilterCount):
def test_membership_range_match_1(self, checkDFilterCount):
dfilter = 'tcp.port in {80..81}'
checkDFilterCount(dfilter, 1)
def test_membership_range_match_2(self, checkDFilterCount):
dfilter = 'tcp.port in {80 ..81}'
checkDFilterCount(dfilter, 1)
def test_membership_range_match_3(self, checkDFilterCount):
dfilter = 'tcp.port in {80.. 81}'
checkDFilterCount(dfilter, 1)
def test_membership_range_match_4(self, checkDFilterCount):
dfilter = 'tcp.port in {80 .. 81}'
checkDFilterCount(dfilter, 1)
def test_membership_3_range_no_match(self, checkDFilterCount):
dfilter = 'tcp.dstport in {1 .. 79, 81 .. 65535}'
checkDFilterCount(dfilter, 0)