aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--epan/dfilter/dfilter-int.h4
-rw-r--r--epan/dfilter/dfilter.c4
-rw-r--r--epan/dfilter/dfunctions.c75
-rw-r--r--epan/dfilter/semcheck.c16
-rw-r--r--test/suite_dfilter/group_function.py11
5 files changed, 70 insertions, 40 deletions
diff --git a/epan/dfilter/dfilter-int.h b/epan/dfilter/dfilter-int.h
index 0e4bf3f752..b477d7418a 100644
--- a/epan/dfilter/dfilter-int.h
+++ b/epan/dfilter/dfilter-int.h
@@ -56,6 +56,10 @@ typedef struct {
GHashTable *raw_references; /* hfinfo -> pointer to array of references */
char *expanded_text;
gboolean apply_optimization;
+ wmem_allocator_t *dfw_scope; /* Because we use exceptions for error handling sometimes
+ cleaning up memory allocations is inconvenient. Memory
+ allocated from this pool will be freed when the dfwork_t
+ context is destroyed. */
} dfwork_t;
/*
diff --git a/epan/dfilter/dfilter.c b/epan/dfilter/dfilter.c
index b1a96f8a5d..03e367e698 100644
--- a/epan/dfilter/dfilter.c
+++ b/epan/dfilter/dfilter.c
@@ -234,6 +234,8 @@ dfwork_new(void)
g_hash_table_new_full(g_direct_hash, g_direct_equal,
NULL, (GDestroyNotify)free_refs_array);
+ dfw->dfw_scope = wmem_allocator_new(WMEM_ALLOCATOR_SIMPLE);
+
return dfw;
}
@@ -273,6 +275,8 @@ dfwork_free(dfwork_t *dfw)
g_free(dfw->expanded_text);
+ wmem_destroy_allocator(dfw->dfw_scope);
+
/*
* We don't free the error message string; our caller will return
* it to its caller.
diff --git a/epan/dfilter/dfunctions.c b/epan/dfilter/dfunctions.c
index 5c8b122878..e21f03898c 100644
--- a/epan/dfilter/dfunctions.c
+++ b/epan/dfilter/dfunctions.c
@@ -330,51 +330,52 @@ ul_semcheck_string_param(dfwork_t *dfw, const char *func_name, ftenum_t lhs_ftyp
}
/* Check arguments are all the same type and they can be compared. */
+/*
+ Every STTYPE_LITERAL needs to be resolved to a STTYPE_FVALUE. If we don't
+ have type information (lhs_ftype is FT_NONE) and we have not seen an argument
+ with a definite type we defer resolving literals to values until we have examined
+ the entire list of function arguments. If we still cannot resolve to a definite
+ type after that (all arguments must have the same type) then we give up and
+ return FT_NONE.
+*/
static ftenum_t
ul_semcheck_compare(dfwork_t *dfw, const char *func_name, ftenum_t lhs_ftype,
GSList *param_list, df_loc_t func_loc _U_)
{
stnode_t *arg;
+ sttype_id_t type;
ftenum_t ftype, ft_arg;
GSList *l;
fvalue_t *fv;
+ wmem_list_t *literals = NULL;
- arg = param_list->data;
-
- if (stnode_type_id(arg) == STTYPE_ARITHMETIC) {
- ftype = check_arithmetic(dfw, arg, lhs_ftype);
- }
- else if (stnode_type_id(arg) == STTYPE_LITERAL && lhs_ftype != FT_NONE) {
- fv = dfilter_fvalue_from_literal(dfw, lhs_ftype, arg, FALSE, NULL);
- stnode_replace(arg, STTYPE_FVALUE, fv);
- ftype = fvalue_type_ftenum(fv);
- }
- else if (stnode_type_id(arg) == STTYPE_FUNCTION) {
- ftype = check_function(dfw, arg, lhs_ftype);
- }
- else if (stnode_type_id(arg) == STTYPE_FIELD || stnode_type_id(arg) == STTYPE_REFERENCE) {
- ftype = sttype_field_ftenum(arg);
- }
- else {
- FAIL(dfw, arg, "Argument '%s' is not valid for %s()",
- stnode_todisplay(arg), func_name);
- }
+ ftype = lhs_ftype;
- for (l = param_list->next; l != NULL; l = l->next) {
+ for (l = param_list; l != NULL; l = l->next) {
arg = l->data;
+ type = stnode_type_id(arg);
- if (stnode_type_id(arg) == STTYPE_ARITHMETIC) {
+ if (type == STTYPE_ARITHMETIC) {
ft_arg = check_arithmetic(dfw, arg, ftype);
}
- else if (stnode_type_id(arg) == STTYPE_LITERAL && ftype != FT_NONE) {
- fv = dfilter_fvalue_from_literal(dfw, ftype, arg, FALSE, NULL);
- stnode_replace(arg, STTYPE_FVALUE, fv);
- ft_arg = fvalue_type_ftenum(fv);
+ else if (type == STTYPE_LITERAL) {
+ if (ftype != FT_NONE) {
+ fv = dfilter_fvalue_from_literal(dfw, ftype, arg, FALSE, NULL);
+ stnode_replace(arg, STTYPE_FVALUE, fv);
+ ft_arg = fvalue_type_ftenum(fv);
+ }
+ else {
+ if (literals == NULL) {
+ literals = wmem_list_new(dfw->dfw_scope);
+ }
+ wmem_list_append(literals, arg);
+ ft_arg = FT_NONE;
+ }
}
- else if (stnode_type_id(arg) == STTYPE_FUNCTION) {
+ else if (type == STTYPE_FUNCTION) {
ft_arg = check_function(dfw, arg, ftype);
}
- else if (stnode_type_id(arg) == STTYPE_FIELD || stnode_type_id(arg) == STTYPE_REFERENCE) {
+ else if (type == STTYPE_FIELD || type == STTYPE_REFERENCE) {
ft_arg = sttype_field_ftenum(arg);
}
else {
@@ -385,15 +386,29 @@ ul_semcheck_compare(dfwork_t *dfw, const char *func_name, ftenum_t lhs_ftype,
if (ftype == FT_NONE) {
ftype = ft_arg;
}
- if (ft_arg != ftype) {
+ if (ft_arg != FT_NONE && ftype != FT_NONE && ft_arg != ftype) {
FAIL(dfw, arg, "Arguments to '%s' must have the same type (expected %s, got %s)",
func_name, ftype_name(ftype), ftype_name(ft_arg));
}
- if (!ftype_can_cmp(ft_arg)) {
+ if (ft_arg != FT_NONE && !ftype_can_cmp(ft_arg)) {
FAIL(dfw, arg, "Argument '%s' to '%s' cannot be ordered",
stnode_todisplay(arg), func_name);
}
}
+
+ if (literals != NULL) {
+ if (ftype != FT_NONE) {
+ wmem_list_frame_t *fp;
+ stnode_t *st;
+ for (fp = wmem_list_head(literals); fp != NULL; fp = wmem_list_frame_next(fp)) {
+ st = wmem_list_frame_data(fp);
+ fv = dfilter_fvalue_from_literal(dfw, ftype, st, FALSE, NULL);
+ stnode_replace(st, STTYPE_FVALUE, fv);
+ }
+ }
+ wmem_destroy_list(literals);
+ }
+
return ftype;
}
diff --git a/epan/dfilter/semcheck.c b/epan/dfilter/semcheck.c
index b93707289f..6c67e0a914 100644
--- a/epan/dfilter/semcheck.c
+++ b/epan/dfilter/semcheck.c
@@ -787,8 +787,8 @@ check_relation_LHS_SLICE(dfwork_t *dfw, stnode_op_t st_op,
static void
check_relation_LHS_FUNCTION(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)
{
sttype_id_t type2;
ftenum_t ftype1, ftype2;
@@ -797,7 +797,11 @@ check_relation_LHS_FUNCTION(dfwork_t *dfw, stnode_op_t st_op,
LOG_NODE(st_node);
ftype1 = check_function(dfw, st_arg1, FT_NONE);
-
+ if (ftype1 == FT_NONE) {
+ check_relation(dfw, st_op, can_func, allow_partial_value,
+ st_node, st_arg2, st_arg1, commute - 1);
+ return;
+ }
if (!can_func(ftype1)) {
FAIL(dfw, st_arg1, "Function %s (type=%s) cannot participate in %s comparison.",
sttype_function_name(st_arg1), ftype_pretty_name(ftype1),
@@ -1006,7 +1010,7 @@ check_relation(dfwork_t *dfw, stnode_op_t st_op,
break;
case STTYPE_FUNCTION:
check_relation_LHS_FUNCTION(dfw, st_op, can_func,
- allow_partial_value, st_node, st_arg1, st_arg2);
+ allow_partial_value, st_node, st_arg1, st_arg2, commute);
break;
case STTYPE_ARITHMETIC:
check_relation_LHS_ARITHMETIC(dfw, st_op, can_func,
@@ -1042,7 +1046,7 @@ check_relation_contains(dfwork_t *dfw, stnode_t *st_node,
break;
case STTYPE_FUNCTION:
check_relation_LHS_FUNCTION(dfw, STNODE_OP_CONTAINS, ftype_can_contains,
- TRUE, st_node, st_arg1, st_arg2);
+ TRUE, st_node, st_arg1, st_arg2, 0);
break;
case STTYPE_SLICE:
check_relation_LHS_SLICE(dfw, STNODE_OP_CONTAINS, ftype_can_contains,
@@ -1089,7 +1093,7 @@ check_relation_matches(dfwork_t *dfw, stnode_t *st_node,
break;
case STTYPE_FUNCTION:
check_relation_LHS_FUNCTION(dfw, STNODE_OP_MATCHES, ftype_can_matches,
- TRUE, st_node, st_arg1, st_arg2);
+ TRUE, st_node, st_arg1, st_arg2, 0);
break;
case STTYPE_SLICE:
check_relation_LHS_SLICE(dfw, STNODE_OP_MATCHES, ftype_can_matches,
diff --git a/test/suite_dfilter/group_function.py b/test/suite_dfilter/group_function.py
index 9d80082b3f..517fa91f34 100644
--- a/test/suite_dfilter/group_function.py
+++ b/test/suite_dfilter/group_function.py
@@ -66,10 +66,13 @@ class case_dfunction_maxmin(unittest.TestCase):
dfilter = 'max(udp.srcport, udp.dstport) < 5060'
checkDFilterCount(dfilter, 1)
- def test_max_4(self, checkDFilterFail):
- error = 'Argument \'1\' is not valid for max()'
- dfilter = 'max(1,_ws.ftypes.int8) == 1'
- checkDFilterFail(dfilter, error)
+ def test_max_4(self, checkDFilterCount):
+ dfilter = 'max(5060, udp.dstport) == udp.srcport'
+ checkDFilterCount(dfilter, 2)
+
+ def test_max_5(self, checkDFilterCount):
+ dfilter = 'max(5060, 5070) == udp.srcport'
+ checkDFilterCount(dfilter, 1)
@fixtures.uses_fixtures
class case_dfunction_abs(unittest.TestCase):