aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJoão Valverde <j@v6e.pt>2023-07-24 23:12:08 +0100
committerJoão Valverde <j@v6e.pt>2023-07-25 12:17:25 +0000
commitca8976020ff82f802ae8c3ab72ea4491f8c6dc1e (patch)
treeef18eea1c5e7fa4ebb7e8bd6d5ccc2710dd54c37
parent1b82eda9ebb72a4ac5198a44072f8694ffc1e060 (diff)
dfilter: Change "not in" behaviour to match inequality
"A not in S" is now implemented as "A and A not_in S" instead of "not (A in S)". "not A in S" is implemented as "not A or A not_in S". This is to be consistent with the way inequality has historically worked, where "A != B" is not the same as "not A == B". Maybe we should change both propositions to have inequality be the same as not equality instead. Fixes #19187.
-rw-r--r--epan/dfilter/dfvm.c12
-rw-r--r--epan/dfilter/dfvm.h2
-rw-r--r--epan/dfilter/gencode.c14
-rw-r--r--epan/dfilter/grammar.lemon7
-rw-r--r--epan/dfilter/semcheck.c10
-rw-r--r--epan/dfilter/sttype-op.c7
-rw-r--r--epan/dfilter/syntax-tree.h1
7 files changed, 43 insertions, 10 deletions
diff --git a/epan/dfilter/dfvm.c b/epan/dfilter/dfvm.c
index 5e5f70c906..52a8a5d2aa 100644
--- a/epan/dfilter/dfvm.c
+++ b/epan/dfilter/dfvm.c
@@ -50,6 +50,8 @@ dfvm_opcode_tostr(dfvm_opcode_t code)
case DFVM_ANY_MATCHES: return "ANY_MATCHES";
case DFVM_SET_ALL_IN: return "SET_ALL_IN";
case DFVM_SET_ANY_IN: return "SET_ANY_IN";
+ case DFVM_SET_ALL_NOT_IN: return "SET_ALL_NOT_IN";
+ case DFVM_SET_ANY_NOT_IN: return "SET_ANY_NOT_IN";
case DFVM_SET_ADD: return "SET_ADD";
case DFVM_SET_ADD_RANGE: return "SET_ADD_RANGE";
case DFVM_SET_CLEAR: return "SET_CLEAR";
@@ -496,6 +498,8 @@ append_op_args(wmem_strbuf_t *buf, dfvm_insn_t *insn, GSList **stack_print,
case DFVM_SET_ALL_IN:
case DFVM_SET_ANY_IN:
+ case DFVM_SET_ALL_NOT_IN:
+ case DFVM_SET_ANY_NOT_IN:
wmem_strbuf_append_printf(buf, "%s%s",
arg1_str, arg1_str_type);
break;
@@ -1686,6 +1690,14 @@ dfvm_apply(dfilter_t *df, proto_tree *tree)
accum = any_in(df, arg1);
break;
+ case DFVM_SET_ALL_NOT_IN:
+ accum = !all_in(df, arg1);
+ break;
+
+ case DFVM_SET_ANY_NOT_IN:
+ accum = !any_in(df, arg1);
+ break;
+
case DFVM_SET_CLEAR:
set_clear(df);
break;
diff --git a/epan/dfilter/dfvm.h b/epan/dfilter/dfvm.h
index 34e7f696b6..c6f444f9ee 100644
--- a/epan/dfilter/dfvm.h
+++ b/epan/dfilter/dfvm.h
@@ -78,6 +78,8 @@ typedef enum {
DFVM_ANY_MATCHES,
DFVM_SET_ALL_IN,
DFVM_SET_ANY_IN,
+ DFVM_SET_ALL_NOT_IN,
+ DFVM_SET_ANY_NOT_IN,
DFVM_SET_ADD,
DFVM_SET_ADD_RANGE,
DFVM_SET_CLEAR,
diff --git a/epan/dfilter/gencode.c b/epan/dfilter/gencode.c
index bb1707a5f2..9675c8d33e 100644
--- a/epan/dfilter/gencode.c
+++ b/epan/dfilter/gencode.c
@@ -44,6 +44,7 @@ select_opcode(dfvm_opcode_t op, stmatch_t how)
case DFVM_ALL_CONTAINS:
case DFVM_ALL_MATCHES:
case DFVM_SET_ALL_IN:
+ case DFVM_SET_ALL_NOT_IN:
return how == STNODE_MATCH_ALL ? op : op + 1;
case DFVM_ANY_EQ:
case DFVM_ANY_NE:
@@ -54,6 +55,7 @@ select_opcode(dfvm_opcode_t op, stmatch_t how)
case DFVM_ANY_CONTAINS:
case DFVM_ANY_MATCHES:
case DFVM_SET_ANY_IN:
+ case DFVM_SET_ANY_NOT_IN:
return how == STNODE_MATCH_ANY ? op : op - 1;
default:
break;
@@ -417,7 +419,7 @@ fixup_jumps(gpointer data, gpointer user_data)
/* Generate the code for the in operator. Pushes set values into a stack
* and then evaluates membership in a single instruction. */
static void
-gen_relation_in(dfwork_t *dfw, stmatch_t how,
+gen_relation_in(dfwork_t *dfw, dfvm_opcode_t op, stmatch_t how,
stnode_t *st_arg1, stnode_t *st_arg2)
{
dfvm_insn_t *insn;
@@ -425,7 +427,6 @@ gen_relation_in(dfwork_t *dfw, stmatch_t how,
GSList *node_jumps = NULL;
dfvm_value_t *val1, *val2, *val3;
stnode_t *node1, *node2;
- dfvm_opcode_t op;
GSList *nodelist_head, *nodelist;
/* Create code for the LHS of the relation */
@@ -458,8 +459,7 @@ gen_relation_in(dfwork_t *dfw, stmatch_t how,
set_nodelist_free(nodelist_head);
/* Create code for the set on the RHS of the relation */
- op = select_opcode(DFVM_SET_ANY_IN, how);
- insn = dfvm_insn_new(op);
+ insn = dfvm_insn_new(select_opcode(op, how));
insn->arg1 = dfvm_value_ref(val1);
dfw_append_insn(dfw, insn);
@@ -742,7 +742,11 @@ gen_test(dfwork_t *dfw, stnode_t *st_node)
break;
case STNODE_OP_IN:
- gen_relation_in(dfw, st_how, st_arg1, st_arg2);
+ gen_relation_in(dfw, DFVM_SET_ANY_IN, st_how, st_arg1, st_arg2);
+ break;
+
+ case STNODE_OP_NOT_IN:
+ gen_relation_in(dfw, DFVM_SET_ANY_NOT_IN, st_how, st_arg1, st_arg2);
break;
case STNODE_OP_BITWISE_AND:
diff --git a/epan/dfilter/grammar.lemon b/epan/dfilter/grammar.lemon
index 2c9c393e34..a064de398e 100644
--- a/epan/dfilter/grammar.lemon
+++ b/epan/dfilter/grammar.lemon
@@ -388,11 +388,10 @@ relation_test(T) ::= entity(E) TEST_IN(O) set(S).
stnode_merge_location(T, E, S);
}
-relation_test(T) ::= entity(E) TEST_NOT(P) TEST_IN(O) set(S).
+relation_test(T) ::= entity(E) TEST_NOT TEST_IN(O) set(S).
{
- T = P;
- sttype_oper_set2(O, STNODE_OP_IN, E, S);
- sttype_oper_set1(T, STNODE_OP_NOT, O);
+ T = O;
+ sttype_oper_set2(O, STNODE_OP_NOT_IN, E, S);
stnode_merge_location(T, E, S);
}
diff --git a/epan/dfilter/semcheck.c b/epan/dfilter/semcheck.c
index 23622563b9..b930172970 100644
--- a/epan/dfilter/semcheck.c
+++ b/epan/dfilter/semcheck.c
@@ -1324,10 +1324,18 @@ check_test(dfwork_t *dfw, stnode_t *st_node)
check_relation_matches(dfw, st_node, st_arg1, st_arg2);
break;
case STNODE_OP_IN:
+ case STNODE_OP_NOT_IN:
check_relation_in(dfw, st_node, st_arg1, st_arg2);
break;
- default:
+ case STNODE_OP_UNINITIALIZED:
+ case STNODE_OP_UNARY_MINUS:
+ case STNODE_OP_BITWISE_AND:
+ case STNODE_OP_ADD:
+ case STNODE_OP_SUBTRACT:
+ case STNODE_OP_MULTIPLY:
+ case STNODE_OP_DIVIDE:
+ case STNODE_OP_MODULO:
ws_assert_not_reached();
}
}
diff --git a/epan/dfilter/sttype-op.c b/epan/dfilter/sttype-op.c
index d11686c17c..c75cf25169 100644
--- a/epan/dfilter/sttype-op.c
+++ b/epan/dfilter/sttype-op.c
@@ -134,6 +134,9 @@ oper_todisplay(const oper_t *oper)
case STNODE_OP_IN:
s = "in";
break;
+ case STNODE_OP_NOT_IN:
+ s = "not in";
+ break;
case STNODE_OP_UNINITIALIZED:
s = "<uninitialized>";
break;
@@ -210,6 +213,9 @@ oper_todebug(const oper_t *oper)
case STNODE_OP_IN:
s = "TEST_IN";
break;
+ case STNODE_OP_NOT_IN:
+ s = "TEST_NOT_IN";
+ break;
case STNODE_OP_UNINITIALIZED:
s = "<uninitialized>";
break;
@@ -261,6 +267,7 @@ num_operands(stnode_op_t op)
case STNODE_OP_CONTAINS:
case STNODE_OP_MATCHES:
case STNODE_OP_IN:
+ case STNODE_OP_NOT_IN:
return 2;
}
ws_assert_not_reached();
diff --git a/epan/dfilter/syntax-tree.h b/epan/dfilter/syntax-tree.h
index 01b5c5d539..dbf2e38710 100644
--- a/epan/dfilter/syntax-tree.h
+++ b/epan/dfilter/syntax-tree.h
@@ -86,6 +86,7 @@ typedef enum {
STNODE_OP_CONTAINS,
STNODE_OP_MATCHES,
STNODE_OP_IN,
+ STNODE_OP_NOT_IN,
STNODE_OP_BITWISE_AND,
STNODE_OP_UNARY_MINUS,
STNODE_OP_ADD,