diff options
author | João Valverde <j@v6e.pt> | 2022-02-22 21:55:05 +0000 |
---|---|---|
committer | A Wireshark GitLab Utility <gerald+gitlab-utility@wireshark.org> | 2022-03-05 11:10:54 +0000 |
commit | 6d520addd1f147bffca0402e05d1eb2152f66cd2 (patch) | |
tree | 73696f00fe14690e835ca89838a463996b38f24c /test | |
parent | 64d95a28086f2939072d68fb78676da6e8748d62 (diff) |
dfilter: Add special syntax for literals and names
The syntax for protocols and some literals like numbers
and bytes/addresses can be ambiguous. Some protocols can
be parsed as a literal, for example the protocol "fc"
(Fibre Channel) can be parsed as 0xFC.
If a numeric protocol is registered that will also take
precedence over any literal, according to the current
rules, thereby breaking numerical comparisons to that
number. The same for an hypothetical protocol named "true",
etc.
To allow the user to disambiguate this meaning introduce
new syntax.
Any value prefixed with ':' or enclosed in <,> will be treated
as a literal value only. The value :fc or <fc> will always
mean 0xFC, under any context. Never a protocol whose filter
name is "fc".
Likewise any value prefixed with a dot will always be parsed
as an identifier (protocol or protocol field) in the language.
Never any literal value parsed from the token "fc".
This allows the user to be explicit about the meaning,
and between the two explicit methods plus the ambiguous one
it doesn't completely break any one meaning.
The difference can be seen in the following two programs:
Filter: frame == fc
Constants:
Instructions:
00000 READ_TREE frame -> reg#0
00001 IF-FALSE-GOTO 5
00002 READ_TREE fc -> reg#1
00003 IF-FALSE-GOTO 5
00004 ANY_EQ reg#0 == reg#1
00005 RETURN
--------
Filter: frame == :fc
Constants:
00000 PUT_FVALUE fc <FT_PROTOCOL> -> reg#1
Instructions:
00000 READ_TREE frame -> reg#0
00001 IF-FALSE-GOTO 3
00002 ANY_EQ reg#0 == reg#1
00003 RETURN
The filter "frame == fc" is the same as "filter == .fc",
according to the current heuristic, except the first form
will try to parse it as a literal if the name does not
correspond to any registered protocol.
By treating a leading dot as a name in the language we
necessarily disallow writing floats with a leading dot. We
will also disallow writing with an ending dot when using
unparsed values. This is a backward incompatibility but has
the happy side effect of making the expression {1...2}
unambiguous.
This could either mean "1 .. .2" or "1. .. 2". If we require
a leading and ending digit then the meaning is clear:
1.0..0.2 -> 1.0 .. 0.2
Fixes #17731.
Diffstat (limited to 'test')
-rw-r--r-- | test/suite_dfilter/group_membership.py | 6 | ||||
-rw-r--r-- | test/suite_dfilter/group_syntax.py | 12 |
2 files changed, 16 insertions, 2 deletions
diff --git a/test/suite_dfilter/group_membership.py b/test/suite_dfilter/group_membership.py index 4f9b315f0d..20072e2db1 100644 --- a/test/suite_dfilter/group_membership.py +++ b/test/suite_dfilter/group_membership.py @@ -72,10 +72,12 @@ class case_membership(unittest.TestCase): dfilter = 'ip.addr in { 10.0.0.5 .. 10.0.0.9 , 10.0.0.1..10.0.0.1 }' checkDFilterCount(dfilter, 1) - def test_membership_9_range_weird_float(self, checkDFilterCount): + def test_membership_9_range_invalid_float(self, checkDFilterFail): # expression should be parsed as "0.1 .. .7" + # .7 is the identifier (protocol) named "7" dfilter = 'frame.time_delta in {0.1...7}' - checkDFilterCount(dfilter, 0) + error = 'not a valid protocol or protocol field' + checkDFilterFail(dfilter, error) def test_membership_10_bad_lhs_number(self, checkDFilterFail): dfilter = '123 in {ip}' diff --git a/test/suite_dfilter/group_syntax.py b/test/suite_dfilter/group_syntax.py index 171cd330a5..b5c6236931 100644 --- a/test/suite_dfilter/group_syntax.py +++ b/test/suite_dfilter/group_syntax.py @@ -135,3 +135,15 @@ class case_equality(unittest.TestCase): def test_all_ne_1(self, checkDFilterCount): dfilter = "udp.port != 5060" checkDFilterCount(dfilter, 1) + + def test_root_1(self, checkDFilterCount): + dfilter = "udp.srcport == .udp.dstport" + checkDFilterCount(dfilter, 2) + + def test_literal_1(self, checkDFilterCount): + dfilter = "udp.port == :5070" + checkDFilterCount(dfilter, 3) + + def test_literal_2(self, checkDFilterCount): + dfilter = "udp contains <ce:13>" + checkDFilterCount(dfilter, 1) |