diff options
author | João Valverde <j@v6e.pt> | 2023-07-24 23:12:08 +0100 |
---|---|---|
committer | João Valverde <j@v6e.pt> | 2023-07-25 12:17:25 +0000 |
commit | ca8976020ff82f802ae8c3ab72ea4491f8c6dc1e (patch) | |
tree | ef18eea1c5e7fa4ebb7e8bd6d5ccc2710dd54c37 | |
parent | 1b82eda9ebb72a4ac5198a44072f8694ffc1e060 (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.c | 12 | ||||
-rw-r--r-- | epan/dfilter/dfvm.h | 2 | ||||
-rw-r--r-- | epan/dfilter/gencode.c | 14 | ||||
-rw-r--r-- | epan/dfilter/grammar.lemon | 7 | ||||
-rw-r--r-- | epan/dfilter/semcheck.c | 10 | ||||
-rw-r--r-- | epan/dfilter/sttype-op.c | 7 | ||||
-rw-r--r-- | epan/dfilter/syntax-tree.h | 1 |
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, |