aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJoão Valverde <j@v6e.pt>2021-10-05 12:13:15 +0100
committerJoão Valverde <j@v6e.pt>2021-10-05 16:39:41 +0100
commitd45ba348fd12a058e8925bf08827eadc0d3c82b0 (patch)
treeb9cf646a4293f10a579ea12fad8189fac118eac1
parentf7a2abb4ae20e44b93f47568fdb8e98bbd1ea5a8 (diff)
dfilter: Strengthen sanity check for range
Allow an entity in the grammar as range body. Perform a stronger sanity check during semantic analysis everywhere a range is used. This is both safer (unless we want to allow FIELD bodies only, but functions are allowed too) and also provides better error messages. Previously a range of range only compiled on the RHS. Now it can appear on both sides of a relation. This fixes a crash with STRING entities similar to #10690 for UNPARSED. This also adds back support for slicing functions that was removed in f3f833ccecce0e8611b2f1990d0fcf81959fcb78 (by accident presumably). Ping #10690
-rw-r--r--epan/dfilter/grammar.lemon4
-rw-r--r--epan/dfilter/semcheck.c81
-rw-r--r--test/suite_dfilter/group_range_method.py12
3 files changed, 59 insertions, 38 deletions
diff --git a/epan/dfilter/grammar.lemon b/epan/dfilter/grammar.lemon
index 85fb9aa029..48516a1a15 100644
--- a/epan/dfilter/grammar.lemon
+++ b/epan/dfilter/grammar.lemon
@@ -186,9 +186,7 @@ entity(E) ::= CHARCONST(C). { E = C; }
entity(E) ::= UNPARSED(U). { E = U; }
entity(E) ::= range(R). { E = R; }
-range_body(B) ::= FIELD(F). { B = F; }
-range_body(B) ::= STRING(S). { B = S; }
-range_body(B) ::= range(R). { B = R; }
+range_body(B) ::= entity(E). { B = E; }
/* Ranges */
range(R) ::= range_body(B) LBRACKET range_node_list(L) RBRACKET.
diff --git a/epan/dfilter/semcheck.c b/epan/dfilter/semcheck.c
index 86ab74fb16..38d79dfc3a 100644
--- a/epan/dfilter/semcheck.c
+++ b/epan/dfilter/semcheck.c
@@ -35,6 +35,9 @@ semcheck(dfwork_t *dfw, stnode_t *st_node);
static stnode_t*
check_param_entity(dfwork_t *dfw, stnode_t *st_node);
+static void
+check_function(dfwork_t *dfw, stnode_t *st_node);
+
typedef gboolean (*FtypeCanFunc)(enum ftenum);
/* Compares to ftenum_t's and decides if they're
@@ -573,7 +576,46 @@ check_drange_node_sanity(gpointer data, gpointer user_data)
static void
check_drange_sanity(dfwork_t *dfw, stnode_t *st)
{
+ stnode_t *entity1;
+ header_field_info *hfinfo1;
+ ftenum_t ftype1;
struct check_drange_sanity_args args;
+ char *s;
+
+ entity1 = sttype_range_entity(st);
+ if (entity1 && stnode_type_id(entity1) == STTYPE_FIELD) {
+ hfinfo1 = (header_field_info *)stnode_data(entity1);
+ ftype1 = hfinfo1->type;
+
+ if (!ftype_can_slice(ftype1)) {
+ dfilter_fail(dfw, "\"%s\" is a %s and cannot be sliced into a sequence of bytes.",
+ hfinfo1->abbrev, ftype_pretty_name(ftype1));
+ THROW(TypeError);
+ }
+ } else if (entity1 && stnode_type_id(entity1) == STTYPE_FUNCTION) {
+ df_func_def_t *funcdef = sttype_function_funcdef(entity1);
+ ftype1 = funcdef->retval_ftype;
+
+ if (!ftype_can_slice(ftype1)) {
+ dfilter_fail(dfw, "Return value of function \"%s\" is a %s and cannot be converted into a sequence of bytes.",
+ funcdef->name, ftype_pretty_name(ftype1));
+ THROW(TypeError);
+ }
+
+ check_function(dfw, entity1);
+ } else if (entity1 && stnode_type_id(entity1) == STTYPE_RANGE) {
+ /* Should this be rejected instead? */
+ check_drange_sanity(dfw, entity1);
+ } else if (entity1) {
+ s = stnode_tostr(entity1);
+ dfilter_fail(dfw, "Range is not supported for entity %s of type %s",
+ s, stnode_type_name(entity1));
+ g_free(s);
+ THROW(TypeError);
+ } else {
+ dfilter_fail(dfw, "Range is not supported, details: " G_STRLOC " entity: NULL");
+ THROW(TypeError);
+ }
args.dfw = dfw;
args.st = st;
@@ -1045,9 +1087,8 @@ check_relation_LHS_RANGE(dfwork_t *dfw, const char *relation_string,
{
stnode_t *new_st;
sttype_id_t type2;
- stnode_t *entity1;
- header_field_info *hfinfo1, *hfinfo2;
- ftenum_t ftype1, ftype2;
+ header_field_info *hfinfo2;
+ ftenum_t ftype2;
fvalue_t *fvalue;
GRegex *pcre;
char *s;
@@ -1055,40 +1096,10 @@ check_relation_LHS_RANGE(dfwork_t *dfw, const char *relation_string,
ws_debug("5 check_relation_LHS_RANGE(%s)", relation_string);
- type2 = stnode_type_id(st_arg2);
- entity1 = sttype_range_entity(st_arg1);
- if (entity1 && stnode_type_id(entity1) == STTYPE_FIELD) {
- hfinfo1 = (header_field_info *)stnode_data(entity1);
- ftype1 = hfinfo1->type;
-
- if (!ftype_can_slice(ftype1)) {
- dfilter_fail(dfw, "\"%s\" is a %s and cannot be sliced into a sequence of bytes.",
- hfinfo1->abbrev, ftype_pretty_name(ftype1));
- THROW(TypeError);
- }
- } else if (entity1 && stnode_type_id(entity1) == STTYPE_FUNCTION) {
- df_func_def_t *funcdef = sttype_function_funcdef(entity1);
- ftype1 = funcdef->retval_ftype;
-
- if (!ftype_can_slice(ftype1)) {
- dfilter_fail(dfw, "Return value of function \"%s\" is a %s and cannot be converted into a sequence of bytes.",
- funcdef->name, ftype_pretty_name(ftype1));
- THROW(TypeError);
- }
-
- check_function(dfw, entity1);
-
- } else if (entity1) {
- dfilter_fail(dfw, "Range is not supported for entity %s of type %s",
- stnode_token_value(entity1), stnode_type_name(entity1));
- THROW(TypeError);
- } else {
- dfilter_fail(dfw, "Range is not supported, details: " G_STRLOC " entity: NULL");
- THROW(TypeError);
- }
-
check_drange_sanity(dfw, st_arg1);
+ type2 = stnode_type_id(st_arg2);
+
if (type2 == STTYPE_FIELD) {
ws_debug("5 check_relation_LHS_RANGE(type2 = STTYPE_FIELD)");
hfinfo2 = (header_field_info*)stnode_data(st_arg2);
diff --git a/test/suite_dfilter/group_range_method.py b/test/suite_dfilter/group_range_method.py
index 4570171bb3..c3068a6ea0 100644
--- a/test/suite_dfilter/group_range_method.py
+++ b/test/suite_dfilter/group_range_method.py
@@ -34,3 +34,15 @@ class case_range(unittest.TestCase):
def test_slice_2_neg(self, checkDFilterCount):
dfilter = "ipx.src.node[3:2] == cc:dd"
checkDFilterCount(dfilter, 0)
+
+ def test_slice_string_1(self, checkDFilterFail):
+ dfilter = "frame == \"00\"[1]"
+ checkDFilterFail(dfilter, "Range is not supported for entity 00 of type STRING")
+
+ def test_slice_unparsed_1(self, checkDFilterFail):
+ dfilter = "a == b[1]"
+ checkDFilterFail(dfilter, "Range is not supported for entity b of type UNPARSED")
+
+ def test_slice_func_1(self, checkDFilterSucceed):
+ dfilter = "string(ipx.src.node)[3:2] == \"cc:dd\""
+ checkDFilterSucceed(dfilter)