dfilter: Allow bytestrings that are also protocol names on RHS

Protocol names can only be on the left hand side of filter expressions.
If a protocol name with an even number of characters ("fc", "dc", "ff",
"fefd", etc.) is on the right hand side of a filter expressions and
can be interpreted as a byte string instead, do so.  Fix #12810.
This commit is contained in:
John Thacker 2021-09-16 20:15:54 -04:00 committed by Wireshark GitLab Utility
parent 750cc38669
commit ac0b1d42f3
1 changed files with 40 additions and 6 deletions

View File

@ -1418,21 +1418,55 @@ check_relation(dfwork_t *dfw, const char *relation_string,
#ifdef DEBUG_dfilter
static guint i = 0;
#endif
header_field_info *hfinfo;
header_field_info *hfinfo;
stnode_t *new_st;
fvalue_t *fvalue;
char *s;
DebugLog((" 4 check_relation(\"%s\") [%u]\n", relation_string, i++));
/* Protocol can only be on LHS (for "contains" or "matches" operators).
* Check to see if protocol is on RHS. This catches the case where the
* user has written "fc" on the RHS, probably intending a byte value
* rather than the fibre channel protocol.
* Check to see if protocol is on RHS, and try to parse it as a byte
* array instead. Only raise an error if it can't be re-interpreted.
* This catches the case where the user has written "fc" on the RHS,
* probably intending a byte value rather than the fibre channel
* protocol, or similar for a number of other possibilities.
* ("dc", "ff", "fefd")
*
* XXX: Is there a better way to do this in the lex scanner or grammar
* parser step instead? Or should the deterimination of whether
* something is a field occur later than it does currently? This is
* kind of a hack.
*/
if (stnode_type_id(st_arg2) == STTYPE_FIELD) {
hfinfo = (header_field_info*)stnode_data(st_arg2);
if (hfinfo->type == FT_PROTOCOL) {
dfilter_fail(dfw, "Protocol (\"%s\") cannot appear on right-hand side of comparison.", hfinfo->abbrev);
THROW(TypeError);
/* Discard const qualifier from hfinfo->abbrev
* for sttnode_new, even though it duplicates the
* string.
*/
s = (char *)hfinfo->abbrev;
/* Could we parse it as a byte string instead of a
* protocol name? (Set allow_partial_value to false
* because there's no point in allowing, e.g. "bfd"
* through.)
*/
fvalue = fvalue_from_unparsed(FT_BYTES, s, FALSE, NULL);
if (!fvalue) {
/* No. Raise an error. */
dfilter_fail(dfw, "Protocol (\"%s\") cannot appear on right-hand side of comparison.", hfinfo->abbrev);
THROW(TypeError);
}
/* Yes. Send it through as unparsed and all the other
* functions will take care of it as if it didn't
* match a protocol string.
*/
FVALUE_FREE(fvalue);
new_st = stnode_new(STTYPE_UNPARSED, s);
stnode_free(st_arg2);
st_arg2 = new_st;
sttype_test_set2_args(st_node, st_arg1, new_st);
}
}