forked from osmocom/wireshark
dfilter: Remove unparsed syntax type and RHS literal bias
This removes unparsed name resolution during the semantic check because it feels like a hack to work around limitations in the language syntax, that should be solved at the lexical level instead. We were interpreting unparsed differently on the LHS and RHS. Now an unparsed value is always a field if it matches a registered field name (this matches the implementation in 3.6 and before). This requires tightening a bit the allowed filter names for protocols to avoid some common and potentially weird conflicting cases. Incidentally this extends set grammar to accept all entities. That is experimental and may be reverted in the future.
This commit is contained in:
parent
190404d66b
commit
b10db887ce
|
@ -869,36 +869,36 @@ to “dhcp.type” but Wireshark will show the warning “"bootp" is deprecated
|
|||
when you use it. Support for the deprecated fields may be removed in the future.
|
||||
|
||||
==== Some protocol names can be ambiguous
|
||||
In some uncommon cases relational display filter expressions (equal, less than, etc.)
|
||||
In some particular cases relational expressions (equal, less than, etc.)
|
||||
can be ambiguous. The filter name of a protocol or protocol field can contain
|
||||
any letter and digit in any order, possibly separated by dots. That can be
|
||||
indistinguishable from a literal value (usually numerical values in hexadecimal).
|
||||
For example the semantic value of `fc` can be the protocol Fibre Channel or the
|
||||
number 0xfc in hexadecimal. The 0x prefix is optional for literal values and
|
||||
furthermore "0xfc" would be a syntactically valid filter name for a protocol.
|
||||
number 0xFC in hexadecimal because the 0x prefix is optional for hexadecimal numbers.
|
||||
|
||||
Wireshark will use a heuristic for parsing those expressions. A value on the
|
||||
right hand side of the expression is treated as literal value first. If that
|
||||
fails it is treated as a protocol or protocol field (if one exists with that
|
||||
name). If that fails it is a syntactical error. On the left hand side values
|
||||
are always treated as protocol fields. Literal values are not considered on the
|
||||
LHS. So the expression `fc == fc` is parsed as
|
||||
"Byte array of protocol with name 'fc' equals byte array { 0xfc } of length 1".
|
||||
Any value that matches a registered protocol or protocol field filter name is
|
||||
interpreted semantically as such. If it doesn't match a protocol name the normal
|
||||
rules for parsing literal values apply.
|
||||
|
||||
Sometimes this may not be the intended meaning and there is additional syntax
|
||||
to resolve the ambiguity. Lexical tokens in-between angle brackets are always
|
||||
and only treated as literal values. Bytes arrays can also be prefixed with a
|
||||
colon. Tokens prefixed with a dot are always treated as a protocol name (the
|
||||
dot stands for the root of the protocol namespace and is optional).
|
||||
So in the case of 'fc' the lexical token is interpreted as "Fibre Channel" and
|
||||
not 0xFC. In the case of 'fd' it would be interpreted as 0xFD because it is a
|
||||
well-formed hexadecimal literal value (according to the rules of display filter
|
||||
language syntax) and there is no protocol registered with the filter name 'fd'.
|
||||
|
||||
How ambiguous values are interpreted may change in the future. To avoid this
|
||||
problem and resolve the ambiguity there is additional syntax available.
|
||||
Values in-between angle brackets are always and only treated as literal
|
||||
values. Bytes arrays and numeric values can also be prefixed with a colon to
|
||||
force interpretation as a literal value. Values prefixed with a dot are always
|
||||
treated as a protocol name. The dot stands for the root of the protocol namespace
|
||||
and is optional)
|
||||
----
|
||||
frame[10:] contains .fc or frame[10] == :fc and not frame contains <cafe.face>
|
||||
----
|
||||
The most common use case for a display filter relational expression is to compare
|
||||
a field with a constant value on the right hand side and in that case the heuristic
|
||||
method used will parse the expression correctly. In the not-so-common case, or
|
||||
if you are writing a script, or you think your expression may not be giving the
|
||||
expected results it is advisable to use the explicit syntax to resolve any
|
||||
possible ambiguity in the meaning of filter expression.
|
||||
If you are writing a script, or you think your expression may not be giving the
|
||||
expected results because of the syntactical ambiguity of some filter expression
|
||||
it is advisable to use the explicit syntax to indicate the correct meaning for
|
||||
that expression.
|
||||
|
||||
[#ChWorkFilterAddExpressionSection]
|
||||
|
||||
|
|
|
@ -105,13 +105,6 @@ DfilterTrace(FILE *TraceFILE, char *zTracePrompt);
|
|||
header_field_info *
|
||||
dfilter_resolve_unparsed(dfwork_t *dfw, const char *name);
|
||||
|
||||
gboolean
|
||||
dfw_resolve_unparsed(dfwork_t *dfw, stnode_t *st);
|
||||
|
||||
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);
|
||||
|
||||
WS_RETNONNULL fvalue_t*
|
||||
dfilter_fvalue_from_literal(dfwork_t *dfw, ftenum_t ftype, stnode_t *st,
|
||||
gboolean allow_partial_value, header_field_info *hfinfo_value_string);
|
||||
|
|
|
@ -94,10 +94,6 @@ dfw_set_error_location(dfwork_t *dfw, stloc_t *loc)
|
|||
dfw->err_loc = *loc;
|
||||
}
|
||||
|
||||
/*
|
||||
* Tries to convert an STTYPE_UNPARSED to a STTYPE_FIELD. If it's not registered as
|
||||
* a field pass UNPARSED to the semantic check.
|
||||
*/
|
||||
header_field_info *
|
||||
dfilter_resolve_unparsed(dfwork_t *dfw, const char *name)
|
||||
{
|
||||
|
@ -121,21 +117,6 @@ dfilter_resolve_unparsed(dfwork_t *dfw, const char *name)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
gboolean
|
||||
dfw_resolve_unparsed(dfwork_t *dfw, stnode_t *st)
|
||||
{
|
||||
if (stnode_type_id(st) != STTYPE_UNPARSED)
|
||||
return FALSE;
|
||||
|
||||
header_field_info *hfinfo = dfilter_resolve_unparsed(dfw, stnode_data(st));
|
||||
if (hfinfo != NULL) {
|
||||
stnode_replace(st, STTYPE_FIELD, hfinfo);
|
||||
return TRUE;
|
||||
}
|
||||
stnode_replace(st, STTYPE_LITERAL, g_strdup(stnode_data(st)));
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* Initialize the dfilter module */
|
||||
void
|
||||
dfilter_init(void)
|
||||
|
|
|
@ -274,8 +274,6 @@ ul_semcheck_is_field_string(dfwork_t *dfw, const char *func_name, ftenum_t lhs_f
|
|||
ws_assert(g_slist_length(param_list) == 1);
|
||||
stnode_t *st_node = param_list->data;
|
||||
|
||||
dfw_resolve_unparsed(dfw, st_node);
|
||||
|
||||
if (stnode_type_id(st_node) == STTYPE_FIELD) {
|
||||
hfinfo = sttype_field_hfinfo(st_node);
|
||||
if (IS_FT_STRING(hfinfo->type)) {
|
||||
|
@ -292,8 +290,6 @@ ul_semcheck_is_field(dfwork_t *dfw, const char *func_name, ftenum_t lhs_ftype _U
|
|||
ws_assert(g_slist_length(param_list) == 1);
|
||||
stnode_t *st_node = param_list->data;
|
||||
|
||||
dfw_resolve_unparsed(dfw, st_node);
|
||||
|
||||
if (stnode_type_id(st_node) == STTYPE_FIELD)
|
||||
return FT_UINT32;
|
||||
|
||||
|
@ -309,8 +305,6 @@ ul_semcheck_string_param(dfwork_t *dfw, const char *func_name, ftenum_t lhs_ftyp
|
|||
ws_assert(g_slist_length(param_list) == 1);
|
||||
stnode_t *st_node = param_list->data;
|
||||
|
||||
dfw_resolve_unparsed(dfw, st_node);
|
||||
|
||||
if (stnode_type_id(st_node) == STTYPE_FIELD) {
|
||||
hfinfo = sttype_field_hfinfo(st_node);
|
||||
switch (hfinfo->type) {
|
||||
|
@ -366,7 +360,6 @@ ul_semcheck_compare(dfwork_t *dfw, const char *func_name, ftenum_t lhs_ftype,
|
|||
fvalue_t *fv;
|
||||
|
||||
arg = param_list->data;
|
||||
dfw_resolve_unparsed(dfw, arg);
|
||||
|
||||
if (stnode_type_id(arg) == STTYPE_ARITHMETIC) {
|
||||
ftype = check_arithmetic_expr(dfw, arg, lhs_ftype);
|
||||
|
@ -390,7 +383,6 @@ ul_semcheck_compare(dfwork_t *dfw, const char *func_name, ftenum_t lhs_ftype,
|
|||
|
||||
for (l = param_list->next; l != NULL; l = l->next) {
|
||||
arg = l->data;
|
||||
dfw_resolve_unparsed(dfw, arg);
|
||||
|
||||
if (stnode_type_id(arg) == STTYPE_ARITHMETIC) {
|
||||
ft_arg = check_arithmetic_expr(dfw, arg, ftype);
|
||||
|
@ -436,7 +428,6 @@ ul_semcheck_absolute_value(dfwork_t *dfw, const char *func_name, ftenum_t lhs_ft
|
|||
fvalue_t *fv;
|
||||
|
||||
st_node = param_list->data;
|
||||
dfw_resolve_unparsed(dfw, st_node);
|
||||
|
||||
if (stnode_type_id(st_node) == STTYPE_ARITHMETIC) {
|
||||
ftype = check_arithmetic_expr(dfw, st_node, lhs_ftype);
|
||||
|
|
|
@ -120,7 +120,6 @@ expr(X) ::= LPAREN expr(Y) RPAREN. { X = Y; }
|
|||
/* Entities, or things that can be compared/tested/checked */
|
||||
atom(A) ::= STRING(S). { A = S; }
|
||||
atom(A) ::= CHARCONST(N). { A = N; }
|
||||
atom(A) ::= UNPARSED(S). { A = S; }
|
||||
atom(A) ::= LITERAL(S). { A = S; }
|
||||
|
||||
layer(R) ::= HASH LBRACKET range_node_list(L) RBRACKET.
|
||||
|
@ -154,7 +153,7 @@ field(R) ::= FIELD(F) layer(L).
|
|||
|
||||
field(R) ::= UNPARSED(U) layer(L).
|
||||
{
|
||||
header_field_info *hfinfo = dfilter_resolve_unparsed(dfw, stnode_data(U));
|
||||
header_field_info *hfinfo = dfilter_resolve_unparsed(dfw, stnode_token(U));
|
||||
if (hfinfo == NULL) {
|
||||
FAIL(dfw, U, "%s is not a valid field", stnode_token(U));
|
||||
}
|
||||
|
@ -174,7 +173,7 @@ reference(R) ::= DOLLAR LBRACE field(F) RBRACE.
|
|||
|
||||
reference(R) ::= DOLLAR LBRACE UNPARSED(U) RBRACE.
|
||||
{
|
||||
header_field_info *hfinfo = dfilter_resolve_unparsed(dfw, stnode_data(U));
|
||||
header_field_info *hfinfo = dfilter_resolve_unparsed(dfw, stnode_token(U));
|
||||
if (hfinfo == NULL) {
|
||||
FAIL(dfw, U, "%s is not a valid field", stnode_token(U));
|
||||
}
|
||||
|
@ -187,6 +186,19 @@ entity(E) ::= slice(R). { E = R; }
|
|||
entity(E) ::= function(F). { E = F; }
|
||||
entity(E) ::= field(F). { E = F; }
|
||||
entity(E) ::= reference(R). { E = R; }
|
||||
entity(E) ::= UNPARSED(U).
|
||||
{
|
||||
const char *token = stnode_token(U);
|
||||
const stloc_t *loc = stnode_location(U);
|
||||
header_field_info *hfinfo = dfilter_resolve_unparsed(dfw, token);
|
||||
if (hfinfo != NULL) {
|
||||
E = stnode_new(STTYPE_FIELD, hfinfo, g_strdup(token), loc);
|
||||
}
|
||||
else {
|
||||
E = stnode_new(STTYPE_LITERAL, g_strdup(token), g_strdup(token), loc);
|
||||
}
|
||||
stnode_free(U);
|
||||
}
|
||||
|
||||
arithmetic_expr(T) ::= entity(N).
|
||||
{
|
||||
|
@ -338,20 +350,20 @@ set_list(L) ::= set_list(P) COMMA set_element(N).
|
|||
L = g_slist_concat(P, N);
|
||||
}
|
||||
|
||||
set_entity(N) ::= atom(X).
|
||||
set_entity(N) ::= entity(E).
|
||||
{
|
||||
N = X;
|
||||
N = E;
|
||||
}
|
||||
|
||||
set_entity(N) ::= MINUS(M) atom(X).
|
||||
set_entity(N) ::= MINUS(M) entity(E).
|
||||
{
|
||||
N = M;
|
||||
sttype_test_set1(N, OP_UNARY_MINUS, X);
|
||||
sttype_test_set1(N, OP_UNARY_MINUS, E);
|
||||
}
|
||||
|
||||
set_entity(N) ::= PLUS atom(X).
|
||||
set_entity(N) ::= PLUS entity(E).
|
||||
{
|
||||
N = X;
|
||||
N = E;
|
||||
}
|
||||
|
||||
set_element(N) ::= set_entity(X).
|
||||
|
@ -408,7 +420,7 @@ range_node_list(L) ::= range_node_list(P) COMMA RANGE_NODE(N).
|
|||
static stnode_t *
|
||||
new_function(dfwork_t *dfw, stnode_t *node)
|
||||
{
|
||||
const char *name = stnode_data(node);
|
||||
const char *name = stnode_token(node);
|
||||
|
||||
df_func_def_t *def = df_func_lookup(name);
|
||||
if (!def) {
|
||||
|
|
|
@ -419,19 +419,19 @@ hyphen-bytes {hex2}(-{hex2})+
|
|||
{MacAddress}|{QuadMacAddress} {
|
||||
/* MAC Address. */
|
||||
update_location(yyextra, yytext);
|
||||
return set_lval_str(yyextra, TOKEN_UNPARSED, yytext);
|
||||
return set_lval_simple(yyextra, TOKEN_UNPARSED, yytext, STTYPE_UNINITIALIZED);
|
||||
}
|
||||
|
||||
{IPv4address}{v4-cidr-prefix}? {
|
||||
/* IPv4 with or without prefix. */
|
||||
update_location(yyextra, yytext);
|
||||
return set_lval_str(yyextra, TOKEN_UNPARSED, yytext);
|
||||
return set_lval_simple(yyextra, TOKEN_UNPARSED, yytext, STTYPE_UNINITIALIZED);
|
||||
}
|
||||
|
||||
{IPv6address}{v6-cidr-prefix}? {
|
||||
/* IPv6 with or without prefix. */
|
||||
update_location(yyextra, yytext);
|
||||
return set_lval_str(yyextra, TOKEN_UNPARSED, yytext);
|
||||
return set_lval_simple(yyextra, TOKEN_UNPARSED, yytext, STTYPE_UNINITIALIZED);
|
||||
}
|
||||
|
||||
:?({colon-bytes}|{dot-bytes}|{hyphen-bytes}) {
|
||||
|
@ -439,7 +439,7 @@ hyphen-bytes {hex2}(-{hex2})+
|
|||
update_location(yyextra, yytext);
|
||||
if (yytext[0] == ':')
|
||||
return set_lval_str(yyextra, TOKEN_LITERAL, yytext); /* Keep leading colon. */
|
||||
return set_lval_str(yyextra, TOKEN_UNPARSED, yytext);
|
||||
return set_lval_simple(yyextra, TOKEN_UNPARSED, yytext, STTYPE_UNINITIALIZED);
|
||||
}
|
||||
|
||||
:[[:xdigit:]]+ {
|
||||
|
@ -464,7 +464,7 @@ hyphen-bytes {hex2}(-{hex2})+
|
|||
/* Skip leading dot. */
|
||||
return set_lval_field(yyextra, TOKEN_FIELD, yytext + 1);
|
||||
}
|
||||
return set_lval_str(yyextra, TOKEN_UNPARSED, yytext);
|
||||
return set_lval_simple(yyextra, TOKEN_UNPARSED, yytext, STTYPE_UNINITIALIZED);
|
||||
}
|
||||
|
||||
. {
|
||||
|
@ -522,9 +522,6 @@ set_lval_str(df_scanner_state_t *state, int token, const char *token_value)
|
|||
case TOKEN_LITERAL:
|
||||
type_id = STTYPE_LITERAL;
|
||||
break;
|
||||
case TOKEN_UNPARSED:
|
||||
type_id = STTYPE_UNPARSED;
|
||||
break;
|
||||
default:
|
||||
ws_assert_not_reached();
|
||||
}
|
||||
|
|
|
@ -184,57 +184,6 @@ dfilter_fvalue_from_literal(dfwork_t *dfw, ftenum_t ftype, stnode_t *st,
|
|||
return fv;
|
||||
}
|
||||
|
||||
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. */
|
||||
dfw_set_error_location(dfw, stnode_location(st));
|
||||
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
|
||||
fvalue_t *
|
||||
|
@ -503,8 +452,6 @@ check_exists(dfwork_t *dfw, stnode_t *st_arg1)
|
|||
{
|
||||
LOG_NODE(st_arg1);
|
||||
|
||||
dfw_resolve_unparsed(dfw, st_arg1);
|
||||
|
||||
switch (stnode_type_id(st_arg1)) {
|
||||
case STTYPE_FIELD:
|
||||
case STTYPE_ARITHMETIC:
|
||||
|
@ -535,7 +482,6 @@ check_exists(dfwork_t *dfw, stnode_t *st_arg1)
|
|||
break;
|
||||
|
||||
case STTYPE_SET:
|
||||
case STTYPE_UNPARSED:
|
||||
case STTYPE_UNINITIALIZED:
|
||||
case STTYPE_NUM_TYPES:
|
||||
case STTYPE_TEST:
|
||||
|
@ -556,7 +502,6 @@ check_slice_sanity(dfwork_t *dfw, stnode_t *st, ftenum_t lhs_ftype)
|
|||
|
||||
entity1 = sttype_slice_entity(st);
|
||||
ws_assert(entity1);
|
||||
dfw_resolve_unparsed(dfw, entity1);
|
||||
|
||||
if (stnode_type_id(entity1) == STTYPE_FIELD) {
|
||||
hfinfo1 = sttype_field_hfinfo(entity1);
|
||||
|
@ -659,7 +604,6 @@ check_relation_LHS_FIELD(dfwork_t *dfw, test_op_t st_op,
|
|||
|
||||
LOG_NODE(st_node);
|
||||
|
||||
again:
|
||||
type2 = stnode_type_id(st_arg2);
|
||||
|
||||
ws_assert(stnode_type_id(st_arg1) == STTYPE_FIELD ||
|
||||
|
@ -687,7 +631,7 @@ again:
|
|||
stnode_todisplay(st_arg2), ftype_pretty_name(ftype2));
|
||||
}
|
||||
}
|
||||
else if (type2 == STTYPE_STRING || type2 == STTYPE_LITERAL || type2 == STTYPE_UNPARSED) {
|
||||
else if (type2 == STTYPE_STRING || type2 == STTYPE_LITERAL) {
|
||||
/* Skip incompatible fields */
|
||||
while (hfinfo1->same_name_prev_id != -1 &&
|
||||
((type2 == STTYPE_STRING && ftype1 != FT_STRING && ftype1!= FT_STRINGZ) ||
|
||||
|
@ -696,14 +640,7 @@ again:
|
|||
ftype1 = hfinfo1->type;
|
||||
}
|
||||
|
||||
if (type2 == STTYPE_UNPARSED) {
|
||||
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;
|
||||
}
|
||||
}
|
||||
else if (type2 == STTYPE_STRING) {
|
||||
if (type2 == STTYPE_STRING) {
|
||||
fvalue = dfilter_fvalue_from_string(dfw, ftype1, st_arg2, hfinfo1);
|
||||
}
|
||||
else {
|
||||
|
@ -778,7 +715,6 @@ check_relation_LHS_SLICE(dfwork_t *dfw, test_op_t st_op,
|
|||
|
||||
check_slice_sanity(dfw, st_arg1, FT_NONE);
|
||||
|
||||
again:
|
||||
type2 = stnode_type_id(st_arg2);
|
||||
|
||||
if (IS_FIELD_ENTITY(type2)) {
|
||||
|
@ -799,14 +735,6 @@ again:
|
|||
fvalue = dfilter_fvalue_from_string(dfw, FT_BYTES, st_arg2, NULL);
|
||||
stnode_replace(st_arg2, STTYPE_FVALUE, fvalue);
|
||||
}
|
||||
else if (type2 == STTYPE_UNPARSED) {
|
||||
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;
|
||||
}
|
||||
stnode_replace(st_arg2, STTYPE_FVALUE, fvalue);
|
||||
}
|
||||
else if (type2 == STTYPE_LITERAL) {
|
||||
fvalue = dfilter_fvalue_from_literal(dfw, FT_BYTES, st_arg2, allow_partial_value, NULL);
|
||||
stnode_replace(st_arg2, STTYPE_FVALUE, fvalue);
|
||||
|
@ -875,7 +803,6 @@ check_relation_LHS_FUNCTION(dfwork_t *dfw, test_op_t st_op,
|
|||
stnode_todisplay(st_node));
|
||||
}
|
||||
|
||||
again:
|
||||
type2 = stnode_type_id(st_arg2);
|
||||
|
||||
if (IS_FIELD_ENTITY(type2)) {
|
||||
|
@ -896,14 +823,6 @@ again:
|
|||
fvalue = dfilter_fvalue_from_string(dfw, ftype1, st_arg2, NULL);
|
||||
stnode_replace(st_arg2, STTYPE_FVALUE, fvalue);
|
||||
}
|
||||
else if (type2 == STTYPE_UNPARSED) {
|
||||
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;
|
||||
}
|
||||
stnode_replace(st_arg2, STTYPE_FVALUE, fvalue);
|
||||
}
|
||||
else if (type2 == STTYPE_LITERAL) {
|
||||
fvalue = dfilter_fvalue_from_literal(dfw, ftype1, st_arg2, allow_partial_value, NULL);
|
||||
stnode_replace(st_arg2, STTYPE_FVALUE, fvalue);
|
||||
|
@ -1001,8 +920,6 @@ check_relation(dfwork_t *dfw, test_op_t st_op,
|
|||
{
|
||||
LOG_NODE(st_node);
|
||||
|
||||
dfw_resolve_unparsed(dfw, st_arg1);
|
||||
|
||||
switch (stnode_type_id(st_arg1)) {
|
||||
case STTYPE_FIELD:
|
||||
case STTYPE_REFERENCE:
|
||||
|
@ -1033,8 +950,6 @@ check_relation_contains(dfwork_t *dfw, stnode_t *st_node,
|
|||
{
|
||||
LOG_NODE(st_node);
|
||||
|
||||
dfw_resolve_unparsed(dfw, st_arg1);
|
||||
|
||||
switch (stnode_type_id(st_arg1)) {
|
||||
case STTYPE_FIELD:
|
||||
case STTYPE_REFERENCE:
|
||||
|
@ -1066,8 +981,6 @@ check_relation_matches(dfwork_t *dfw, stnode_t *st_node,
|
|||
|
||||
LOG_NODE(st_node);
|
||||
|
||||
dfw_resolve_unparsed(dfw, st_arg1);
|
||||
|
||||
if (stnode_type_id(st_arg2) != STTYPE_STRING) {
|
||||
FAIL(dfw, st_arg2, "Matches requires a double quoted string on the right side.");
|
||||
}
|
||||
|
@ -1113,8 +1026,6 @@ check_relation_in(dfwork_t *dfw, stnode_t *st_node _U_,
|
|||
|
||||
LOG_NODE(st_node);
|
||||
|
||||
dfw_resolve_unparsed(dfw, st_arg1);
|
||||
|
||||
if (stnode_type_id(st_arg1) != STTYPE_FIELD) {
|
||||
FAIL(dfw, st_arg1, "Only a field may be tested for membership in a set.");
|
||||
}
|
||||
|
@ -1216,7 +1127,6 @@ check_arithmetic_entity(dfwork_t *dfw, stnode_t *st_arg, ftenum_t lhs_ftype)
|
|||
* is none we must have been passed an entity with a definite type
|
||||
* (field, function, etc). */
|
||||
|
||||
dfw_resolve_unparsed(dfw, st_arg);
|
||||
type = stnode_type_id(st_arg);
|
||||
|
||||
if (type == STTYPE_LITERAL) {
|
||||
|
@ -1264,7 +1174,6 @@ check_arithmetic_expr(dfwork_t *dfw, stnode_t *st_node, ftenum_t lhs_ftype)
|
|||
}
|
||||
|
||||
sttype_test_get(st_node, &st_op, &st_arg1, &st_arg2);
|
||||
dfw_resolve_unparsed(dfw, st_arg1);
|
||||
|
||||
/* On the LHS we require a field-like value as the first term. */
|
||||
if (lhs_ftype == FT_NONE && node_is_constant(st_arg1)) {
|
||||
|
|
|
@ -61,15 +61,6 @@ sttype_register_string(void)
|
|||
gstring_tostr
|
||||
};
|
||||
|
||||
static sttype_t unparsed_type = {
|
||||
STTYPE_UNPARSED,
|
||||
"UNPARSED",
|
||||
NULL,
|
||||
string_free,
|
||||
string_dup,
|
||||
string_tostr
|
||||
};
|
||||
|
||||
static sttype_t literal_type = {
|
||||
STTYPE_LITERAL,
|
||||
"LITERAL",
|
||||
|
@ -80,7 +71,6 @@ sttype_register_string(void)
|
|||
};
|
||||
|
||||
sttype_register(&string_type);
|
||||
sttype_register(&unparsed_type);
|
||||
sttype_register(&literal_type);
|
||||
}
|
||||
|
||||
|
|
|
@ -102,7 +102,7 @@ stnode_clear(stnode_t *node)
|
|||
}
|
||||
|
||||
void
|
||||
stnode_init(stnode_t *node, sttype_id_t type_id, gpointer data, char *token, stloc_t *loc)
|
||||
stnode_init(stnode_t *node, sttype_id_t type_id, gpointer data, char *token, const stloc_t *loc)
|
||||
{
|
||||
sttype_t *type;
|
||||
|
||||
|
@ -149,7 +149,7 @@ stnode_replace(stnode_t *node, sttype_id_t type_id, gpointer data)
|
|||
}
|
||||
|
||||
stnode_t*
|
||||
stnode_new(sttype_id_t type_id, gpointer data, char *token, stloc_t *loc)
|
||||
stnode_new(sttype_id_t type_id, gpointer data, char *token, const stloc_t *loc)
|
||||
{
|
||||
stnode_t *node;
|
||||
|
||||
|
|
|
@ -24,7 +24,6 @@ typedef enum {
|
|||
STTYPE_UNINITIALIZED,
|
||||
STTYPE_TEST,
|
||||
STTYPE_LITERAL,
|
||||
STTYPE_UNPARSED,
|
||||
STTYPE_REFERENCE,
|
||||
STTYPE_STRING,
|
||||
STTYPE_CHARCONST,
|
||||
|
@ -120,7 +119,7 @@ void
|
|||
sttype_register(sttype_t *type);
|
||||
|
||||
stnode_t*
|
||||
stnode_new(sttype_id_t type_id, gpointer data, char *token, stloc_t *loc);
|
||||
stnode_new(sttype_id_t type_id, gpointer data, char *token, const stloc_t *loc);
|
||||
|
||||
stnode_t*
|
||||
stnode_dup(const stnode_t *org);
|
||||
|
@ -129,7 +128,7 @@ void
|
|||
stnode_clear(stnode_t *node);
|
||||
|
||||
void
|
||||
stnode_init(stnode_t *node, sttype_id_t type_id, gpointer data, char *token, stloc_t *loc);
|
||||
stnode_init(stnode_t *node, sttype_id_t type_id, gpointer data, char *token, const stloc_t *loc);
|
||||
|
||||
void
|
||||
stnode_replace(stnode_t *node, sttype_id_t type_id, gpointer data);
|
||||
|
|
26
epan/proto.c
26
epan/proto.c
|
@ -7425,12 +7425,38 @@ proto_tree_set_appendix(proto_tree *tree, tvbuff_t *tvb, gint start,
|
|||
static void
|
||||
check_protocol_filter_name_or_fail(const char *filter_name)
|
||||
{
|
||||
/* Require at least two characters. */
|
||||
if (filter_name[0] == '\0' || filter_name[1] == '\0') {
|
||||
REPORT_DISSECTOR_BUG("Protocol filter name \"%s\" cannot have length less than two.", filter_name);
|
||||
}
|
||||
|
||||
if (proto_check_field_name(filter_name) != '\0') {
|
||||
REPORT_DISSECTOR_BUG("Protocol filter name \"%s\" has one or more invalid characters."
|
||||
" Allowed are letters, digits, '-', '_' and non-repeating '.'."
|
||||
" This might be caused by an inappropriate plugin or a development error.", filter_name);
|
||||
}
|
||||
|
||||
/* Check that it doesn't match some very common numeric forms. */
|
||||
if (filter_name[0] == '0' &&
|
||||
(filter_name[1] == 'x' || filter_name[1] == 'X' ||
|
||||
filter_name[1] == 'b' || filter_name[1] == 'B')) {
|
||||
REPORT_DISSECTOR_BUG("Protocol filter name \"%s\" cannot start with \"%c%c\".",
|
||||
filter_name, filter_name[0], filter_name[1]);
|
||||
}
|
||||
|
||||
/* Check that it doesn't have all decimal digits. */
|
||||
bool all_digits = true;
|
||||
for (const char *s = filter_name; *s != '\0'; s++) {
|
||||
if (!g_ascii_isdigit(*s)) {
|
||||
all_digits = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (all_digits) {
|
||||
REPORT_DISSECTOR_BUG("Protocol filter name \"%s\" cannot be composed of all decimal digits.",
|
||||
filter_name);
|
||||
}
|
||||
|
||||
/* Check for reserved keywords. */
|
||||
if (g_hash_table_contains(proto_reserved_filter_names, filter_name)) {
|
||||
REPORT_DISSECTOR_BUG("Protocol filter name \"%s\" is invalid because it is a reserved keyword."
|
||||
|
|
|
@ -167,20 +167,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):
|
||||
def test_rhs_bias_1(self, checkDFilterCount):
|
||||
# Protocol "Fibre Channel" on the RHS
|
||||
dfilter = 'frame[37] == fc'
|
||||
checkDFilterCount(dfilter, 1)
|
||||
checkDFilterCount(dfilter, 0)
|
||||
|
||||
def test_rhs_literal_bias_2(self, checkDFilterCount):
|
||||
def test_rhs_bias_2(self, checkDFilterCount):
|
||||
# Byte 0xFC on the RHS
|
||||
dfilter = 'frame[37] == :fc'
|
||||
checkDFilterCount(dfilter, 1)
|
||||
|
||||
def test_rhs_literal_bias_3(self, checkDFilterCount):
|
||||
# Byte 0xFC on the RHS
|
||||
dfilter = 'frame[37] == <fc>'
|
||||
checkDFilterCount(dfilter, 1)
|
||||
|
||||
def test_rhs_literal_bias_4(self, checkDFilterCount):
|
||||
# This is Fibre Channel on the RHS
|
||||
# Protocol "Fibre Channel" on the RHS
|
||||
dfilter = 'frame[37] == .fc'
|
||||
checkDFilterCount(dfilter, 0)
|
||||
|
||||
|
|
Loading…
Reference in New Issue