Commit graph

747 commits

Author SHA1 Message Date
João Valverde
a2b23f5a09 dfilter: Fix DFVM function debug output
Add a NULL check. Add missing newlines.

Remove explicit display of number of input arguments.
2023-01-06 02:52:04 +00:00
João Valverde
df30299aff dftest: Add -h and improve output format
Experiment with removing the type from the instruction output.

This information is also available with the -s option flag.

Rename -t to -s.
2023-01-06 01:43:42 +00:00
João Valverde
522c74b734 dftest: More CLI options and improve output format 2023-01-05 20:26:42 +00:00
João Valverde
fd709a6af3 dfilter: Indent DFVM program using spaces 2023-01-05 20:26:42 +00:00
João Valverde
e990b25ea2 dfilter: Remove semcheck arithmetic commute argument
No one is using this so I'd like to explore other
options first to handle constants in arithmetic
expressions that lack type information.

Reverts 3ddb017a88.
2023-01-03 12:46:13 +00:00
João Valverde
f37c7c4062 dfilter: Tweak representation for length-1 byte array
Make dfilter byte representation always use ':' for consistency.

Make 1 byte be represented as "XX:" with the colon suffix to
make it nonambiguous that is is a byte and not other type,
like a protocol.

The difference is can be seen in the following programs. In the
before representation it is not obvious at all that the second
"fc" value is a literal bytes value and not the value of the
protocol "fc", although it can be inferred from the lack of
a READ_TREE instruction. In the After we know that "fc:" must
be bytes and not a protocol.

Note that a leading colon is a syntactical expedient to say
"this value with any type is a literal value and not a protocol
field." A terminating colon is just a part of the dfilter
literal bytes syntax.

Before:

Filter: fc == :fc

Syntax tree:
 0 TEST_ANY_EQ:
   1 FIELD(fc <FT_PROTOCOL>)
   1 FVALUE(fc <FT_PROTOCOL>)

Instructions:
00000 READ_TREE		fc <FT_PROTOCOL> -> reg#0
00001 IF_FALSE_GOTO	3
00002 ANY_EQ		reg#0 == fc <FT_PROTOCOL>

After:

Filter: fc == :fc

Syntax tree:
 0 TEST_ANY_EQ:
   1 FIELD(fc <FT_PROTOCOL>)
   1 FVALUE(fc: <FT_PROTOCOL>)

Instructions:
00000 READ_TREE		fc <FT_PROTOCOL> -> reg#0
00001 IF_FALSE_GOTO	3
00002 ANY_EQ		reg#0 == fc: <FT_PROTOCOL>
2023-01-02 02:54:38 +00:00
João Valverde
c762d8492b dfilter: Improve debug format 2023-01-02 02:53:21 +00:00
João Valverde
f5bfe89785 dfilter: Replace global variable 2023-01-02 01:19:51 +00:00
João Valverde
5d8f495233 dfilter: Minor flex clean up
Replace flex prefix to improve readability.

Remove two no-longer-needed workarounds to suppress warnings.
2023-01-02 01:19:26 +00:00
João Valverde
f2218ae5f0 Lemon: Update code and remove cruft
Remove some unused historical files.

Aggressively disable warnings to keep the lemon source
pristine and avoid the maintenance burden for lemon itself.

Lemon has its own lax policy for warnings that doesn't match our
own and they won't accept external patches to remove the
warnings, so just ignore them. Lemon is just executed to generate
code for the Wireshark build and the minor code issues it has
have no influence at runtime.

For lemon generated code we selectively disable some linting
warnings.

Remove patches for lemon and lempar, they are no longer required
with these changes to silence warnings.
2023-01-01 18:18:06 +00:00
João Valverde
6bdc85e37f dfilter: Reject constant expressions
Constant logical expressions are tautologies and almost certainly
user error. Reject them as invalid.

Most of them were already rejected with insufficient type information
but some corner cases were still valid.

