aboutsummaryrefslogtreecommitdiffstats
path: root/epan/dfilter
diff options
context:
space:
mode:
authorJoão Valverde <j@v6e.pt>2022-12-26 00:40:00 +0000
committerJoão Valverde <j@v6e.pt>2022-12-26 15:29:50 +0000
commit079ef9a165aef36f6cd46e400e548bfdb3bec8a2 (patch)
treebd22076c82009b3e43b064c2a89f3995c2bede4c /epan/dfilter
parent49ec151a7a220f52052caf755365d99211f83425 (diff)
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
Diffstat (limited to 'epan/dfilter')
-rw-r--r--epan/dfilter/semcheck.c27
1 files changed, 22 insertions, 5 deletions
diff --git a/epan/dfilter/semcheck.c b/epan/dfilter/semcheck.c
index 508d844fa7..96ea7e5a4f 100644
--- a/epan/dfilter/semcheck.c
+++ b/epan/dfilter/semcheck.c
@@ -920,10 +920,17 @@ check_relation_LHS_ARITHMETIC(dfwork_t *dfw, stnode_op_t st_op _U_,
static void
check_relation(dfwork_t *dfw, stnode_op_t st_op,
FtypeCanFunc can_func, gboolean allow_partial_value,
- stnode_t *st_node, stnode_t *st_arg1, stnode_t *st_arg2)
+ stnode_t *st_node, stnode_t *st_arg1, stnode_t *st_arg2,
+ int commute)
{
LOG_NODE(st_node);
+ if (commute < 0) {
+ /* We have already commuted the LHS with the RHS and still
+ cannot assign a field type to any side of the relation. */
+ FAIL(dfw, st_node, "Constant expression is invalid.");
+ }
+
switch (stnode_type_id(st_arg1)) {
case STTYPE_FIELD:
case STTYPE_REFERENCE:
@@ -942,9 +949,19 @@ check_relation(dfwork_t *dfw, stnode_op_t st_op,
check_relation_LHS_ARITHMETIC(dfw, st_op, can_func,
allow_partial_value, st_node, st_arg1, st_arg2);
break;
+ case STTYPE_LITERAL:
+ case STTYPE_STRING:
+ case STTYPE_CHARCONST:
+ /* We cannot semantically check a relation with literals on the LHS because we
+ don't have a type to assign them. Commute the LHS with the RHS and retry
+ the relation semantic check. */
+ check_relation(dfw, st_op, can_func,
+ allow_partial_value,st_node, st_arg2, st_arg1, --commute);
+ break;
default:
- FAIL(dfw, st_arg1, "Left side of \"%s\" expression must be a field or function, not %s.",
- stnode_todisplay(st_node), stnode_todisplay(st_arg1));
+ /* Should not happen. */
+ FAIL(dfw, st_arg1, "(FIXME) Syntax node type \"%s\" is invalid for relation \"%s\".",
+ stnode_type_name(st_arg1), stnode_todisplay(st_node));
}
}
@@ -1096,13 +1113,13 @@ check_test(dfwork_t *dfw, stnode_t *st_node)
case STNODE_OP_ANY_EQ:
case STNODE_OP_ALL_NE:
case STNODE_OP_ANY_NE:
- check_relation(dfw, st_op, ftype_can_eq, FALSE, st_node, st_arg1, st_arg2);
+ check_relation(dfw, st_op, ftype_can_eq, FALSE, st_node, st_arg1, st_arg2, 1);
break;
case STNODE_OP_GT:
case STNODE_OP_GE:
case STNODE_OP_LT:
case STNODE_OP_LE:
- check_relation(dfw, st_op, ftype_can_cmp, FALSE, st_node, st_arg1, st_arg2);
+ check_relation(dfw, st_op, ftype_can_cmp, FALSE, st_node, st_arg1, st_arg2, 1);
break;
case STNODE_OP_CONTAINS:
check_relation_contains(dfw, st_node, st_arg1, st_arg2);