From 0313cd02bc13f21b3f01e723e0ed727eca570bd1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Valverde?= Date: Wed, 6 Apr 2022 21:59:02 +0100 Subject: [PATCH] dfilter: Fix RHS bias for literal values Fixes a3b76138f0e6ae25729337ed22125b092c439463. --- epan/dfilter/semcheck.c | 68 +++++++++++++++++++++++++++--- test/suite_dfilter/group_syntax.py | 17 ++++++++ 2 files changed, 79 insertions(+), 6 deletions(-) diff --git a/epan/dfilter/semcheck.c b/epan/dfilter/semcheck.c index 6798e9d457..120d4bf718 100644 --- a/epan/dfilter/semcheck.c +++ b/epan/dfilter/semcheck.c @@ -186,6 +186,56 @@ dfilter_fvalue_from_literal(dfwork_t *dfw, ftenum_t ftype, stnode_t *st, return fv; } +static fvalue_t * +dfilter_fvalue_from_unparsed(dfwork_t *dfw, ftenum_t ftype, stnode_t *st, + gboolean allow_partial_value, header_field_info *hfinfo_value_string) +{ + fvalue_t *fv; + const char *s = stnode_data(st); + + /* Don't set the error message if it's already set. */ + fv = fvalue_from_literal(ftype, s, allow_partial_value, + dfw->error_message == NULL ? &dfw->error_message : NULL); + + if (fv != NULL) { + /* converted to fvalue successfully. */ + return fv; + } + + if (hfinfo_value_string) { + /* check value_string */ + fv = mk_fvalue_from_val_string(dfw, hfinfo_value_string, s); + + if (fv != NULL) { + /* + * Ignore previous errors if this can be mapped + * to an item from value_string. + */ + g_free(dfw->error_message); + dfw->error_message = NULL; + return fv; + } + } + + header_field_info *hfinfo = dfilter_resolve_unparsed(dfw, s); + + if (hfinfo == NULL) { + /* This node is neither a valid fvalue nor a valid field. */ + /* The parse failed. Error message is already set. */ + THROW(TypeError); + } + + /* Successfully resolved to a field. */ + + /* Free the error message for the failed fvalue_from_literal() attempt. */ + g_free(dfw->error_message); + dfw->error_message = NULL; + + stnode_replace(st, STTYPE_FIELD, hfinfo); + /* Return NULL to signal we have a field. */ + return NULL; +} + /* Gets an fvalue from a string, and sets the error message on failure. */ WS_RETNONNULL static fvalue_t * @@ -657,9 +707,11 @@ again: } if (type2 == STTYPE_UNPARSED) { - if (resolve_unparsed(dfw, st_arg2)) + fvalue = dfilter_fvalue_from_unparsed(dfw, ftype1, st_arg2, allow_partial_value, hfinfo1); + if (fvalue == NULL) { + /* We have a protocol or protocol field. */ goto again; - fvalue = dfilter_fvalue_from_literal(dfw, ftype1, st_arg2, allow_partial_value, hfinfo1); + } } else if (type2 == STTYPE_STRING) { fvalue = dfilter_fvalue_from_string(dfw, ftype1, st_arg2, hfinfo1); @@ -763,9 +815,11 @@ again: stnode_replace(st_arg2, STTYPE_FVALUE, fvalue); } else if (type2 == STTYPE_UNPARSED) { - if (resolve_unparsed(dfw, st_arg2)) + fvalue = dfilter_fvalue_from_unparsed(dfw, FT_BYTES, st_arg2, allow_partial_value, NULL); + if (fvalue == NULL) { + /* We have a protocol or protocol field. */ goto again; - fvalue = dfilter_fvalue_from_literal(dfw, FT_BYTES, st_arg2, allow_partial_value, NULL); + } stnode_replace(st_arg2, STTYPE_FVALUE, fvalue); } else if (type2 == STTYPE_LITERAL) { @@ -868,9 +922,11 @@ again: stnode_replace(st_arg2, STTYPE_FVALUE, fvalue); } else if (type2 == STTYPE_UNPARSED) { - if (resolve_unparsed(dfw, st_arg2)) + fvalue = dfilter_fvalue_from_unparsed(dfw, ftype1, st_arg2, allow_partial_value, NULL); + if (fvalue == NULL) { + /* We have a protocol or protocol field. */ goto again; - fvalue = dfilter_fvalue_from_literal(dfw, ftype1, st_arg2, allow_partial_value, NULL); + } stnode_replace(st_arg2, STTYPE_FVALUE, fvalue); } else if (type2 == STTYPE_LITERAL) { diff --git a/test/suite_dfilter/group_syntax.py b/test/suite_dfilter/group_syntax.py index a9c699c7c5..5ca2aff038 100644 --- a/test/suite_dfilter/group_syntax.py +++ b/test/suite_dfilter/group_syntax.py @@ -158,6 +158,23 @@ class case_equality(unittest.TestCase): dfilter = "frame[0:10] contains :00-01-6c" checkDFilterCount(dfilter, 1) + def test_rhs_literal_bias_1(self, checkDFilterCount): + dfilter = 'frame[37] == fc' + checkDFilterCount(dfilter, 1) + + def test_rhs_literal_bias_2(self, checkDFilterCount): + dfilter = 'frame[37] == :fc' + checkDFilterCount(dfilter, 1) + + def test_rhs_literal_bias_3(self, checkDFilterCount): + dfilter = 'frame[37] == ' + checkDFilterCount(dfilter, 1) + + def test_rhs_literal_bias_4(self, checkDFilterCount): + # This is Fibre Channel on the RHS + dfilter = 'frame[37] == .fc' + checkDFilterCount(dfilter, 0) + @fixtures.uses_fixtures class case_bitwise(unittest.TestCase): trace_file = "http.pcap"