Before:

    Filter: ${frame.number} == 3

    Syntax tree:
     0 TEST_ANY_EQ:
       1 REFERENCE(frame.number <FT_UINT32>)
       1 FVALUE(3 <FT_UINT32>)

    Instructions:
    00000 READ_REFERENCE	${frame.number <FT_UINT32>} -> reg#0
    00001 IF_FALSE_GOTO	3
    00002 ANY_EQ		reg#0 == 3 <FT_UINT32>
    00003 RETURN

After:

    Filter: ${frame.number} == 3
    dftest: Constant expression is invalid.
    	${frame.number} == 3
    	^~~~~~~~~~~~~~~~~~~~
2022-12-30 18:46:22 +00:00
João Valverde
a17fb20550 dfilter: Remove commute argument from semantic check
Take a more conservative, less flexible, maybe more elegant,
approach to type inference for now.
2022-12-30 18:46:22 +00:00
João Valverde
2ff6139307 dfilter: Add a check_nonzero() function
Small refactoring with no functional difference.
2022-12-30 18:46:22 +00:00
João Valverde
d3d06c2552 dftest: Add debug command-line options 2022-12-30 13:42:26 +00:00
João Valverde
1400d92724 dfilter: Add compilation warning for ambiguous syntax
$ dfilter 'frame contains fc'
    Filter: frame contains fc

    Warning: Interpreting "fc" as "Fibre Channel". Consider writing :fc or .fc.
    (...)
2022-12-29 23:48:56 +00:00
João Valverde
af22c743bd dfilter: Refactor error location for expressions
Underline the whole expression for errors, not just the token.
Implement it for all expressions.
2022-12-29 18:28:54 +00:00
João Valverde
77ef21f86e dfilter: Replace unparsed lexical type and simplify grammar
Remove unparsed lexical type and replace it with identifier
and constant. This separation is still necessary to differentiate
names (fields and function) from literals that look like names
but it has some advantages to do it at the lexical level.

The main advantage is a much cleaner and simplified grammar,
because we only have a single token type for field names, without
any loss of generality (the same name is valid for fields and
function names for example).

The CONSTANT token type is necessary to be different from literal
to provide errors for function rules.
2022-12-29 18:28:54 +00:00
João Valverde
bdd00edac8 dfilter: Rename grammar rules 2022-12-29 18:28:54 +00:00
João Valverde
95f705dd8b dfilter: Improve error location for functions
Underline the whole expression if the error is for the function.

Before:

    Filter: frame.number == abs(1, 2)
    dftest: Function abs can only accept 1 arguments.
    	frame.number == abs(1, 2)
    	                ^~~
After:

    Filter: frame.number == abs(1, 2)
    dftest: Function abs can only accept 1 arguments.
    	frame.number == abs(1, 2)
    	                ^~~~~~~~~
