diff options
author | João Valverde <j@v6e.pt> | 2021-09-26 22:22:50 +0100 |
---|---|---|
committer | Wireshark GitLab Utility <gerald+gitlab-utility@wireshark.org> | 2021-10-01 16:04:37 +0000 |
commit | db18865e5517484ed7ce3aebc2e8695d5bf7bedf (patch) | |
tree | 9f26806ce246b0cf4f987c541a196acc4aa784de /epan/dfilter | |
parent | 487e2b6bc3c204559fa6502f06c33c2383cd5e90 (diff) |
dfilter: Save token value to syntax tree
When parsing we save the token value to the syntax tree. This is
useful for better error reporting. Use it to report an invalid
entity for the slice operation. Before only the memory location
was reported, which is not a good error message.
Before:
% dftest '"01:02:03:04"[0:3] == foo'
Filter: ""01:02:03:04"[0:3] == foo"
dftest: Range is not supported for entity <0x7f6c84017740> of type STRING
After:
% dftest '"01:02:03:04"[0:3] == foo'
Filter: ""01:02:03:04"[0:3] == foo"
dftest: Range is not supported for entity 01:02:03:04 of type STRING
When creating a new node from an old one we need to copy the token
value. Simple tokens such as RBRACKET, COMMA and COLON are
not part of the AST and don't have an associated semantic value.
Diffstat (limited to 'epan/dfilter')
-rw-r--r-- | epan/dfilter/dfilter.c | 2 | ||||
-rw-r--r-- | epan/dfilter/grammar.lemon | 20 | ||||
-rw-r--r-- | epan/dfilter/scanner.l | 62 | ||||
-rw-r--r-- | epan/dfilter/semcheck.c | 53 | ||||
-rw-r--r-- | epan/dfilter/syntax-tree.c | 24 | ||||
-rw-r--r-- | epan/dfilter/syntax-tree.h | 11 |
6 files changed, 101 insertions, 71 deletions
diff --git a/epan/dfilter/dfilter.c b/epan/dfilter/dfilter.c index e093668d88..84822b3924 100644 --- a/epan/dfilter/dfilter.c +++ b/epan/dfilter/dfilter.c @@ -311,7 +311,7 @@ dfilter_compile(const gchar *text, dfilter_t **dfp, gchar **err_msg) df_set_extra(&state, scanner); while (1) { - df_lval = stnode_new(STTYPE_UNINITIALIZED, NULL); + df_lval = stnode_new(STTYPE_UNINITIALIZED, NULL, NULL); token = df_lex(scanner); /* Check for scanner failure */ diff --git a/epan/dfilter/grammar.lemon b/epan/dfilter/grammar.lemon index 814c0e3cc4..66158129be 100644 --- a/epan/dfilter/grammar.lemon +++ b/epan/dfilter/grammar.lemon @@ -152,25 +152,25 @@ expr(X) ::= logical_test(L). { X = L; } /* Logical tests */ logical_test(T) ::= expr(E) TEST_AND expr(F). { - T = stnode_new(STTYPE_TEST, NULL); + T = stnode_new(STTYPE_TEST, NULL, NULL); sttype_test_set2(T, TEST_OP_AND, E, F); } logical_test(T) ::= expr(E) TEST_OR expr(F). { - T = stnode_new(STTYPE_TEST, NULL); + T = stnode_new(STTYPE_TEST, NULL, NULL); sttype_test_set2(T, TEST_OP_OR, E, F); } logical_test(T) ::= TEST_NOT expr(E). { - T = stnode_new(STTYPE_TEST, NULL); + T = stnode_new(STTYPE_TEST, NULL, NULL); sttype_test_set1(T, TEST_OP_NOT, E); } logical_test(T) ::= entity(E). { - T = stnode_new(STTYPE_TEST, NULL); + T = stnode_new(STTYPE_TEST, NULL, NULL); sttype_test_set1(T, TEST_OP_EXISTS, E); } @@ -190,7 +190,7 @@ range_body(B) ::= range(R). { B = R; } /* Ranges */ range(R) ::= range_body(B) LBRACKET drnode_list(L) RBRACKET. { - R = stnode_new(STTYPE_RANGE, NULL); + R = stnode_new(STTYPE_RANGE, NULL, NULL); sttype_range_set(R, B, L); /* Delete the list, but not the drange_nodes that @@ -266,7 +266,7 @@ drnode(D) ::= INTEGER(X). /* Relational tests */ relation_test(T) ::= entity(E) rel_op2(O) entity(F). { - T = stnode_new(STTYPE_TEST, NULL); + T = stnode_new(STTYPE_TEST, NULL, NULL); sttype_test_set2(T, O, E, F); } @@ -284,10 +284,10 @@ relation_test(T) ::= entity(E) rel_op2(O) relation_test(R). sttype_test_get(F, NULL, &F, NULL); } while (stnode_type_id(F) == STTYPE_TEST); - L = stnode_new(STTYPE_TEST, NULL); + L = stnode_new(STTYPE_TEST, NULL, NULL); sttype_test_set2(L, O, E, stnode_dup(F)); - T = stnode_new(STTYPE_TEST, NULL); + T = stnode_new(STTYPE_TEST, NULL, NULL); sttype_test_set2(T, TEST_OP_AND, L, R); } @@ -304,8 +304,8 @@ rel_op2(O) ::= TEST_MATCHES. { O = TEST_OP_MATCHES; } relation_test(T) ::= entity(E) TEST_IN LBRACE setnode_list(L) RBRACE. { stnode_t *S; - T = stnode_new(STTYPE_TEST, NULL); - S = stnode_new(STTYPE_SET, L); + T = stnode_new(STTYPE_TEST, NULL, NULL); + S = stnode_new(STTYPE_SET, L, NULL); sttype_test_set2(T, TEST_OP_IN, E, S); } diff --git a/epan/dfilter/scanner.l b/epan/dfilter/scanner.l index 1a50d1200d..0ff0d906be 100644 --- a/epan/dfilter/scanner.l +++ b/epan/dfilter/scanner.l @@ -84,10 +84,12 @@ DIAG_OFF_FLEX /*#undef YY_NO_UNPUT*/ -static int set_lval(int token, gpointer data); -static int set_lval_int(dfwork_t *dfw, int token, char *s); +static int set_lval_str(int token, const char *token_value); +static int set_lval_field(int token, header_field_info *hfinfo, const char *token_value); +static int set_lval_func(int token, df_func_def_t *func, const char *token_value); +static int set_lval_int(dfwork_t *dfw, int token, const char *token_value); static int simple(int token); -static gboolean str_to_gint32(dfwork_t *dfw, char *s, gint32* pint); +static gboolean str_to_gint32(dfwork_t *dfw, const char *s, gint32* pint); /* * Sleazy hack to suppress compiler warnings in yy_fatal_error(). @@ -269,7 +271,7 @@ static gboolean str_to_gint32(dfwork_t *dfw, char *s, gint32* pint); /* end quote */ int token; BEGIN(INITIAL); - token = set_lval(TOKEN_STRING, yyextra->quoted_string->str); + token = set_lval_str(TOKEN_STRING, yyextra->quoted_string->str); g_string_free(yyextra->quoted_string, TRUE); yyextra->quoted_string = NULL; return token; @@ -371,7 +373,7 @@ static gboolean str_to_gint32(dfwork_t *dfw, char *s, gint32* pint); int token; BEGIN(INITIAL); g_string_append_c(yyextra->quoted_string, '\''); - token = set_lval(TOKEN_CHARCONST, yyextra->quoted_string->str); + token = set_lval_str(TOKEN_CHARCONST, yyextra->quoted_string->str); g_string_free(yyextra->quoted_string, TRUE); yyextra->quoted_string = NULL; return token; @@ -391,7 +393,7 @@ static gboolean str_to_gint32(dfwork_t *dfw, char *s, gint32* pint); [-[:alnum:]_\.:]*\/[[:digit:]]+ { /* CIDR */ - return set_lval(TOKEN_UNPARSED, yytext); + return set_lval_str(TOKEN_UNPARSED, yytext); } ([.][-+[:alnum:]_:]+)+[.]{0,2} | @@ -409,30 +411,28 @@ static gboolean str_to_gint32(dfwork_t *dfw, char *s, gint32* pint); hfinfo = proto_registrar_get_byname(yytext); if (hfinfo) { /* Yes, it's a field name */ - return set_lval(TOKEN_FIELD, hfinfo); + return set_lval_field(TOKEN_FIELD, hfinfo, yytext); } hfinfo = proto_registrar_get_byalias(yytext); if (hfinfo) { /* Yes, it's an aliased field name */ - /* XXX Do we need to make a copy of yytext? dfilter_compile - * will dup this later on. */ add_deprecated_token(yyextra->deprecated, yytext); - return set_lval(TOKEN_FIELD, hfinfo); + return set_lval_field(TOKEN_FIELD, hfinfo, yytext); } df_func_def = df_func_lookup(yytext); if (df_func_def) { /* Yes, it's a dfilter function */ - return set_lval(TOKEN_FUNCTION, df_func_def); + return set_lval_func(TOKEN_FUNCTION, df_func_def, yytext); } /* No match, so treat it as an unparsed string */ - return set_lval(TOKEN_UNPARSED, yytext); + return set_lval_str(TOKEN_UNPARSED, yytext); } . { /* Default */ - return set_lval(TOKEN_UNPARSED, yytext); + return set_lval_str(TOKEN_UNPARSED, yytext); } @@ -479,9 +479,9 @@ simple(int token) } static int -set_lval(int token, gpointer data) +set_lval_str(int token, const char *token_value) { - sttype_id_t type_id = STTYPE_UNINITIALIZED; + sttype_id_t type_id; switch (token) { case TOKEN_STRING: @@ -490,29 +490,39 @@ set_lval(int token, gpointer data) case TOKEN_CHARCONST: type_id = STTYPE_CHARCONST; break; - case TOKEN_FIELD: - type_id = STTYPE_FIELD; - break; case TOKEN_UNPARSED: type_id = STTYPE_UNPARSED; break; - case TOKEN_FUNCTION: - type_id = STTYPE_FUNCTION; - break; default: ws_assert_not_reached(); } - stnode_init(df_lval, type_id, data); + stnode_init(df_lval, type_id, (gpointer)token_value, token_value); + return token; +} + +static int +set_lval_field(int token, header_field_info *hfinfo, const char *token_value) +{ + ws_assert(token == TOKEN_FIELD); + stnode_init(df_lval, STTYPE_FIELD, hfinfo, token_value); + return token; +} + +static int +set_lval_func(int token, df_func_def_t *func, const char *token_value) +{ + ws_assert(token == TOKEN_FUNCTION); + stnode_init(df_lval, STTYPE_FUNCTION, func, token_value); return token; } static int -set_lval_int(dfwork_t *dfw, int token, char *s) +set_lval_int(dfwork_t *dfw, int token, const char *token_value) { sttype_id_t type_id = STTYPE_UNINITIALIZED; gint32 val; - if (!str_to_gint32(dfw, s, &val)) { + if (!str_to_gint32(dfw, token_value, &val)) { return SCAN_FAILED; } @@ -524,13 +534,13 @@ set_lval_int(dfwork_t *dfw, int token, char *s) ws_assert_not_reached(); } - stnode_init_int(df_lval, type_id, val); + stnode_init_int(df_lval, type_id, val, token_value); return token; } static gboolean -str_to_gint32(dfwork_t *dfw, char *s, gint32* pint) +str_to_gint32(dfwork_t *dfw, const char *s, gint32* pint) { char *endptr; long integer; diff --git a/epan/dfilter/semcheck.c b/epan/dfilter/semcheck.c index 86d689c7b0..86ab74fb16 100644 --- a/epan/dfilter/semcheck.c +++ b/epan/dfilter/semcheck.c @@ -593,7 +593,7 @@ convert_to_bytes(stnode_t *arg) stnode_t *new_st; drange_node *rn; - new_st = stnode_new(STTYPE_RANGE, NULL); + new_st = stnode_new(STTYPE_RANGE, NULL, arg->token_value); rn = drange_node_new(); drange_node_set_start_offset(rn, 0); @@ -714,7 +714,7 @@ check_relation_LHS_FIELD(dfwork_t *dfw, const char *relation_string, if (!pcre) { THROW(TypeError); } - new_st = stnode_new(STTYPE_PCRE, pcre); + new_st = stnode_new(STTYPE_PCRE, pcre, st_arg2->token_value); } else { /* Skip incompatible fields */ while (hfinfo1->same_name_prev_id != -1 && @@ -756,7 +756,7 @@ check_relation_LHS_FIELD(dfwork_t *dfw, const char *relation_string, if (!fvalue) { THROW(TypeError); } - new_st = stnode_new(STTYPE_FVALUE, fvalue); + new_st = stnode_new(STTYPE_FVALUE, fvalue, st_arg2->token_value); } if (stnode_type_id(st_node) == STTYPE_TEST) { sttype_test_set2_args(st_node, st_arg1, new_st); @@ -887,7 +887,7 @@ check_relation_LHS_STRING(dfwork_t *dfw, const char* relation_string, } } - new_st = stnode_new(STTYPE_FVALUE, fvalue); + new_st = stnode_new(STTYPE_FVALUE, fvalue, st_arg1->token_value); sttype_test_set2_args(st_node, new_st, st_arg2); stnode_free(st_arg1); } @@ -906,7 +906,7 @@ check_relation_LHS_STRING(dfwork_t *dfw, const char* relation_string, if (!fvalue) { THROW(TypeError); } - new_st = stnode_new(STTYPE_FVALUE, fvalue); + new_st = stnode_new(STTYPE_FVALUE, fvalue, st_arg1->token_value); sttype_test_set2_args(st_node, new_st, st_arg2); stnode_free(st_arg1); } @@ -929,7 +929,7 @@ check_relation_LHS_STRING(dfwork_t *dfw, const char* relation_string, check_function(dfw, st_arg2); - new_st = stnode_new(STTYPE_FVALUE, fvalue); + new_st = stnode_new(STTYPE_FVALUE, fvalue, st_arg1->token_value); sttype_test_set2_args(st_node, new_st, st_arg2); stnode_free(st_arg1); } @@ -981,7 +981,7 @@ check_relation_LHS_UNPARSED(dfwork_t *dfw, const char* relation_string, } } - new_st = stnode_new(STTYPE_FVALUE, fvalue); + new_st = stnode_new(STTYPE_FVALUE, fvalue, st_arg1->token_value); sttype_test_set2_args(st_node, new_st, st_arg2); stnode_free(st_arg1); } @@ -1000,7 +1000,7 @@ check_relation_LHS_UNPARSED(dfwork_t *dfw, const char* relation_string, if (!fvalue) { THROW(TypeError); } - new_st = stnode_new(STTYPE_FVALUE, fvalue); + new_st = stnode_new(STTYPE_FVALUE, fvalue, st_arg1->token_value); sttype_test_set2_args(st_node, new_st, st_arg2); stnode_free(st_arg1); } @@ -1023,7 +1023,7 @@ check_relation_LHS_UNPARSED(dfwork_t *dfw, const char* relation_string, check_function(dfw, st_arg2); - new_st = stnode_new(STTYPE_FVALUE, fvalue); + new_st = stnode_new(STTYPE_FVALUE, fvalue, st_arg1->token_value); sttype_test_set2_args(st_node, new_st, st_arg2); stnode_free(st_arg1); } @@ -1078,13 +1078,12 @@ check_relation_LHS_RANGE(dfwork_t *dfw, const char *relation_string, 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 { - if (entity1 == NULL) { - dfilter_fail(dfw, "Range is not supported, details: " G_STRLOC " entity: NULL"); - } else { - dfilter_fail(dfw, "Range is not supported, details: " G_STRLOC " entity: %p of type %d", - (void *)entity1, stnode_type_id(entity1)); - } + dfilter_fail(dfw, "Range is not supported, details: " G_STRLOC " entity: NULL"); THROW(TypeError); } @@ -1118,13 +1117,13 @@ check_relation_LHS_RANGE(dfwork_t *dfw, const char *relation_string, if (!pcre) { THROW(TypeError); } - new_st = stnode_new(STTYPE_PCRE, pcre); + new_st = stnode_new(STTYPE_PCRE, pcre, st_arg2->token_value); } else { fvalue = dfilter_fvalue_from_string(dfw, FT_BYTES, s); if (!fvalue) { THROW(TypeError); } - new_st = stnode_new(STTYPE_FVALUE, fvalue); + new_st = stnode_new(STTYPE_FVALUE, fvalue, st_arg2->token_value); } sttype_test_set2_args(st_node, st_arg1, new_st); stnode_free(st_arg2); @@ -1139,7 +1138,7 @@ check_relation_LHS_RANGE(dfwork_t *dfw, const char *relation_string, if (!pcre) { THROW(TypeError); } - new_st = stnode_new(STTYPE_PCRE, pcre); + new_st = stnode_new(STTYPE_PCRE, pcre, st_arg2->token_value); } else { /* * The RHS should be FT_BYTES. However, there is a @@ -1176,7 +1175,7 @@ check_relation_LHS_RANGE(dfwork_t *dfw, const char *relation_string, if (!fvalue) { THROW(TypeError); } - new_st = stnode_new(STTYPE_FVALUE, fvalue); + new_st = stnode_new(STTYPE_FVALUE, fvalue, st_arg2->token_value); } sttype_test_set2_args(st_node, st_arg1, new_st); stnode_free(st_arg2); @@ -1190,7 +1189,7 @@ check_relation_LHS_RANGE(dfwork_t *dfw, const char *relation_string, if (!pcre) { THROW(TypeError); } - new_st = stnode_new(STTYPE_PCRE, pcre); + new_st = stnode_new(STTYPE_PCRE, pcre, st_arg2->token_value); } else { /* The RHS should be FT_BYTES, but a character is just a * one-byte byte string. */ @@ -1198,7 +1197,7 @@ check_relation_LHS_RANGE(dfwork_t *dfw, const char *relation_string, if (!fvalue) { THROW(TypeError); } - new_st = stnode_new(STTYPE_FVALUE, fvalue); + new_st = stnode_new(STTYPE_FVALUE, fvalue, st_arg2->token_value); } sttype_test_set2_args(st_node, st_arg1, new_st); stnode_free(st_arg2); @@ -1253,7 +1252,7 @@ check_param_entity(dfwork_t *dfw, stnode_t *st_node) THROW(TypeError); } - new_st = stnode_new(STTYPE_FVALUE, fvalue); + new_st = stnode_new(STTYPE_FVALUE, fvalue, st_node->token_value); stnode_free(st_node); return new_st; } @@ -1322,13 +1321,13 @@ check_relation_LHS_FUNCTION(dfwork_t *dfw, const char *relation_string, if (!pcre) { THROW(TypeError); } - new_st = stnode_new(STTYPE_PCRE, pcre); + new_st = stnode_new(STTYPE_PCRE, pcre, st_arg2->token_value); } else { fvalue = dfilter_fvalue_from_string(dfw, ftype1, s); if (!fvalue) { THROW(TypeError); } - new_st = stnode_new(STTYPE_FVALUE, fvalue); + new_st = stnode_new(STTYPE_FVALUE, fvalue, st_arg2->token_value); } sttype_test_set2_args(st_node, st_arg1, new_st); stnode_free(st_arg2); @@ -1341,13 +1340,13 @@ check_relation_LHS_FUNCTION(dfwork_t *dfw, const char *relation_string, if (!pcre) { THROW(TypeError); } - new_st = stnode_new(STTYPE_PCRE, pcre); + new_st = stnode_new(STTYPE_PCRE, pcre, st_arg2->token_value); } else { fvalue = dfilter_fvalue_from_unparsed(dfw, ftype1, s, allow_partial_value); if (!fvalue) { THROW(TypeError); } - new_st = stnode_new(STTYPE_FVALUE, fvalue); + new_st = stnode_new(STTYPE_FVALUE, fvalue, st_arg2->token_value); } sttype_test_set2_args(st_node, st_arg1, new_st); stnode_free(st_arg2); @@ -1450,7 +1449,7 @@ check_relation(dfwork_t *dfw, const char *relation_string, * functions will take care of it as if it didn't * match a protocol string. */ - new_st = stnode_new(STTYPE_UNPARSED, s); + new_st = stnode_new(STTYPE_UNPARSED, s, st_arg2->token_value); stnode_free(st_arg2); st_arg2 = new_st; sttype_test_set2_args(st_node, st_arg1, new_st); diff --git a/epan/dfilter/syntax-tree.c b/epan/dfilter/syntax-tree.c index 09388eb7c0..047aae25d6 100644 --- a/epan/dfilter/syntax-tree.c +++ b/epan/dfilter/syntax-tree.c @@ -78,7 +78,7 @@ sttype_lookup(sttype_id_t type_id) stnode_t* -stnode_new(sttype_id_t type_id, gpointer data) +stnode_new(sttype_id_t type_id, gpointer data, const char *token_value) { sttype_t *type; stnode_t *node; @@ -102,6 +102,7 @@ stnode_new(sttype_id_t type_id, gpointer data) } } + node->token_value = g_strdup(token_value); return node; } @@ -119,6 +120,7 @@ stnode_dup(const stnode_t *org) node = g_new(stnode_t, 1); node->magic = STNODE_MAGIC; + node->type = type; node->flags = org->flags; @@ -128,17 +130,20 @@ stnode_dup(const stnode_t *org) node->data = org->data; node->value = org->value; + node->token_value = g_strdup(org->token_value); + return node; } void -stnode_init(stnode_t *node, sttype_id_t type_id, gpointer data) +stnode_init(stnode_t *node, sttype_id_t type_id, gpointer data, const char *token_value) { sttype_t *type; ws_assert_magic(node, STNODE_MAGIC); ws_assert(!node->type); ws_assert(!node->data); + ws_assert(!node->token_value); type = sttype_lookup(type_id); ws_assert(type); @@ -152,12 +157,13 @@ stnode_init(stnode_t *node, sttype_id_t type_id, gpointer data) node->data = data; } node->value = 0; + node->token_value = g_strdup(token_value); } void -stnode_init_int(stnode_t *node, sttype_id_t type_id, gint32 value) +stnode_init_int(stnode_t *node, sttype_id_t type_id, gint32 value, const char *token_value) { - stnode_init(node, type_id, NULL); + stnode_init(node, type_id, NULL, token_value); node->value = value; } @@ -173,6 +179,7 @@ stnode_free(stnode_t *node) else { ws_assert(!node->data); } + g_free(node->token_value); g_free(node); } @@ -338,6 +345,15 @@ visit_tree(wmem_strbuf_t *buf, stnode_t *node, int level) } } +const char * +stnode_token_value(stnode_t *node) +{ + if (node->token_value) { + return node->token_value; + } + return "<unknown token>"; +} + void log_syntax_tree(enum ws_log_level level, stnode_t *root, const char *msg) { diff --git a/epan/dfilter/syntax-tree.h b/epan/dfilter/syntax-tree.h index 47b9893f41..afae6c0834 100644 --- a/epan/dfilter/syntax-tree.h +++ b/epan/dfilter/syntax-tree.h @@ -62,6 +62,8 @@ typedef struct { * set aside to time to do so. */ gpointer data; int32_t value; + + char *token_value; } stnode_t; /* These are the sttype_t registration function prototypes. */ @@ -83,16 +85,16 @@ void sttype_register(sttype_t *type); stnode_t* -stnode_new(sttype_id_t type_id, gpointer data); +stnode_new(sttype_id_t type_id, gpointer data, const char *token_value); stnode_t* stnode_dup(const stnode_t *org); void -stnode_init(stnode_t *node, sttype_id_t type_id, gpointer data); +stnode_init(stnode_t *node, sttype_id_t type_id, gpointer data, const char *token_value); void -stnode_init_int(stnode_t *node, sttype_id_t type_id, gint32 value); +stnode_init_int(stnode_t *node, sttype_id_t type_id, gint32 value, const char *token_value); void stnode_free(stnode_t *node); @@ -118,6 +120,9 @@ stnode_tostr(stnode_t *node); gboolean stnode_inside_parens(stnode_t *node); +const char * +stnode_token_value(stnode_t *node); + void stnode_set_inside_parens(stnode_t *node, gboolean inside); |