diff options
author | Phil Sutter <phil@nwl.cc> | 2018-08-24 13:26:57 +0200 |
---|---|---|
committer | Pablo Neira Ayuso <pablo@netfilter.org> | 2018-10-04 02:11:17 +0200 |
commit | 14a9968a56f8b35138bab172aa7ce796f5d98e03 (patch) | |
tree | a901e04ad134ee30ec1fa9b9606e05e7c083898d | |
parent | a493147e60d350aca4197975281bf2ffe4cd1009 (diff) |
parser_bison: Fix for ECN keyword in LHS of relational
Of all possible TCP flags, 'ecn' is special since it is recognized by
lex as a keyword (there is a a field in IPv4 and IPv6 headers with the
same name). Therefore it is listed in keyword_expr, but that was
sufficient for RHS only. The following statement reproduces the issue:
| tcp flags & (syn | ecn) == (syn | ecn)
The solution is to limit binop expressions to accept an RHS expression
on RHS ("real" LHS expressions don't make much sense there anyway),
which then allows keyword_expr to occur there. In order to maintain the
recursive behaviour if braces are present, allow primary_rhs_expr to
consist of a basic_rhs_expr enclosed in braces. This in turn requires
for braced RHS part in relational_expr to be dropped, otherwise bison
complains about shift/reduce conflict.
Signed-off-by: Phil Sutter <phil@nwl.cc>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
-rw-r--r-- | src/parser_bison.y | 15 | ||||
-rw-r--r-- | tests/py/inet/tcp.t | 1 | ||||
-rw-r--r-- | tests/py/inet/tcp.t.json | 23 | ||||
-rw-r--r-- | tests/py/inet/tcp.t.json.output | 16 | ||||
-rw-r--r-- | tests/py/inet/tcp.t.payload | 8 |
5 files changed, 54 insertions, 9 deletions
diff --git a/src/parser_bison.y b/src/parser_bison.y index 831090b6..c9189e9c 100644 --- a/src/parser_bison.y +++ b/src/parser_bison.y @@ -3119,32 +3119,32 @@ osf_expr : OSF NAME ; shift_expr : primary_expr - | shift_expr LSHIFT primary_expr + | shift_expr LSHIFT primary_rhs_expr { $$ = binop_expr_alloc(&@$, OP_LSHIFT, $1, $3); } - | shift_expr RSHIFT primary_expr + | shift_expr RSHIFT primary_rhs_expr { $$ = binop_expr_alloc(&@$, OP_RSHIFT, $1, $3); } ; and_expr : shift_expr - | and_expr AMPERSAND shift_expr + | and_expr AMPERSAND shift_rhs_expr { $$ = binop_expr_alloc(&@$, OP_AND, $1, $3); } ; exclusive_or_expr : and_expr - | exclusive_or_expr CARET and_expr + | exclusive_or_expr CARET and_rhs_expr { $$ = binop_expr_alloc(&@$, OP_XOR, $1, $3); } ; inclusive_or_expr : exclusive_or_expr - | inclusive_or_expr '|' exclusive_or_expr + | inclusive_or_expr '|' exclusive_or_rhs_expr { $$ = binop_expr_alloc(&@$, OP_OR, $1, $3); } @@ -3473,10 +3473,6 @@ relational_expr : expr /* implicit */ rhs_expr { $$ = relational_expr_alloc(&@2, $2, $1, $3); } - | expr relational_op '(' rhs_expr ')' - { - $$ = relational_expr_alloc(&@2, $2, $1, $4); - } ; list_rhs_expr : basic_rhs_expr COMMA basic_rhs_expr @@ -3660,6 +3656,7 @@ primary_rhs_expr : symbol_expr { $$ = $1; } BYTEORDER_HOST_ENDIAN, sizeof(data) * BITS_PER_BYTE, &data); } + | '(' basic_rhs_expr ')' { $$ = $2; } ; relational_op : EQ { $$ = OP_EQ; } diff --git a/tests/py/inet/tcp.t b/tests/py/inet/tcp.t index d66ba843..f96e3634 100644 --- a/tests/py/inet/tcp.t +++ b/tests/py/inet/tcp.t @@ -78,6 +78,7 @@ tcp flags cwr;ok tcp flags != cwr;ok tcp flags == syn;ok tcp flags & (syn|fin) == (syn|fin);ok;tcp flags & (fin | syn) == fin | syn +tcp flags & (fin | syn | rst | psh | ack | urg | ecn | cwr) == fin | syn | rst | psh | ack | urg | ecn | cwr;ok;tcp flags == 0xff tcp window 22222;ok tcp window 22;ok diff --git a/tests/py/inet/tcp.t.json b/tests/py/inet/tcp.t.json index 5744e594..babe5920 100644 --- a/tests/py/inet/tcp.t.json +++ b/tests/py/inet/tcp.t.json @@ -1101,6 +1101,29 @@ } ] +# tcp flags & (fin | syn | rst | psh | ack | urg | ecn | cwr) == fin | syn | rst | psh | ack | urg | ecn | cwr +[ + { + "match": { + "left": { + "&": [ + { + "payload": { + "field": "flags", + "protocol": "tcp" + } + }, + { + "|": [ "fin", { "|": [ "syn", { "|": [ "rst", { "|": [ "psh", { "|": [ "ack", { "|": [ "urg", { "|": [ "ecn", "cwr" ] } ] } ] } ] } ] } ] } ] + } + ] + }, + "op": "==", + "right": { "|": [ "fin", { "|": [ "syn", { "|": [ "rst", { "|": [ "psh", { "|": [ "ack", { "|": [ "urg", { "|": [ "ecn", "cwr" ] } ] } ] } ] } ] } ] } ] } + } + } +] + # tcp window 22222 [ { diff --git a/tests/py/inet/tcp.t.json.output b/tests/py/inet/tcp.t.json.output index 50282ec5..143490f7 100644 --- a/tests/py/inet/tcp.t.json.output +++ b/tests/py/inet/tcp.t.json.output @@ -139,3 +139,19 @@ } ] +# tcp flags & (fin | syn | rst | psh | ack | urg | ecn | cwr) == fin | syn | rst | psh | ack | urg | ecn | cwr +[ + { + "match": { + "left": { + "payload": { + "field": "flags", + "protocol": "tcp" + } + }, + "op": "==", + "right": 255 + } + } +] + diff --git a/tests/py/inet/tcp.t.payload b/tests/py/inet/tcp.t.payload index 09538aed..2390a24e 100644 --- a/tests/py/inet/tcp.t.payload +++ b/tests/py/inet/tcp.t.payload @@ -436,6 +436,14 @@ inet test-inet input [ bitwise reg 1 = (reg=1 & 0x00000003 ) ^ 0x00000000 ] [ cmp eq reg 1 0x00000003 ] +# tcp flags & (fin | syn | rst | psh | ack | urg | ecn | cwr) == fin | syn | rst | psh | ack | urg | ecn | cwr +inet test-inet input + [ meta load l4proto => reg 1 ] + [ cmp eq reg 1 0x00000006 ] + [ payload load 1b @ transport header + 13 => reg 1 ] + [ bitwise reg 1 = (reg=1 & 0x000000ff ) ^ 0x00000000 ] + [ cmp eq reg 1 0x000000ff ] + # tcp window 22222 inet test-inet input [ meta load l4proto => reg 1 ] |