2022-12-28 20:26:00 +00:00
João Valverde
6c1ee11172 dfilter: Allow compatible types to be compared in min/max 2022-12-27 21:09:04 +00:00
João Valverde
e85f8d4cf1 dfilter: Do not jump when generating function arguments
Instead of "jumping" with length zero to the next sequential
instruction skip generating the no-op jump instruction entirely.
2022-12-27 21:09:04 +00:00
João Valverde
f6a02a1e4a dfilter: Preserve function argument order when printing
Instead of printing back to front (from the top of the stack
print them front to back as a user would type them.
2022-12-27 21:09:04 +00:00
João Valverde
b19bed43d1 dfilter: Allow constants as the first or only argument to min/max
The strategy here is to delay resolving literals to values until
we have looked at the entire argument list.

Also we will try to commute the relation in a comparison if
we do not have a type for the return value of the function,
like any other constant.

Before:

    Filter: max(1,_ws.ftypes.int8) == 1
    dftest: Argument '1' is not valid for max()
    	max(1,_ws.ftypes.int8) == 1
    	    ^

After:

    Filter: max(1,_ws.ftypes.int8) == 1

    Syntax tree:
     0 TEST_ANY_EQ:
       1 FUNCTION(max#2):
         2 FVALUE(1 <FT_INT8>)
         2 FIELD(_ws.ftypes.int8 <FT_INT8>)
       1 FVALUE(1 <FT_INT8>)

    Instructions:
    00000 STACK_PUSH	1 <FT_INT8>
    00001 READ_TREE		_ws.ftypes.int8 <FT_INT8> -> reg#1
    00002 IF_FALSE_GOTO	3
    00003 STACK_PUSH	reg#1
    00004 CALL_FUNCTION	max(reg#1, 1 <FT_INT8>) -> reg#0
    00005 STACK_POP	2
    00006 IF_FALSE_GOTO	8
    00007 ANY_EQ		reg#0 == 1 <FT_INT8>
    00008 RETURN
2022-12-27 02:21:06 +00:00
João Valverde
6399f724d9 dfilter: Fix crash with min/max literal argument
Filter: max(1,_ws.ftypes.int8) == 1
     ** (dftest:64938) 01:43:25.950180 [DFilter ERROR] epan/dfilter/sttype-field.c:117 -- sttype_field_ftenum(): Magic num is 0x5cf30031, but should be 0xfc2002cf
2022-12-27 01:54:57 +00:00
João Valverde
540b71d738 dfilter: Fix crash with a constant arithmetic expression 2022-12-26 23:55:27 +00:00
João Valverde
3ddb017a88 dfilter: Allow arithmetic expression to commute
Allow an arithmetic expression like 1 + some.field. If we
cannot assign a type to the LHS commute the terms and
try again.

Before:

    Filter: _ws.ftypes.int32 + 1 == 10

    Syntax tree:
     0 TEST_ANY_EQ:
       1 OP_ADD:
         2 FIELD(_ws.ftypes.int32 <FT_INT32>)
         2 FVALUE(1 <FT_INT32>)
       1 FVALUE(10 <FT_INT32>)

    Instructions:
    00000 READ_TREE		_ws.ftypes.int32 <FT_INT32> -> reg#0
    00001 IF_FALSE_GOTO	4
    00002 ADD		reg#0 + 1 <FT_INT32> -> reg#1
    00003 ANY_EQ		reg#1 == 10 <FT_INT32>
    00004 RETURN

    Filter: 1 + _ws.ftypes.int32 == 10
    dftest: Constant arithmetic expression on the LHS is invalid.
    	1 + _ws.ftypes.int32 == 10
    	^

After:

    Filter: _ws.ftypes.int32 + 1 == 10

    Syntax tree:
     0 TEST_ANY_EQ:
       1 OP_ADD:
         2 FIELD(_ws.ftypes.int32 <FT_INT32>)
         2 FVALUE(1 <FT_INT32>)
       1 FVALUE(10 <FT_INT32>)

    Instructions:
    00000 READ_TREE		_ws.ftypes.int32 <FT_INT32> -> reg#0
    00001 IF_FALSE_GOTO	4
    00002 ADD		reg#0 + 1 <FT_INT32> -> reg#1
    00003 ANY_EQ		reg#1 == 10 <FT_INT32>
    00004 RETURN

    Filter: 1 + _ws.ftypes.int32 == 10

    Syntax tree:
     0 TEST_ANY_EQ:
       1 OP_ADD:
         2 FVALUE(1 <FT_INT32>)
         2 FIELD(_ws.ftypes.int32 <FT_INT32>)
       1 FVALUE(10 <FT_INT32>)

    Instructions:
    00000 READ_TREE		_ws.ftypes.int32 <FT_INT32> -> reg#0
    00001 IF_FALSE_GOTO	4
    00002 ADD		1 <FT_INT32> + reg#0 -> reg#1
    00003 ANY_EQ		reg#1 == 10 <FT_INT32>
    00004 RETURN
2022-12-26 20:50:44 +00:00
João Valverde
c37552c43c dfilter: Fix an assertion macro 2022-12-26 20:22:21 +00:00
João Valverde
1d544c2077 dfilter: Fix grammar memory leak 2022-12-26 18:48:54 +00:00
João Valverde
079ef9a165 dfilter: Allow comparison relation to commute
Comparison relations should be allowed to commute but they can not
because we need type information to resolve literals to fvalues. For
that reason an expression like "1 == some.field"  is invalid. Solve
that by commuting the relation if the first try did not succeed in
assigning a type to the LHS.

After the second try give up, that means we have a relation with
constants on both sides and that is not semantically valid.

Other relations like "matches" and "contains" are not symmetric and
should not commute anyway.

Before:

    Filter: _ws.ftypes.int32 == 10

    Syntax tree:
     0 TEST_ANY_EQ:
       1 FIELD(_ws.ftypes.int32 <FT_INT32>)
       1 FVALUE(10 <FT_INT32>)

    Instructions:
    00000 READ_TREE		_ws.ftypes.int32 <FT_INT32> -> reg#0
    00001 IF_FALSE_GOTO	3
    00002 ANY_EQ		reg#0 == 10 <FT_INT32>
    00003 RETURN

    Filter: 10 == _ws.ftypes.int32
    dftest: Left side of "==" expression must be a field or function, not 10.
    	10 == _ws.ftypes.int32
    	^~

After:

    Filter: _ws.ftypes.int32 == 10

    Syntax tree:
     0 TEST_ANY_EQ:
       1 FIELD(_ws.ftypes.int32 <FT_INT32>)
       1 FVALUE(10 <FT_INT32>)

    Instructions:
    00000 READ_TREE		_ws.ftypes.int32 <FT_INT32> -> reg#0
    00001 IF_FALSE_GOTO	3
    00002 ANY_EQ		reg#0 == 10 <FT_INT32>
    00003 RETURN

    Filter: 10 == _ws.ftypes.int32

    Syntax tree:
     0 TEST_ANY_EQ:
       1 FVALUE(10 <FT_INT32>)
       1 FIELD(_ws.ftypes.int32 <FT_INT32>)

    Instructions:
    00000 READ_TREE		_ws.ftypes.int32 <FT_INT32> -> reg#0
    00001 IF_FALSE_GOTO	3
    00002 ANY_EQ		10 <FT_INT32> == reg#0
    00003 RETURN
2022-12-26 15:29:50 +00:00
João Valverde
49ec151a7a dfilter: Allow the first DFVM argument to be an fvalue
Do not assert that arg1 must be a register, allow passing constants
as the first argument to allow the arguments to commute freely.
2022-12-26 12:40:23 +00:00
João Valverde
596e0b41d1 dfilter: Change two scanner patterns to camel case 2022-12-26 07:27:40 +00:00
João Valverde
7742b22be4 dfilter: Minor fixups 2022-12-26 04:24:55 +00:00
João Valverde
eda80ed336 dfilter: Improve error location for parenthesized expressions 2022-12-26 03:20:30 +00:00
João Valverde
816005fc23 dfilter: Reformat grammar code
Use a consistent style for grammar rules.

Remove a comment that is too generic. The current code should
conform to how Python operates and does not need additional error
checking.
2022-12-24 18:25:11 +00:00
João Valverde
b9a5009cb2 dfilter: Clean up scanner code
Clean up some issues flagged by a linter.

Remove hyphen from pattern names and remove an unused start condition.
2022-12-24 15:51:36 +00:00
João Valverde
44511c318d dfilter: Improve error location for expressions
Try to underline the whole expression instead of the
token.
2022-12-23 18:23:14 +00:00
João Valverde
3938b406fb dfilter: Refactor error location tracking
Remove duplicate location struct by adding a new header.

Pass around a structure instead of a pointer.
2022-12-23 18:23:06 +00:00
João Valverde
4e1211de90 dfilter: Add support for negation of arithmetic expressions 2022-12-22 23:51:16 +00:00
João Valverde
ba1a85d381 dfilter: Improve arithmetic error messages 2022-12-22 10:13:30 +00:00
João Valverde
263bda375c dfilter: Check if type supports unary minus
Fix crash for types that do not support unary minus.

Fixes #18750.
2022-12-21 14:43:39 +00:00
João Valverde
32f88ad22c wmem: Remove strbuf max size parameter
This parameter was introduced as a safeguard for bugs
that generate an unbounded string but its utility for
that purpose is doubtful and the way it is being used
creates problems with invalid truncation of UTF-8
strings.

Rename wmem_strbuf_sized_new() with a better name.
2022-12-03 01:54:52 +00:00
João Valverde
967a3c3df9 Qt: Check field autocomplete for syntactical validity
Currently the autocompletion engine always suggests a protocol
field completion, even in places where it isn't syntactically
valid.

Fix that by compiling the preamble to the token under the cursor
and checking the returned error. If it is DF_ERROR_UNEXPECTED_END
that indicates a field or literal value was expected. Otherwise
a field replacement is not valid in this position.

Fixes #12811.
2022-12-01 22:50:09 +00:00
João Valverde
b116ccd6d5 dfilter: Replace compile booleans arguments with a bit flag 2022-11-30 17:36:17 +00:00
João Valverde
84e75be5c6 dfilter: Add optimization flag
When we are just testing code to see if it compiles performing
optimizations is wasteful. Add an option to disable them.
2022-11-30 17:36:17 +00:00
João Valverde
93814ef740 dfilter: Always set error pointer in case of failure 2022-11-30 15:00:34 +00:00
João Valverde
a0d77e9329 dfilter: Return an error object instead of string
Return an struct containing error information. This simplifies
the interface to more easily provide richer diagnostics in the future.

Add an error code besides a human-readable error string to allow
checking programmatically for errors in a robust manner. Currently
there is only a generic error code, it is expected to increase
in the future.

Move error location information to the struct. Change callers and
implementation to use the new interface.
2022-11-28 15:46:44 +00:00
João Valverde
79c3a77752 Add macros to control lemon diagnostics
Rename flex macros using parenthesis (mostly a style issue):

DIAG_OFF_FLEX -> DIAG_OFF_FLEX()
DIAG_ON_FLEX  -> DIAG_ON_FLEX()

Use the same kind of construct with lemon generated code using
DIAG_OFF_LEMON() and DIAG_ON_LEMON(). Use %include and %code
directives to enforce the desired order with generated code
in the middle in between pragmas.

Fix a clang-specific pragma to use DIAG_OFF_CLANG().

DIAG_OFF(unreachable-code) -> DIAG_OFF_CLANG(unreachable-code).

Apparently GCC is ignoring the -Wunreachable flag, that's why
it did not trigger an unknown pragma warning. From [1}:

  The -Wunreachable-code has been removed, because it was unstable: it
  relied on the optimizer, and so different versions of gcc would warn
  about different code.  The compiler still accepts and ignores the
  command line option so that existing Makefiles are not broken.  In some
  future release the option will be removed entirely. - Ian

[1] https://gcc.gnu.org/legacy-ml/gcc-help/2011-05/msg00360.html
2022-11-20 10:11:27 +00:00
João Valverde
2443df7318 Disable another -Wunreachable lemon warning 2022-11-17 11:21:41 +00:00
Peter Wu
df478a365d dfilter: treat carriage returns as whitespace
Fixes #18595
2022-11-07 01:00:50 +00:00
João Valverde
4c2d0f16d4 dfilter: Improve representation of raw field references
Instead of using the abstract type "<RAW>", which might be confusing,
show FT_BYTES, but display the representation with the "@" operator,
so it's not even more confusing in error messages why a field might
flip-flop types.

Refactor the field tostr() function and some other clean ups.

Before:
```
Filter: _ws.ftypes.string ==${@frame.len}
dftest: _ws.ftypes.string and frame.len <RAW> are not of compatible types.
	_ws.ftypes.string ==${@frame.len}
	                       ^~~~~~~~~
```

After:
```
Filter: _ws.ftypes.string ==${@frame.len}
dftest: _ws.ftypes.string <FT_STRING> and @frame.len <FT_BYTES> are not of compatible types.
	_ws.ftypes.string ==${@frame.len}
	                       ^~~~~~~~~
```
2022-10-31 21:02:39 +00:00