From cfcbb286712ae392689e7cd1a640b57b611dd277 Mon Sep 17 00:00:00 2001 From: Guy Harris Date: Sun, 18 Jan 2015 02:22:19 -0800 Subject: [PATCH] Clean up ftype-conversion and dfilter error message string handling. Have dfilter_compile() take an additional gchar ** argument, pointing to a gchar * item that, on error, gets set to point to a g_malloc()ed error string. That removes one bit of global state from the display filter parser, and doesn't impose a fixed limit on the error message strings. Have fvalue_from_string() and fvalue_from_unparsed() take a gchar ** argument, pointer to a gchar * item, rather than an error-reporting function, and set the gchar * item to point to a g_malloc()ed error string on an error. Allow either gchar ** argument to be null; if the argument is null, no error message is allocated or provided. Change-Id: Ibd36b8aaa9bf4234aa6efa1e7fb95f7037493b4c Reviewed-on: https://code.wireshark.org/review/6608 Reviewed-by: Guy Harris --- color_filters.c | 24 ++- dftest.c | 6 +- echld/child.c | 20 ++- epan/column.c | 2 +- epan/dfilter/dfilter-int.h | 11 +- epan/dfilter/dfilter-macro.c | 47 +++-- epan/dfilter/dfilter.c | 63 ++++--- epan/dfilter/dfilter.h | 20 +-- epan/dfilter/dfunctions.c | 12 +- epan/dfilter/dfunctions.h | 2 +- epan/dfilter/grammar.lemon | 16 +- epan/dfilter/scanner.l | 34 ++-- epan/dfilter/semcheck.c | 268 ++++++++++++++++------------- epan/dfilter/sttype-function.h | 1 + epan/dissectors/packet-ncp2222.inc | 8 +- epan/ftypes/ftype-bytes.c | 137 ++++++++------- epan/ftypes/ftype-double.c | 16 +- epan/ftypes/ftype-guid.c | 5 +- epan/ftypes/ftype-integer.c | 135 +++++++-------- epan/ftypes/ftype-ipv4.c | 15 +- epan/ftypes/ftype-ipv6.c | 13 +- epan/ftypes/ftype-pcre.c | 16 +- epan/ftypes/ftype-string.c | 6 +- epan/ftypes/ftype-time.c | 16 +- epan/ftypes/ftype-tvbuff.c | 6 +- epan/ftypes/ftypes-int.h | 4 +- epan/ftypes/ftypes.c | 26 ++- epan/ftypes/ftypes.h | 6 +- epan/funnel.h | 2 +- epan/tap.c | 12 +- epan/wslua/wslua_field.c | 6 +- epan/wslua/wslua_gui.c | 7 +- file.c | 16 +- rawshark.c | 7 +- tfshark.c | 11 +- tshark.c | 13 +- ui/capture.c | 2 +- ui/gtk/capture_file_dlg.c | 12 +- ui/gtk/color_edit_dlg.c | 6 +- ui/gtk/dfilter_expr_dlg.c | 23 +-- ui/gtk/filter_dlg.c | 58 +++---- ui/gtk/find_dlg.c | 9 +- ui/gtk/funnel_stat.c | 13 +- ui/gtk/gui_utils.c | 5 +- ui/gtk/gui_utils.h | 5 +- ui/gtk/iax2_analysis.c | 6 +- ui/gtk/io_stat.c | 6 +- ui/gtk/main.c | 13 +- ui/gtk/main_menubar.c | 2 +- ui/gtk/rlc_lte_graph.c | 6 +- ui/gtk/rtp_analysis.c | 6 +- ui/gtk/sctp_assoc_analyse.c | 6 +- ui/qt/display_filter_edit.cpp | 6 +- ui/qt/io_graph_dialog.cpp | 6 +- ui/qt/main_window.cpp | 7 +- ui/qt/main_window_slots.cpp | 8 +- ui/qt/search_frame.cpp | 2 +- ui/qt/syntax_line_edit.cpp | 18 +- ui/qt/syntax_line_edit.h | 2 + ui/tap-tcp-stream.c | 6 +- 60 files changed, 699 insertions(+), 543 deletions(-) diff --git a/color_filters.c b/color_filters.c index d9e2ecfdc4..869a6e506d 100644 --- a/color_filters.c +++ b/color_filters.c @@ -150,6 +150,7 @@ color_filters_set_tmp(guint8 filt_nr, gchar *filter, gboolean disabled) GSList *cfl; color_filter_t *colorf; dfilter_t *compiled_filter; + gchar *err_msg; guint8 i; /* Go through the tomporary filters and look for the same filter string. @@ -174,10 +175,11 @@ color_filters_set_tmp(guint8 filt_nr, gchar *filter, gboolean disabled) * or if we found a matching filter string which need to be cleared */ tmpfilter = ( (filter==NULL) || (i!=filt_nr) ) ? "frame" : filter; - if (!dfilter_compile(tmpfilter, &compiled_filter)) { + if (!dfilter_compile(tmpfilter, &compiled_filter, &err_msg)) { simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "Could not compile color filter name: \"%s\"" - " text: \"%s\".\n%s", name, filter, dfilter_error_msg); + " text: \"%s\".\n%s", name, filter, err_msg); + g_free(err_msg); } else { if (colorf->filter_text != NULL) g_free(colorf->filter_text); @@ -339,12 +341,14 @@ static void color_filter_compile_cb(gpointer filter_arg, gpointer unused _U_) { color_filter_t *colorf = (color_filter_t *)filter_arg; + gchar *err_msg; g_assert(colorf->c_colorfilter == NULL); - if (!dfilter_compile(colorf->filter_text, &colorf->c_colorfilter)) { + if (!dfilter_compile(colorf->filter_text, &colorf->c_colorfilter, &err_msg)) { simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "Could not compile color filter name: \"%s\" text: \"%s\".\n%s", - colorf->filter_name, colorf->filter_text, dfilter_error_msg); + colorf->filter_name, colorf->filter_text, err_msg); + g_free(err_msg); /* this filter was compilable before, so this should never happen */ /* except if the OK button of the parent window has been clicked */ /* so don't use g_assert_not_reached() but check the filters again */ @@ -355,12 +359,14 @@ static void color_filter_validate_cb(gpointer filter_arg, gpointer unused _U_) { color_filter_t *colorf = (color_filter_t *)filter_arg; + gchar *err_msg; g_assert(colorf->c_colorfilter == NULL); - if (!dfilter_compile(colorf->filter_text, &colorf->c_colorfilter)) { + if (!dfilter_compile(colorf->filter_text, &colorf->c_colorfilter, &err_msg)) { simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "Removing color filter name: \"%s\" text: \"%s\".\n%s", - colorf->filter_name, colorf->filter_text, dfilter_error_msg); + colorf->filter_name, colorf->filter_text, err_msg); + g_free(err_msg); /* Delete the color filter from the list of color filters. */ color_filter_valid_list = g_slist_remove(color_filter_valid_list, colorf); color_filter_delete(colorf); @@ -566,10 +572,12 @@ read_filters_file(FILE *f, gpointer user_data) color_t bg_color, fg_color; color_filter_t *colorf; dfilter_t *temp_dfilter; + gchar *err_msg; - if (!dfilter_compile(filter_exp, &temp_dfilter)) { + if (!dfilter_compile(filter_exp, &temp_dfilter, &err_msg)) { g_warning("Could not compile \"%s\" in colorfilters file.\n%s", - name, dfilter_error_msg); + name, err_msg); + g_free(err_msg); prefs.unknown_colorfilters = TRUE; skip_end_of_line = TRUE; diff --git a/dftest.c b/dftest.c index 5c28cc6eeb..9945d3632a 100644 --- a/dftest.c +++ b/dftest.c @@ -60,6 +60,7 @@ main(int argc, char **argv) int gpf_open_errno, gpf_read_errno; int pf_open_errno, pf_read_errno; dfilter_t *df; + gchar *err_msg; /* * Get credential information for later use. @@ -144,8 +145,9 @@ main(int argc, char **argv) printf("Filter: \"%s\"\n", text); /* Compile it */ - if (!dfilter_compile(text, &df)) { - fprintf(stderr, "dftest: %s\n", dfilter_error_msg); + if (!dfilter_compile(text, &df, &err_msg)) { + fprintf(stderr, "dftest: %s\n", err_msg); + g_free(err_msg); epan_cleanup(); exit(2); } diff --git a/echld/child.c b/echld/child.c index 1441be0b20..9f24b85b36 100644 --- a/echld/child.c +++ b/echld/child.c @@ -230,21 +230,23 @@ static char* param_get_packet_count(char** err) { -static echld_bool_t param_set_dfilter(char* val , char** err _U_) { +static echld_bool_t param_set_dfilter(char* val , char** err) { dfilter_t *dfn = NULL; + gchar *err_msg; if (child.state != IDLE && child.state != DONE ) { *err = g_strdup("Only while idle or done"); return FALSE; - } else if ( dfilter_compile(val, &dfn) ) { - if (child.dfilter) g_free(child.dfilter); - if (child.df) dfilter_free(child.df); - child.df = dfn; - child.dfilter = g_strdup(val); - return TRUE; } else { - *err = g_strdup(dfilter_error_msg); - return FALSE; + if ( dfilter_compile(val, &dfn, err) ) { + if (child.dfilter) g_free(child.dfilter); + if (child.df) dfilter_free(child.df); + child.df = dfn; + child.dfilter = g_strdup(val); + return TRUE; + } else { + return FALSE; + } } } diff --git a/epan/column.c b/epan/column.c index c5aacd9777..503a2c120f 100644 --- a/epan/column.c +++ b/epan/column.c @@ -799,7 +799,7 @@ build_column_format_array(column_info *cinfo, const gint num_cols, const gboolea if (cinfo->col_fmt[i] == COL_CUSTOM) { cinfo->col_custom_field[i] = g_strdup(get_column_custom_field(i)); cinfo->col_custom_occurrence[i] = get_column_custom_occurrence(i); - if(!dfilter_compile(cinfo->col_custom_field[i], &cinfo->col_custom_dfilter[i])) { + if(!dfilter_compile(cinfo->col_custom_field[i], &cinfo->col_custom_dfilter[i], NULL)) { /* XXX: Should we issue a warning? */ g_free(cinfo->col_custom_field[i]); cinfo->col_custom_field[i] = NULL; diff --git a/epan/dfilter/dfilter-int.h b/epan/dfilter/dfilter-int.h index 8a7511de05..40e55488b5 100644 --- a/epan/dfilter/dfilter-int.h +++ b/epan/dfilter/dfilter-int.h @@ -44,6 +44,7 @@ typedef struct { /* Syntax Tree stuff */ stnode_t *st_root; gboolean syntax_error; + gchar *error_message; GPtrArray *insns; GPtrArray *consts; GHashTable *loaded_fields; @@ -54,6 +55,12 @@ typedef struct { int first_constant; /* first register used as a constant */ } dfwork_t; +/* + * XXX - if we're using a version of Flex that supports reentrant lexical + * analyzers, we should put this into the lexical analyzer's state. + */ +extern dfwork_t *global_dfw; + /* Constructor/Destructor prototypes for Lemon Parser */ void *DfilterAlloc(void* (*)(gsize)); @@ -66,9 +73,9 @@ extern stnode_t *df_lval; /* Return value for error in scanner. */ #define SCAN_FAILED -1 /* not 0, as that means end-of-input */ -/* Set dfilter_error_msg_buf and dfilter_error_msg */ +/* Set dfw->error_message */ void -dfilter_fail(const char *format, ...) G_GNUC_PRINTF(1, 2); +dfilter_fail(dfwork_t *dfw, const char *format, ...) G_GNUC_PRINTF(2, 3); void DfilterTrace(FILE *TraceFILE, char *zTracePrompt); diff --git a/epan/dfilter/dfilter-macro.c b/epan/dfilter/dfilter-macro.c index 578bac60c6..132c9fe5a0 100644 --- a/epan/dfilter/dfilter-macro.c +++ b/epan/dfilter/dfilter-macro.c @@ -30,7 +30,6 @@ #include "dfilter.h" #include "dfilter-macro.h" #include -#include #include #include #include @@ -110,7 +109,8 @@ void dfilter_macro_save(const gchar* filename, gchar** error) { FILE* f = ws_fopen(filename,"w"); if (!f) { - *error = wmem_strdup_printf(NULL, "Could not open file: '%s', error: %s\n", filename, g_strerror(errno) ); + if (error != NULL) + *error = g_strdup_printf("Could not open file: '%s', error: %s\n", filename, g_strerror(errno) ); return; } @@ -170,11 +170,13 @@ static gchar* dfilter_macro_resolve(gchar* name, gchar** args, gchar** error) { if(e->usable) { return wmem_strdup(NULL, e->repr); } else { - *error = wmem_strdup_printf(NULL, "macro '%s' is unusable", name); + if (error != NULL) + *error = g_strdup_printf("macro '%s' is unusable", name); return NULL; } } else { - *error = wmem_strdup_printf(NULL, "macro '%s' does not exist", name); + if (error != NULL) + *error = g_strdup_printf("macro '%s' does not exist", name); return NULL; } } @@ -186,8 +188,10 @@ static gchar* dfilter_macro_resolve(gchar* name, gchar** args, gchar** error) { } if (argc != m->argc) { - *error = wmem_strdup_printf(NULL, "wrong number of arguments for macro '%s', expecting %d instead of %d", - name, m->argc, argc); + if (error != NULL) { + *error = g_strdup_printf("wrong number of arguments for macro '%s', expecting %d instead of %d", + name, m->argc, argc); + } return NULL; } @@ -223,7 +227,8 @@ static const gchar* dfilter_macro_apply_recurse(const gchar* text, guint depth, gboolean changed = FALSE; if ( depth > 31) { - *error = wmem_strdup(NULL, "too much nesting in macros"); + if (error != NULL) + *error = g_strdup("too much nesting in macros"); return NULL; } @@ -240,7 +245,8 @@ static const gchar* dfilter_macro_apply_recurse(const gchar* text, guint depth, } \ } while(0) - *error = NULL; + if (error != NULL) + *error = NULL; out = g_string_sized_new(64); while(1) { @@ -295,7 +301,8 @@ static const gchar* dfilter_macro_apply_recurse(const gchar* text, guint depth, g_ptr_array_add(args,NULL); resolved = dfilter_macro_resolve(name->str, (gchar**)args->pdata, error); - if (*error) goto on_error; + if (resolved == NULL) + goto on_error; changed = TRUE; @@ -306,17 +313,20 @@ static const gchar* dfilter_macro_apply_recurse(const gchar* text, guint depth, state = OUTSIDE; } else if ( c == '\0') { - *error = wmem_strdup(NULL, "end of filter in the middle of a macro expression"); + if (error != NULL) + *error = g_strdup("end of filter in the middle of a macro expression"); goto on_error; } else { - *error = wmem_strdup(NULL, "invalid char in macro name"); + if (error != NULL) + *error = g_strdup("invalid character in macro name"); goto on_error; } break; } case ARGS: { switch(c) { case '\0': { - *error = wmem_strdup(NULL, "end of filter in the middle of a macro expression"); + if (error != NULL) + *error = g_strdup("end of filter in the middle of a macro expression"); goto on_error; } case ';': { g_ptr_array_add(args,g_string_free(arg,FALSE)); @@ -329,7 +339,8 @@ static const gchar* dfilter_macro_apply_recurse(const gchar* text, guint depth, g_string_append_c(arg,c); break; } else { - *error = wmem_strdup(NULL, "end of filter in the middle of a macro expression"); + if (error != NULL) + *error = g_strdup("end of filter in the middle of a macro expression"); goto on_error; } } default: { @@ -343,7 +354,8 @@ static const gchar* dfilter_macro_apply_recurse(const gchar* text, guint depth, arg = NULL; resolved = dfilter_macro_resolve(name->str, (gchar**)args->pdata, error); - if (*error) goto on_error; + if (resolved == NULL) + goto on_error; changed = TRUE; @@ -368,7 +380,7 @@ finish: if (changed) { const gchar* resolved = dfilter_macro_apply_recurse(out->str, depth + 1, error); g_string_free(out,TRUE); - return (*error) ? NULL : resolved; + return resolved; } else { const gchar* out_str = wmem_strdup(NULL, out->str); g_string_free(out,TRUE); @@ -378,7 +390,10 @@ finish: on_error: { FREE_ALL(); - if (! *error) *error = wmem_strdup(NULL, "unknown error in macro expression"); + if (error != NULL) { + if (*error == NULL) + *error = g_strdup("unknown error in macro expression"); + } g_string_free(out,TRUE); return NULL; } diff --git a/epan/dfilter/dfilter.c b/epan/dfilter/dfilter.c index 8e21d30853..903ec33868 100644 --- a/epan/dfilter/dfilter.c +++ b/epan/dfilter/dfilter.c @@ -34,10 +34,6 @@ #define DFILTER_TOKEN_ID_OFFSET 1 -/* Global error message space for dfilter_compile errors */ -static gchar dfilter_error_msg_buf[1024]; -const gchar *dfilter_error_msg; /* NULL when no error resulted */ - /* From scanner.c */ void df_scanner_text(const char *text); void df_scanner_cleanup(void); @@ -46,24 +42,26 @@ int df_lex(void); /* Holds the singular instance of our Lemon parser object */ static void* ParserObj = NULL; +/* + * XXX - if we're using a version of Flex that supports reentrant lexical + * analyzers, we should put this into the lexical analyzer's state. + */ +dfwork_t *global_dfw; + void -dfilter_fail(const char *format, ...) +dfilter_fail(dfwork_t *dfw, const char *format, ...) { va_list args; /* If we've already reported one error, don't overwite it */ - if (dfilter_error_msg != NULL) + if (dfw->error_message != NULL) return; va_start(args, format); - - g_vsnprintf(dfilter_error_msg_buf, sizeof(dfilter_error_msg_buf), - format, args); - dfilter_error_msg = dfilter_error_msg_buf; + dfw->error_message = g_strdup_vprintf(format, args); va_end(args); } - /* Initialize the dfilter module */ void dfilter_init(void) @@ -110,7 +108,7 @@ dfilter_new(void) df = g_new0(dfilter_t, 1); df->insns = NULL; - df->deprecated = NULL; + df->deprecated = NULL; return df; } @@ -202,11 +200,15 @@ dfwork_free(dfwork_t *dfw) free_insns(dfw->consts); } + /* + * We don't free the error message string; our caller will return + * it to its caller. + */ g_free(dfw); } gboolean -dfilter_compile(const gchar *text, dfilter_t **dfp) +dfilter_compile(const gchar *text, dfilter_t **dfp, gchar **err_msg) { int token; dfilter_t *dfilter; @@ -216,26 +218,28 @@ dfilter_compile(const gchar *text, dfilter_t **dfp) guint i; /* XXX, GHashTable */ GPtrArray *deprecated; - gchar *temp_error_msg; g_assert(dfp); if (!text) { *dfp = NULL; + if (err_msg != NULL) + *err_msg = g_strdup("BUG: NULL text pointer passed to dfilter_compile()"); return FALSE; } - dfilter_error_msg = NULL; - - if ( !( text = dfilter_macro_apply(text, &temp_error_msg) ) ) { - /* Move the ep_ allocation up a layer */ - dfilter_error_msg = ep_strdup(temp_error_msg); - wmem_free(NULL, temp_error_msg); + if ( !( text = dfilter_macro_apply(text, err_msg) ) ) { return FALSE; } dfw = dfwork_new(); + /* + * XXX - if we're using a version of Flex that supports reentrant lexical + * analyzers, we should put this into the lexical analyzer's state. + */ + global_dfw = dfw; + df_scanner_text(text); deprecated = g_ptr_array_new(); @@ -353,12 +357,18 @@ dfilter_compile(const gchar *text, dfilter_t **dfp) *dfp = dfilter; } /* SUCCESS */ + global_dfw = NULL; dfwork_free(dfw); wmem_free(NULL, (char*)text); return TRUE; FAILURE: if (dfw) { + if (err_msg != NULL) + *err_msg = dfw->error_message; + else + g_free(dfw->error_message); + global_dfw = NULL; dfwork_free(dfw); } for (i = 0; i < deprecated->len; ++i) { @@ -366,11 +376,18 @@ FAILURE: g_free(depr); } g_ptr_array_free(deprecated, TRUE); - dfilter_fail("Unable to parse filter string \"%s\".", text); - wmem_free(NULL, (char*)text); + if (err_msg != NULL) { + /* + * Default error message. + * + * XXX - we should really make sure that this is never the + * case for any error. + */ + if (*err_msg == NULL) + *err_msg = g_strdup_printf("Unable to parse filter string \"%s\".", text); + } *dfp = NULL; return FALSE; - } diff --git a/epan/dfilter/dfilter.h b/epan/dfilter/dfilter.h index b408dc7757..1bbf907ec4 100644 --- a/epan/dfilter/dfilter.h +++ b/epan/dfilter/dfilter.h @@ -50,17 +50,16 @@ dfilter_cleanup(void); * a pointer to the newly-allocated dfilter_t * structure. * - * On failure, dfilter_error_msg points to an - * appropriate error message. This error message is - * a global string, so another invocation of - * dfilter_compile() will clear it. The dfilter* - * will be set to NULL after a failure. + * On failure, *err_msg is set to point to the error + * message. This error message is allocated with + * g_malloc(), and must be freed with g_free(). + * The dfilter* will be set to NULL after a failure. * * Returns TRUE on success, FALSE on failure. */ WS_DLL_PUBLIC gboolean -dfilter_compile(const gchar *text, dfilter_t **dfp); +dfilter_compile(const gchar *text, dfilter_t **dfp, gchar **err_msg); /* Frees all memory used by dfilter, and frees * the dfilter itself. */ @@ -68,15 +67,6 @@ WS_DLL_PUBLIC void dfilter_free(dfilter_t *df); - -/* dfilter_error_msg is NULL if there was no error during dfilter_compile, - * otherwise it points to a displayable error message. With MSVC and a - * libwireshark.dll, we need a special declaration. - */ - -WS_DLL_PUBLIC const gchar *dfilter_error_msg; - - /* Apply compiled dfilter */ WS_DLL_PUBLIC gboolean diff --git a/epan/dfilter/dfunctions.c b/epan/dfilter/dfunctions.c index 6394a1e482..204e6f712b 100644 --- a/epan/dfilter/dfunctions.c +++ b/epan/dfilter/dfunctions.c @@ -22,8 +22,8 @@ #include -#include "dfunctions.h" #include "dfilter-int.h" +#include "dfunctions.h" #include @@ -142,7 +142,7 @@ df_func_count(GList* arg1list, GList *arg2junk _U_, GList **retval) /* For upper(), lower() and len(), checks that the parameter passed to * it is an FT_STRING */ static void -ul_semcheck_params(int param_num, stnode_t *st_node) +ul_semcheck_params(dfwork_t *dfw, int param_num, stnode_t *st_node) { sttype_id_t type; ftenum_t ftype; @@ -156,12 +156,12 @@ ul_semcheck_params(int param_num, stnode_t *st_node) hfinfo = (header_field_info *)stnode_data(st_node); ftype = hfinfo->type; if (!IS_FT_STRING(ftype)) { - dfilter_fail("Only strings can be used in upper() or lower() or len()"); + dfilter_fail(dfw, "Only strings can be used in upper() or lower() or len()"); THROW(TypeError); } break; default: - dfilter_fail("Only string-type fields can be used in upper() or lower() or len()"); + dfilter_fail(dfw, "Only string-type fields can be used in upper() or lower() or len()"); THROW(TypeError); } } @@ -171,7 +171,7 @@ ul_semcheck_params(int param_num, stnode_t *st_node) } static void -ul_semcheck_field_param(int param_num, stnode_t *st_node) +ul_semcheck_field_param(dfwork_t *dfw, int param_num, stnode_t *st_node) { sttype_id_t type; @@ -182,7 +182,7 @@ ul_semcheck_field_param(int param_num, stnode_t *st_node) case STTYPE_FIELD: break; default: - dfilter_fail("Only type fields can be used as parameter " + dfilter_fail(dfw, "Only type fields can be used as parameter " "for size() or count()"); THROW(TypeError); } diff --git a/epan/dfilter/dfunctions.h b/epan/dfilter/dfunctions.h index 2b7957ec2c..96aed53bc6 100644 --- a/epan/dfilter/dfunctions.h +++ b/epan/dfilter/dfunctions.h @@ -29,7 +29,7 @@ typedef gboolean (*DFFuncType)(GList *arg1list, GList *arg2list, GList **retval); /* The semantic check for the dfilter function */ -typedef void (*DFSemCheckType)(int param_num, stnode_t *st_node); +typedef void (*DFSemCheckType)(dfwork_t *dfw, int param_num, stnode_t *st_node); /* If a function needs more args than this, increase * this macro and add more arg members to the dfvm_insn_t diff --git a/epan/dfilter/grammar.lemon b/epan/dfilter/grammar.lemon index c52fe7ad40..abd6e9a1cd 100644 --- a/epan/dfilter/grammar.lemon +++ b/epan/dfilter/grammar.lemon @@ -68,35 +68,35 @@ any "error" symbols are shifted, if possible. */ header_field_info *hfinfo; if (!TOKEN) { - dfilter_fail("Unexpected end of filter string."); + dfilter_fail(dfw, "Unexpected end of filter string."); return; } switch(stnode_type_id(TOKEN)) { case STTYPE_UNINITIALIZED: - dfilter_fail("Syntax error."); + dfilter_fail(dfw, "Syntax error."); break; case STTYPE_TEST: - dfilter_fail("Syntax error, TEST."); + dfilter_fail(dfw, "Syntax error, TEST."); break; case STTYPE_STRING: - dfilter_fail("The string \"%s\" was unexpected in this context.", + dfilter_fail(dfw, "The string \"%s\" was unexpected in this context.", (char *)stnode_data(TOKEN)); break; case STTYPE_UNPARSED: - dfilter_fail("\"%s\" was unexpected in this context.", + dfilter_fail(dfw, "\"%s\" was unexpected in this context.", (char *)stnode_data(TOKEN)); break; case STTYPE_INTEGER: - dfilter_fail("The integer %d was unexpected in this context.", + dfilter_fail(dfw, "The integer %d was unexpected in this context.", stnode_value(TOKEN)); break; case STTYPE_FIELD: hfinfo = (header_field_info *)stnode_data(TOKEN); - dfilter_fail("Syntax error near \"%s\".", hfinfo->abbrev); + dfilter_fail(dfw, "Syntax error near \"%s\".", hfinfo->abbrev); break; case STTYPE_FUNCTION: - dfilter_fail("The function s was unexpected in this context."); + dfilter_fail(dfw, "The function s was unexpected in this context."); break; /* These aren't handed to use as terminal tokens from diff --git a/epan/dfilter/scanner.l b/epan/dfilter/scanner.l index f09f30b40c..d3b71a39f9 100644 --- a/epan/dfilter/scanner.l +++ b/epan/dfilter/scanner.l @@ -68,9 +68,9 @@ /*#undef YY_NO_UNPUT*/ static int set_lval(int token, gpointer data); -static int set_lval_int(int token, char *s); +static int set_lval_int(dfwork_t *dfw, int token, char *s); static int simple(int token); -static gboolean str_to_gint32(char *s, gint32* pint); +static gboolean str_to_gint32(dfwork_t *dfw, char *s, gint32* pint); GString* quoted_string = NULL; static void mark_lval_deprecated(const char *s); @@ -128,12 +128,12 @@ static void mark_lval_deprecated(const char *s); [+-]?[[:digit:]]+ { BEGIN(RANGE_PUNCT); - return set_lval_int(TOKEN_INTEGER, yytext); + return set_lval_int(global_dfw, TOKEN_INTEGER, yytext); } [+-]?0x[[:xdigit:]]+ { BEGIN(RANGE_PUNCT); - return set_lval_int(TOKEN_INTEGER, yytext); + return set_lval_int(global_dfw, TOKEN_INTEGER, yytext); } ":" { @@ -159,7 +159,7 @@ static void mark_lval_deprecated(const char *s); /* Error if none of the above while scanning a range (slice) */ [^:\-,\]]+ { - dfilter_fail("Invalid string \"%s\" found while scanning slice.", yytext); + dfilter_fail(global_dfw, "Invalid string \"%s\" found while scanning slice.", yytext); return SCAN_FAILED; } @@ -168,7 +168,7 @@ static void mark_lval_deprecated(const char *s); */ . { - dfilter_fail("Invalid character \"%s\" found while scanning slice; expected integer.", yytext); + dfilter_fail(global_dfw, "Invalid character \"%s\" found while scanning slice; expected integer.", yytext); return SCAN_FAILED; } @@ -200,7 +200,7 @@ static void mark_lval_deprecated(const char *s); See: http://www.gnu.org/software/flex/manual/html_node/flex_13.html */ - dfilter_fail("The final quote was missing from a quoted string."); + dfilter_fail(global_dfw, "The final quote was missing from a quoted string."); return SCAN_FAILED; } @@ -221,7 +221,7 @@ static void mark_lval_deprecated(const char *s); if (result > 0xff) { g_string_free(quoted_string, TRUE); quoted_string = NULL; - dfilter_fail("%s is larger than 255.", yytext); + dfilter_fail(global_dfw, "%s is larger than 255.", yytext); return SCAN_FAILED; } g_string_append_c(quoted_string, (gchar) result); @@ -340,12 +340,12 @@ set_lval(int token, gpointer data) } static int -set_lval_int(int token, char *s) +set_lval_int(dfwork_t *dfw, int token, char *s) { sttype_id_t type_id = STTYPE_UNINITIALIZED; gint32 val; - if (!str_to_gint32(s, &val)) { + if (!str_to_gint32(dfw, s, &val)) { return SCAN_FAILED; } @@ -363,7 +363,7 @@ set_lval_int(int token, char *s) static gboolean -str_to_gint32(char *s, gint32* pint) +str_to_gint32(dfwork_t *dfw, char *s, gint32* pint) { char *endptr; long integer; @@ -373,22 +373,22 @@ str_to_gint32(char *s, gint32* pint) if (errno == EINVAL || endptr == s || *endptr != '\0') { /* This isn't a valid number. */ - dfilter_fail("\"%s\" is not a valid number.", s); + dfilter_fail(dfw, "\"%s\" is not a valid number.", s); return FALSE; } if (errno == ERANGE) { if (integer == LONG_MAX) { - dfilter_fail("\"%s\" causes an integer overflow.", s); + dfilter_fail(dfw, "\"%s\" causes an integer overflow.", s); } else if (integer == LONG_MIN) { - dfilter_fail("\"%s\" causes an integer underflow.", s); + dfilter_fail(dfw, "\"%s\" causes an integer underflow.", s); } else { /* * XXX - can "strtol()" set errno to ERANGE without * returning LONG_MAX or LONG_MIN? */ - dfilter_fail("\"%s\" is not an integer.", s); + dfilter_fail(dfw, "\"%s\" is not an integer.", s); } return FALSE; } @@ -397,7 +397,7 @@ str_to_gint32(char *s, gint32* pint) * Fits in a long, but not in a gint32 (a long might be * 64 bits). */ - dfilter_fail("\"%s\" causes an integer overflow.", s); + dfilter_fail(dfw, "\"%s\" causes an integer overflow.", s); return FALSE; } if (integer < G_MININT32) { @@ -405,7 +405,7 @@ str_to_gint32(char *s, gint32* pint) * Fits in a long, but not in a gint32 (a long might be * 64 bits). */ - dfilter_fail("\"%s\" causes an integer underflow.", s); + dfilter_fail(dfw, "\"%s\" causes an integer underflow.", s); return FALSE; } diff --git a/epan/dfilter/semcheck.c b/epan/dfilter/semcheck.c index bda8f49c4b..cc1a5df4bb 100644 --- a/epan/dfilter/semcheck.c +++ b/epan/dfilter/semcheck.c @@ -48,10 +48,10 @@ #endif static void -semcheck(stnode_t *st_node, GPtrArray *deprecated); +semcheck(dfwork_t *dfw, stnode_t *st_node, GPtrArray *deprecated); static stnode_t* -check_param_entity(stnode_t *st_node); +check_param_entity(dfwork_t *dfw, stnode_t *st_node); typedef gboolean (*FtypeCanFunc)(enum ftenum); @@ -137,6 +137,25 @@ compatible_ftypes(ftenum_t a, ftenum_t b) return FALSE; } +/* Gets an fvalue from a string, and sets the error message on failure. */ +static fvalue_t* +dfilter_fvalue_from_unparsed(dfwork_t *dfw, ftenum_t ftype, const char *s, gboolean allow_partial_value) +{ + /* + * Don't set the error message if it's already set. + */ + return fvalue_from_unparsed(ftype, s, allow_partial_value, + dfw->error_message == NULL ? &dfw->error_message : NULL); +} + +/* Gets an fvalue from a string, and sets the error message on failure. */ +static fvalue_t* +dfilter_fvalue_from_string(dfwork_t *dfw, ftenum_t ftype, const char *s) +{ + return fvalue_from_string(ftype, s, + dfw->error_message == NULL ? &dfw->error_message : NULL); +} + /* Creates a FT_UINT32 fvalue with a given value. */ static fvalue_t* mk_uint32_fvalue(guint32 val) @@ -165,7 +184,7 @@ mk_uint64_fvalue(guint64 val) * This works only for ftypes that are integers. Returns the created fvalue_t* * or NULL if impossible. */ static fvalue_t* -mk_fvalue_from_val_string(header_field_info *hfinfo, char *s) +mk_fvalue_from_val_string(dfwork_t *dfw, header_field_info *hfinfo, char *s) { static const true_false_string default_tf = { "True", "False" }; const true_false_string *tf = &default_tf; @@ -230,8 +249,13 @@ mk_fvalue_from_val_string(header_field_info *hfinfo, char *s) return mk_uint32_fvalue(FALSE); } else { - dfilter_error_msg = NULL; /* Prefer this error message */ - dfilter_fail("\"%s\" cannot be found among the possible values for %s.", + /* + * Prefer this error message to whatever error message + * has already been set. + */ + g_free(dfw->error_message); + dfw->error_message = NULL; + dfilter_fail(dfw, "\"%s\" cannot be found among the possible values for %s.", s, hfinfo->abbrev); return NULL; } @@ -239,18 +263,19 @@ mk_fvalue_from_val_string(header_field_info *hfinfo, char *s) /* Do val_strings exist? */ if (!hfinfo->strings) { - dfilter_fail("%s cannot accept strings as values.", + dfilter_fail(dfw, "%s cannot accept strings as values.", hfinfo->abbrev); return NULL; } - /* Reset the dfilter error message, since *something* interesting - * will happen, and the error message will be more interesting than - * any error message I happen to have now. */ - dfilter_error_msg = NULL; + /* Reset the error message, since *something* interesting will happen, + * and the error message will be more interesting than any error message + * I happen to have now. */ + g_free(dfw->error_message); + dfw->error_message = NULL; if (hfinfo->display & BASE_RANGE_STRING) { - dfilter_fail("\"%s\" cannot accept [range] strings as values.", + dfilter_fail(dfw, "\"%s\" cannot accept [range] strings as values.", hfinfo->abbrev); } else if (hfinfo->display & BASE_VAL64_STRING) { @@ -262,7 +287,7 @@ mk_fvalue_from_val_string(header_field_info *hfinfo, char *s) } vals++; } - dfilter_fail("\"%s\" cannot be found among the possible values for %s.", + dfilter_fail(dfw, "\"%s\" cannot be found among the possible values for %s.", s, hfinfo->abbrev); } else if (hfinfo->display == BASE_CUSTOM) { @@ -272,7 +297,7 @@ mk_fvalue_from_val_string(header_field_info *hfinfo, char *s) * integer, we have the string they're trying to match. * -><- */ - dfilter_fail("\"%s\" cannot accept [custom] strings as values.", + dfilter_fail(dfw, "\"%s\" cannot accept [custom] strings as values.", hfinfo->abbrev); } else { @@ -286,7 +311,7 @@ mk_fvalue_from_val_string(header_field_info *hfinfo, char *s) } vals++; } - dfilter_fail("\"%s\" cannot be found among the possible values for %s.", + dfilter_fail(dfw, "\"%s\" cannot be found among the possible values for %s.", s, hfinfo->abbrev); } return NULL; @@ -347,7 +372,7 @@ is_bytes_type(enum ftenum type) /* Check the semantics of an existence test. */ static void -check_exists(stnode_t *st_arg1) +check_exists(dfwork_t *dfw, stnode_t *st_arg1) { #ifdef DEBUG_dfilter static guint i = 0; @@ -360,7 +385,7 @@ check_exists(stnode_t *st_arg1) break; case STTYPE_STRING: case STTYPE_UNPARSED: - dfilter_fail("\"%s\" is neither a field nor a protocol name.", + dfilter_fail(dfw, "\"%s\" is neither a field nor a protocol name.", (char *)stnode_data(st_arg1)); THROW(TypeError); break; @@ -372,14 +397,14 @@ check_exists(stnode_t *st_arg1) * has at least 2 bytes starting at an offset of * 3"? */ - dfilter_fail("You cannot test whether a range is present."); + dfilter_fail(dfw, "You cannot test whether a range is present."); THROW(TypeError); break; case STTYPE_FUNCTION: /* XXX - Maybe we should change functions so they can return fields, * in which case the 'exist' should be fine. */ - dfilter_fail("You cannot test whether a function is present."); + dfilter_fail(dfw, "You cannot test whether a function is present."); THROW(TypeError); break; @@ -393,6 +418,7 @@ check_exists(stnode_t *st_arg1) } struct check_drange_sanity_args { + dfwork_t *dfw; stnode_t *st; gboolean err; }; @@ -428,13 +454,13 @@ check_drange_node_sanity(gpointer data, gpointer user_data) if (entity && stnode_type_id(entity) == STTYPE_FIELD) { hfinfo = (header_field_info *)stnode_data(entity); - dfilter_fail("Range %d:%d specified for \"%s\" isn't valid, " + dfilter_fail(args->dfw, "Range %d:%d specified for \"%s\" isn't valid, " "as length %d isn't positive", start_offset, length, hfinfo->abbrev, length); } else - dfilter_fail("Range %d:%d isn't valid, " + dfilter_fail(args->dfw, "Range %d:%d isn't valid, " "as length %d isn't positive", start_offset, length, length); @@ -462,14 +488,14 @@ check_drange_node_sanity(gpointer data, gpointer user_data) if (entity && stnode_type_id(entity) == STTYPE_FIELD) { hfinfo = (header_field_info *)stnode_data(entity); - dfilter_fail("Range %d-%d specified for \"%s\" isn't valid, " + dfilter_fail(args->dfw, "Range %d-%d specified for \"%s\" isn't valid, " "as %d is greater than %d", start_offset, end_offset, hfinfo->abbrev, start_offset, end_offset); } else - dfilter_fail("Range %d-%d isn't valid, " + dfilter_fail(args->dfw, "Range %d-%d isn't valid, " "as %d is greater than %d", start_offset, end_offset, start_offset, end_offset); @@ -487,10 +513,11 @@ check_drange_node_sanity(gpointer data, gpointer user_data) } static void -check_drange_sanity(stnode_t *st) +check_drange_sanity(dfwork_t *dfw, stnode_t *st) { struct check_drange_sanity_args args; + args.dfw = dfw; args.st = st; args.err = FALSE; @@ -520,7 +547,7 @@ convert_to_bytes(stnode_t *arg) } static void -check_function(stnode_t *st_node) +check_function(dfwork_t *dfw, stnode_t *st_node) { df_func_def_t *funcdef; GSList *params; @@ -532,19 +559,19 @@ check_function(stnode_t *st_node) nparams = g_slist_length(params); if (nparams < funcdef->min_nargs) { - dfilter_fail("Function %s needs at least %u arguments.", + dfilter_fail(dfw, "Function %s needs at least %u arguments.", funcdef->name, funcdef->min_nargs); THROW(TypeError); } else if (nparams > funcdef->max_nargs) { - dfilter_fail("Function %s can only accept %u arguments.", + dfilter_fail(dfw, "Function %s can only accept %u arguments.", funcdef->name, funcdef->max_nargs); THROW(TypeError); } iparam = 0; while (params) { - params->data = check_param_entity((stnode_t *)params->data); - funcdef->semcheck_param_function(iparam, (stnode_t *)params->data); + params->data = check_param_entity(dfw, (stnode_t *)params->data); + funcdef->semcheck_param_function(dfw, iparam, (stnode_t *)params->data); params = params->next; iparam++; } @@ -553,8 +580,8 @@ check_function(stnode_t *st_node) /* If the LHS of a relation test is a FIELD, run some checks * and possibly some modifications of syntax tree nodes. */ static void -check_relation_LHS_FIELD(const char *relation_string, FtypeCanFunc can_func, - gboolean allow_partial_value, +check_relation_LHS_FIELD(dfwork_t *dfw, const char *relation_string, + FtypeCanFunc can_func, gboolean allow_partial_value, stnode_t *st_node, stnode_t *st_arg1, stnode_t *st_arg2) { stnode_t *new_st; @@ -573,7 +600,7 @@ check_relation_LHS_FIELD(const char *relation_string, FtypeCanFunc can_func, DebugLog((" 5 check_relation_LHS_FIELD(%s)\n", relation_string)); if (!can_func(ftype1)) { - dfilter_fail("%s (type=%s) cannot participate in '%s' comparison.", + dfilter_fail(dfw, "%s (type=%s) cannot participate in '%s' comparison.", hfinfo1->abbrev, ftype_pretty_name(ftype1), relation_string); THROW(TypeError); @@ -584,14 +611,14 @@ check_relation_LHS_FIELD(const char *relation_string, FtypeCanFunc can_func, ftype2 = hfinfo2->type; if (!compatible_ftypes(ftype1, ftype2)) { - dfilter_fail("%s and %s are not of compatible types.", + dfilter_fail(dfw, "%s and %s are not of compatible types.", hfinfo1->abbrev, hfinfo2->abbrev); THROW(TypeError); } /* Do this check even though you'd think that if * they're compatible, then can_func() would pass. */ if (!can_func(ftype2)) { - dfilter_fail("%s (type=%s) cannot participate in specified comparison.", + dfilter_fail(dfw, "%s (type=%s) cannot participate in specified comparison.", hfinfo2->abbrev, ftype_pretty_name(ftype2)); THROW(TypeError); } @@ -601,9 +628,9 @@ check_relation_LHS_FIELD(const char *relation_string, FtypeCanFunc can_func, if (strcmp(relation_string, "matches") == 0) { /* Convert to a FT_PCRE */ if (type2 == STTYPE_STRING) - fvalue = fvalue_from_string(FT_PCRE, s, dfilter_fail); + fvalue = dfilter_fvalue_from_string(dfw, FT_PCRE, s); else - fvalue = fvalue_from_unparsed(FT_PCRE, s, FALSE, dfilter_fail); + fvalue = dfilter_fvalue_from_unparsed(dfw, FT_PCRE, s, FALSE); } else { /* Skip incompatible fields */ while (hfinfo1->same_name_prev_id != -1 && @@ -614,13 +641,13 @@ check_relation_LHS_FIELD(const char *relation_string, FtypeCanFunc can_func, } if (type2 == STTYPE_STRING) - fvalue = fvalue_from_string(ftype1, s, dfilter_fail); + fvalue = dfilter_fvalue_from_string(dfw, ftype1, s); else - fvalue = fvalue_from_unparsed(ftype1, s, allow_partial_value, dfilter_fail); + fvalue = dfilter_fvalue_from_unparsed(dfw, ftype1, s, allow_partial_value); if (!fvalue) { /* check value_string */ - fvalue = mk_fvalue_from_val_string(hfinfo1, s); + fvalue = mk_fvalue_from_val_string(dfw, hfinfo1, s); } } @@ -633,10 +660,10 @@ check_relation_LHS_FIELD(const char *relation_string, FtypeCanFunc can_func, stnode_free(st_arg2); } else if (type2 == STTYPE_RANGE) { - check_drange_sanity(st_arg2); + check_drange_sanity(dfw, st_arg2); if (!is_bytes_type(ftype1)) { if (!ftype_can_slice(ftype1)) { - dfilter_fail("\"%s\" is a %s and cannot be converted into a sequence of bytes.", + dfilter_fail(dfw, "\"%s\" is a %s and cannot be converted into a sequence of bytes.", hfinfo1->abbrev, ftype_pretty_name(ftype1)); THROW(TypeError); @@ -653,19 +680,19 @@ check_relation_LHS_FIELD(const char *relation_string, FtypeCanFunc can_func, ftype2 = funcdef->retval_ftype; if (!compatible_ftypes(ftype1, ftype2)) { - dfilter_fail("%s (type=%s) and return value of %s() (type=%s) are not of compatible types.", + dfilter_fail(dfw, "%s (type=%s) and return value of %s() (type=%s) are not of compatible types.", hfinfo1->abbrev, ftype_pretty_name(ftype1), funcdef->name, ftype_pretty_name(ftype2)); THROW(TypeError); } if (!can_func(ftype2)) { - dfilter_fail("return value of %s() (type=%s) cannot participate in specified comparison.", + dfilter_fail(dfw, "return value of %s() (type=%s) cannot participate in specified comparison.", funcdef->name, ftype_pretty_name(ftype2)); THROW(TypeError); } - check_function(st_arg2); + check_function(dfw, st_arg2); } else { g_assert_not_reached(); @@ -673,7 +700,7 @@ check_relation_LHS_FIELD(const char *relation_string, FtypeCanFunc can_func, } static void -check_relation_LHS_STRING(const char* relation_string, +check_relation_LHS_STRING(dfwork_t *dfw, const char* relation_string, FtypeCanFunc can_func, gboolean allow_partial_value _U_, stnode_t *st_node, stnode_t *st_arg1, stnode_t *st_arg2) @@ -695,17 +722,17 @@ check_relation_LHS_STRING(const char* relation_string, ftype2 = hfinfo2->type; if (!can_func(ftype2)) { - dfilter_fail("%s (type=%s) cannot participate in '%s' comparison.", + dfilter_fail(dfw, "%s (type=%s) cannot participate in '%s' comparison.", hfinfo2->abbrev, ftype_pretty_name(ftype2), relation_string); THROW(TypeError); } s = (char*)stnode_data(st_arg1); - fvalue = fvalue_from_string(ftype2, s, dfilter_fail); + fvalue = dfilter_fvalue_from_string(dfw, ftype2, s); if (!fvalue) { /* check value_string */ - fvalue = mk_fvalue_from_val_string(hfinfo2, s); + fvalue = mk_fvalue_from_val_string(dfw, hfinfo2, s); if (!fvalue) { THROW(TypeError); } @@ -717,15 +744,15 @@ check_relation_LHS_STRING(const char* relation_string, } else if (type2 == STTYPE_STRING || type2 == STTYPE_UNPARSED) { /* Well now that's silly... */ - dfilter_fail("Neither \"%s\" nor \"%s\" are field or protocol names.", + dfilter_fail(dfw, "Neither \"%s\" nor \"%s\" are field or protocol names.", (char *)stnode_data(st_arg1), (char *)stnode_data(st_arg2)); THROW(TypeError); } else if (type2 == STTYPE_RANGE) { - check_drange_sanity(st_arg2); + check_drange_sanity(dfw, st_arg2); s = (char*)stnode_data(st_arg1); - fvalue = fvalue_from_string(FT_BYTES, s, dfilter_fail); + fvalue = dfilter_fvalue_from_string(dfw, FT_BYTES, s); if (!fvalue) { THROW(TypeError); } @@ -738,19 +765,19 @@ check_relation_LHS_STRING(const char* relation_string, ftype2 = funcdef->retval_ftype; if (!can_func(ftype2)) { - dfilter_fail("Return value of function %s (type=%s) cannot participate in '%s' comparison.", + dfilter_fail(dfw, "Return value of function %s (type=%s) cannot participate in '%s' comparison.", funcdef->name, ftype_pretty_name(ftype2), relation_string); THROW(TypeError); } s = (char*)stnode_data(st_arg1); - fvalue = fvalue_from_string(ftype2, s, dfilter_fail); + fvalue = dfilter_fvalue_from_string(dfw, ftype2, s); if (!fvalue) { THROW(TypeError); } - check_function(st_arg2); + check_function(dfw, st_arg2); new_st = stnode_new(STTYPE_FVALUE, fvalue); sttype_test_set2_args(st_node, new_st, st_arg2); @@ -762,7 +789,7 @@ check_relation_LHS_STRING(const char* relation_string, } static void -check_relation_LHS_UNPARSED(const char* relation_string, +check_relation_LHS_UNPARSED(dfwork_t *dfw, const char* relation_string, FtypeCanFunc can_func, gboolean allow_partial_value, stnode_t *st_node, stnode_t *st_arg1, stnode_t *st_arg2) @@ -784,17 +811,17 @@ check_relation_LHS_UNPARSED(const char* relation_string, ftype2 = hfinfo2->type; if (!can_func(ftype2)) { - dfilter_fail("%s (type=%s) cannot participate in '%s' comparison.", + dfilter_fail(dfw, "%s (type=%s) cannot participate in '%s' comparison.", hfinfo2->abbrev, ftype_pretty_name(ftype2), relation_string); THROW(TypeError); } s = (char*)stnode_data(st_arg1); - fvalue = fvalue_from_unparsed(ftype2, s, allow_partial_value, dfilter_fail); + fvalue = dfilter_fvalue_from_unparsed(dfw, ftype2, s, allow_partial_value); if (!fvalue) { /* check value_string */ - fvalue = mk_fvalue_from_val_string(hfinfo2, s); + fvalue = mk_fvalue_from_val_string(dfw, hfinfo2, s); if (!fvalue) { THROW(TypeError); } @@ -806,15 +833,15 @@ check_relation_LHS_UNPARSED(const char* relation_string, } else if (type2 == STTYPE_STRING || type2 == STTYPE_UNPARSED) { /* Well now that's silly... */ - dfilter_fail("Neither \"%s\" nor \"%s\" are field or protocol names.", + dfilter_fail(dfw, "Neither \"%s\" nor \"%s\" are field or protocol names.", (char *)stnode_data(st_arg1), (char *)stnode_data(st_arg2)); THROW(TypeError); } else if (type2 == STTYPE_RANGE) { - check_drange_sanity(st_arg2); + check_drange_sanity(dfw, st_arg2); s = (char*)stnode_data(st_arg1); - fvalue = fvalue_from_unparsed(FT_BYTES, s, allow_partial_value, dfilter_fail); + fvalue = dfilter_fvalue_from_unparsed(dfw, FT_BYTES, s, allow_partial_value); if (!fvalue) { THROW(TypeError); } @@ -827,19 +854,19 @@ check_relation_LHS_UNPARSED(const char* relation_string, ftype2 = funcdef->retval_ftype; if (!can_func(ftype2)) { - dfilter_fail("return value of function %s() (type=%s) cannot participate in '%s' comparison.", + dfilter_fail(dfw, "return value of function %s() (type=%s) cannot participate in '%s' comparison.", funcdef->name, ftype_pretty_name(ftype2), relation_string); THROW(TypeError); } s = (char*)stnode_data(st_arg1); - fvalue = fvalue_from_unparsed(ftype2, s, allow_partial_value, dfilter_fail); + fvalue = dfilter_fvalue_from_unparsed(dfw, ftype2, s, allow_partial_value); if (!fvalue) { THROW(TypeError); } - check_function(st_arg2); + check_function(dfw, st_arg2); new_st = stnode_new(STTYPE_FVALUE, fvalue); sttype_test_set2_args(st_node, new_st, st_arg2); @@ -851,7 +878,8 @@ check_relation_LHS_UNPARSED(const char* relation_string, } static void -check_relation_LHS_RANGE(const char *relation_string, FtypeCanFunc can_func _U_, +check_relation_LHS_RANGE(dfwork_t *dfw, const char *relation_string, + FtypeCanFunc can_func _U_, gboolean allow_partial_value, stnode_t *st_node, stnode_t *st_arg1, stnode_t *st_arg2) @@ -874,7 +902,7 @@ check_relation_LHS_RANGE(const char *relation_string, FtypeCanFunc can_func _U_, ftype1 = hfinfo1->type; if (!ftype_can_slice(ftype1)) { - dfilter_fail("\"%s\" is a %s and cannot be sliced into a sequence of bytes.", + dfilter_fail(dfw, "\"%s\" is a %s and cannot be sliced into a sequence of bytes.", hfinfo1->abbrev, ftype_pretty_name(ftype1)); THROW(TypeError); } @@ -883,20 +911,20 @@ check_relation_LHS_RANGE(const char *relation_string, FtypeCanFunc can_func _U_, ftype1 = funcdef->retval_ftype; if (!ftype_can_slice(ftype1)) { - dfilter_fail("Return value of function \"%s\" is a %s and cannot be converted into a sequence of bytes.", + dfilter_fail(dfw, "Return value of function \"%s\" is a %s and cannot be converted into a sequence of bytes.", funcdef->name, ftype_pretty_name(ftype1)); THROW(TypeError); } - check_function(entity1); + check_function(dfw, entity1); } else { - dfilter_fail("Range is not supported, details: " G_STRLOC " entity: %p of type %d", + dfilter_fail(dfw, "Range is not supported, details: " G_STRLOC " entity: %p of type %d", entity1, entity1 ? (int) stnode_type_id(entity1) : -1); THROW(TypeError); } - check_drange_sanity(st_arg1); + check_drange_sanity(dfw, st_arg1); if (type2 == STTYPE_FIELD) { DebugLog((" 5 check_relation_LHS_RANGE(type2 = STTYPE_FIELD)\n")); @@ -905,7 +933,7 @@ check_relation_LHS_RANGE(const char *relation_string, FtypeCanFunc can_func _U_, if (!is_bytes_type(ftype2)) { if (!ftype_can_slice(ftype2)) { - dfilter_fail("\"%s\" is a %s and cannot be converted into a sequence of bytes.", + dfilter_fail(dfw, "\"%s\" is a %s and cannot be converted into a sequence of bytes.", hfinfo2->abbrev, ftype_pretty_name(ftype2)); THROW(TypeError); @@ -922,9 +950,9 @@ check_relation_LHS_RANGE(const char *relation_string, FtypeCanFunc can_func _U_, s = (char*)stnode_data(st_arg2); if (strcmp(relation_string, "matches") == 0) { /* Convert to a FT_PCRE */ - fvalue = fvalue_from_string(FT_PCRE, s, dfilter_fail); + fvalue = dfilter_fvalue_from_string(dfw, FT_PCRE, s); } else { - fvalue = fvalue_from_string(FT_BYTES, s, dfilter_fail); + fvalue = dfilter_fvalue_from_string(dfw, FT_BYTES, s); } if (!fvalue) { DebugLog((" 5 check_relation_LHS_RANGE(type2 = STTYPE_STRING): Could not convert from string!\n")); @@ -940,7 +968,7 @@ check_relation_LHS_RANGE(const char *relation_string, FtypeCanFunc can_func _U_, len_range = drange_get_total_length(sttype_range_drange(st_arg1)); if (strcmp(relation_string, "matches") == 0) { /* Convert to a FT_PCRE */ - fvalue = fvalue_from_unparsed(FT_PCRE, s, FALSE, dfilter_fail); + fvalue = dfilter_fvalue_from_unparsed(dfw, FT_PCRE, s, FALSE); } /* The RHS should be FT_BYTES. However, there is a special case where @@ -952,17 +980,17 @@ check_relation_LHS_RANGE(const char *relation_string, FtypeCanFunc can_func _U_, else if (len_range == 1 && strlen(s) == 4 && strncmp(s, "0x", 2) == 0) { /* Even if the RHS string starts with "0x", it still could fail to * be an integer. Try converting it here. */ - fvalue = fvalue_from_unparsed(FT_UINT8, s, allow_partial_value, dfilter_fail); + fvalue = dfilter_fvalue_from_unparsed(dfw, FT_UINT8, s, allow_partial_value); if (fvalue) { FVALUE_FREE(fvalue); /* The value doees indeed fit into 8 bits. Create a BYTE_STRING * from it. Since we know that the last 2 characters are a valid * hex string, just use those directly. */ - fvalue = fvalue_from_unparsed(FT_BYTES, s+2, allow_partial_value, dfilter_fail); + fvalue = dfilter_fvalue_from_unparsed(dfw, FT_BYTES, s+2, allow_partial_value); } } else { - fvalue = fvalue_from_unparsed(FT_BYTES, s, allow_partial_value, dfilter_fail); + fvalue = dfilter_fvalue_from_unparsed(dfw, FT_BYTES, s, allow_partial_value); } if (!fvalue) { DebugLog((" 5 check_relation_LHS_RANGE(type2 = STTYPE_UNPARSED): Could not convert from string!\n")); @@ -974,7 +1002,7 @@ check_relation_LHS_RANGE(const char *relation_string, FtypeCanFunc can_func _U_, } else if (type2 == STTYPE_RANGE) { DebugLog((" 5 check_relation_LHS_RANGE(type2 = STTYPE_RANGE)\n")); - check_drange_sanity(st_arg2); + check_drange_sanity(dfw, st_arg2); } else if (type2 == STTYPE_FUNCTION) { df_func_def_t *funcdef = sttype_function_funcdef(st_arg2); @@ -982,7 +1010,7 @@ check_relation_LHS_RANGE(const char *relation_string, FtypeCanFunc can_func _U_, if (!is_bytes_type(ftype2)) { if (!ftype_can_slice(ftype2)) { - dfilter_fail("Return value of function \"%s\" is a %s and cannot be converted into a sequence of bytes.", + dfilter_fail(dfw, "Return value of function \"%s\" is a %s and cannot be converted into a sequence of bytes.", funcdef->name, ftype_pretty_name(ftype2)); THROW(TypeError); @@ -994,7 +1022,7 @@ check_relation_LHS_RANGE(const char *relation_string, FtypeCanFunc can_func _U_, sttype_test_set2_args(st_node, st_arg1, new_st); } - check_function(st_arg2); + check_function(dfw, st_arg2); } else { g_assert_not_reached(); @@ -1002,7 +1030,7 @@ check_relation_LHS_RANGE(const char *relation_string, FtypeCanFunc can_func _U_, } static stnode_t* -check_param_entity(stnode_t *st_node) +check_param_entity(dfwork_t *dfw, stnode_t *st_node) { sttype_id_t e_type; stnode_t *new_st; @@ -1013,7 +1041,7 @@ check_param_entity(stnode_t *st_node) /* If there's an unparsed string, change it to an FT_STRING */ if (e_type == STTYPE_UNPARSED) { s = (char*)stnode_data(st_node); - fvalue = fvalue_from_unparsed(FT_STRING, s, FALSE, dfilter_fail); + fvalue = dfilter_fvalue_from_unparsed(dfw, FT_STRING, s, FALSE); if (!fvalue) { THROW(TypeError); } @@ -1029,7 +1057,8 @@ check_param_entity(stnode_t *st_node) /* If the LHS of a relation test is a FUNCTION, run some checks * and possibly some modifications of syntax tree nodes. */ static void -check_relation_LHS_FUNCTION(const char *relation_string, FtypeCanFunc can_func, +check_relation_LHS_FUNCTION(dfwork_t *dfw, const char *relation_string, + FtypeCanFunc can_func, gboolean allow_partial_value, stnode_t *st_node, stnode_t *st_arg1, stnode_t *st_arg2) { @@ -1043,7 +1072,7 @@ check_relation_LHS_FUNCTION(const char *relation_string, FtypeCanFunc can_func, df_func_def_t *funcdef2; /* GSList *params; */ - check_function(st_arg1); + check_function(dfw, st_arg1); type2 = stnode_type_id(st_arg2); funcdef = sttype_function_funcdef(st_arg1); @@ -1054,7 +1083,7 @@ check_relation_LHS_FUNCTION(const char *relation_string, FtypeCanFunc can_func, DebugLog((" 5 check_relation_LHS_FUNCTION(%s)\n", relation_string)); if (!can_func(ftype1)) { - dfilter_fail("Function %s (type=%s) cannot participate in '%s' comparison.", + dfilter_fail(dfw, "Function %s (type=%s) cannot participate in '%s' comparison.", funcdef->name, ftype_pretty_name(ftype1), relation_string); THROW(TypeError); @@ -1065,14 +1094,14 @@ check_relation_LHS_FUNCTION(const char *relation_string, FtypeCanFunc can_func, ftype2 = hfinfo2->type; if (!compatible_ftypes(ftype1, ftype2)) { - dfilter_fail("Function %s and %s are not of compatible types.", + dfilter_fail(dfw, "Function %s and %s are not of compatible types.", funcdef->name, hfinfo2->abbrev); THROW(TypeError); } /* Do this check even though you'd think that if * they're compatible, then can_func() would pass. */ if (!can_func(ftype2)) { - dfilter_fail("%s (type=%s) cannot participate in specified comparison.", + dfilter_fail(dfw, "%s (type=%s) cannot participate in specified comparison.", hfinfo2->abbrev, ftype_pretty_name(ftype2)); THROW(TypeError); } @@ -1081,9 +1110,9 @@ check_relation_LHS_FUNCTION(const char *relation_string, FtypeCanFunc can_func, s = (char*)stnode_data(st_arg2); if (strcmp(relation_string, "matches") == 0) { /* Convert to a FT_PCRE */ - fvalue = fvalue_from_string(FT_PCRE, s, dfilter_fail); + fvalue = dfilter_fvalue_from_string(dfw, FT_PCRE, s); } else { - fvalue = fvalue_from_string(ftype1, s, dfilter_fail); + fvalue = dfilter_fvalue_from_string(dfw, ftype1, s); } if (!fvalue) { THROW(TypeError); @@ -1097,9 +1126,9 @@ check_relation_LHS_FUNCTION(const char *relation_string, FtypeCanFunc can_func, s = (char*)stnode_data(st_arg2); if (strcmp(relation_string, "matches") == 0) { /* Convert to a FT_PCRE */ - fvalue = fvalue_from_unparsed(FT_PCRE, s, FALSE, dfilter_fail); + fvalue = dfilter_fvalue_from_unparsed(dfw, FT_PCRE, s, FALSE); } else { - fvalue = fvalue_from_unparsed(ftype1, s, allow_partial_value, dfilter_fail); + fvalue = dfilter_fvalue_from_unparsed(dfw, ftype1, s, allow_partial_value); } if (!fvalue) { THROW(TypeError); @@ -1110,10 +1139,10 @@ check_relation_LHS_FUNCTION(const char *relation_string, FtypeCanFunc can_func, stnode_free(st_arg2); } else if (type2 == STTYPE_RANGE) { - check_drange_sanity(st_arg2); + check_drange_sanity(dfw, st_arg2); if (!is_bytes_type(ftype1)) { if (!ftype_can_slice(ftype1)) { - dfilter_fail("Function \"%s\" is a %s and cannot be converted into a sequence of bytes.", + dfilter_fail(dfw, "Function \"%s\" is a %s and cannot be converted into a sequence of bytes.", funcdef->name, ftype_pretty_name(ftype1)); THROW(TypeError); @@ -1130,7 +1159,7 @@ check_relation_LHS_FUNCTION(const char *relation_string, FtypeCanFunc can_func, ftype2 = funcdef2->retval_ftype; if (!compatible_ftypes(ftype1, ftype2)) { - dfilter_fail("Return values of function %s (type=%s) and function %s (type=%s) are not of compatible types.", + dfilter_fail(dfw, "Return values of function %s (type=%s) and function %s (type=%s) are not of compatible types.", funcdef->name, ftype_pretty_name(ftype1), funcdef2->name, ftype_pretty_name(ftype2)); THROW(TypeError); } @@ -1138,12 +1167,12 @@ check_relation_LHS_FUNCTION(const char *relation_string, FtypeCanFunc can_func, /* Do this check even though you'd think that if * they're compatible, then can_func() would pass. */ if (!can_func(ftype2)) { - dfilter_fail("Return value of %s (type=%s) cannot participate in specified comparison.", + dfilter_fail(dfw, "Return value of %s (type=%s) cannot participate in specified comparison.", funcdef2->name, ftype_pretty_name(ftype2)); THROW(TypeError); } - check_function(st_arg2); + check_function(dfw, st_arg2); } else { g_assert_not_reached(); @@ -1153,7 +1182,8 @@ check_relation_LHS_FUNCTION(const char *relation_string, FtypeCanFunc can_func, /* Check the semantics of any relational test. */ static void -check_relation(const char *relation_string, gboolean allow_partial_value, +check_relation(dfwork_t *dfw, const char *relation_string, + gboolean allow_partial_value, FtypeCanFunc can_func, stnode_t *st_node, stnode_t *st_arg1, stnode_t *st_arg2) { @@ -1173,30 +1203,30 @@ header_field_info *hfinfo; if (stnode_type_id(st_arg2) == STTYPE_FIELD) { hfinfo = (header_field_info*)stnode_data(st_arg2); if (hfinfo->type == FT_PROTOCOL) { - dfilter_fail("Protocol (\"%s\") cannot appear on right-hand side of comparison.", hfinfo->abbrev); + dfilter_fail(dfw, "Protocol (\"%s\") cannot appear on right-hand side of comparison.", hfinfo->abbrev); THROW(TypeError); } } switch (stnode_type_id(st_arg1)) { case STTYPE_FIELD: - check_relation_LHS_FIELD(relation_string, can_func, + check_relation_LHS_FIELD(dfw, relation_string, can_func, allow_partial_value, st_node, st_arg1, st_arg2); break; case STTYPE_STRING: - check_relation_LHS_STRING(relation_string, can_func, + check_relation_LHS_STRING(dfw, relation_string, can_func, allow_partial_value, st_node, st_arg1, st_arg2); break; case STTYPE_RANGE: - check_relation_LHS_RANGE(relation_string, can_func, + check_relation_LHS_RANGE(dfw, relation_string, can_func, allow_partial_value, st_node, st_arg1, st_arg2); break; case STTYPE_UNPARSED: - check_relation_LHS_UNPARSED(relation_string, can_func, + check_relation_LHS_UNPARSED(dfw, relation_string, can_func, allow_partial_value, st_node, st_arg1, st_arg2); break; case STTYPE_FUNCTION: - check_relation_LHS_FUNCTION(relation_string, can_func, + check_relation_LHS_FUNCTION(dfw, relation_string, can_func, allow_partial_value, st_node, st_arg1, st_arg2); break; @@ -1211,7 +1241,7 @@ header_field_info *hfinfo; /* Check the semantics of any type of TEST */ static void -check_test(stnode_t *st_node, GPtrArray *deprecated) +check_test(dfwork_t *dfw, stnode_t *st_node, GPtrArray *deprecated) { test_op_t st_op, st_arg_op; stnode_t *st_arg1, *st_arg2; @@ -1229,11 +1259,11 @@ check_test(stnode_t *st_node, GPtrArray *deprecated) break; case TEST_OP_EXISTS: - check_exists(st_arg1); + check_exists(dfw, st_arg1); break; case TEST_OP_NOT: - semcheck(st_arg1, deprecated); + semcheck(dfw, st_arg1, deprecated); break; case TEST_OP_AND: @@ -1254,36 +1284,36 @@ check_test(stnode_t *st_node, GPtrArray *deprecated) } } - semcheck(st_arg1, deprecated); - semcheck(st_arg2, deprecated); + semcheck(dfw, st_arg1, deprecated); + semcheck(dfw, st_arg2, deprecated); break; case TEST_OP_EQ: - check_relation("==", FALSE, ftype_can_eq, st_node, st_arg1, st_arg2); + check_relation(dfw, "==", FALSE, ftype_can_eq, st_node, st_arg1, st_arg2); break; case TEST_OP_NE: - check_relation("!=", FALSE, ftype_can_ne, st_node, st_arg1, st_arg2); + check_relation(dfw, "!=", FALSE, ftype_can_ne, st_node, st_arg1, st_arg2); break; case TEST_OP_GT: - check_relation(">", FALSE, ftype_can_gt, st_node, st_arg1, st_arg2); + check_relation(dfw, ">", FALSE, ftype_can_gt, st_node, st_arg1, st_arg2); break; case TEST_OP_GE: - check_relation(">=", FALSE, ftype_can_ge, st_node, st_arg1, st_arg2); + check_relation(dfw, ">=", FALSE, ftype_can_ge, st_node, st_arg1, st_arg2); break; case TEST_OP_LT: - check_relation("<", FALSE, ftype_can_lt, st_node, st_arg1, st_arg2); + check_relation(dfw, "<", FALSE, ftype_can_lt, st_node, st_arg1, st_arg2); break; case TEST_OP_LE: - check_relation("<=", FALSE, ftype_can_le, st_node, st_arg1, st_arg2); + check_relation(dfw, "<=", FALSE, ftype_can_le, st_node, st_arg1, st_arg2); break; case TEST_OP_BITWISE_AND: - check_relation("&", FALSE, ftype_can_bitwise_and, st_node, st_arg1, st_arg2); + check_relation(dfw, "&", FALSE, ftype_can_bitwise_and, st_node, st_arg1, st_arg2); break; case TEST_OP_CONTAINS: - check_relation("contains", TRUE, ftype_can_contains, st_node, st_arg1, st_arg2); + check_relation(dfw, "contains", TRUE, ftype_can_contains, st_node, st_arg1, st_arg2); break; case TEST_OP_MATCHES: - check_relation("matches", TRUE, ftype_can_matches, st_node, st_arg1, st_arg2); break; + check_relation(dfw, "matches", TRUE, ftype_can_matches, st_node, st_arg1, st_arg2); break; default: g_assert_not_reached(); @@ -1294,7 +1324,7 @@ check_test(stnode_t *st_node, GPtrArray *deprecated) /* Check the entire syntax tree. */ static void -semcheck(stnode_t *st_node, GPtrArray *deprecated) +semcheck(dfwork_t *dfw, stnode_t *st_node, GPtrArray *deprecated) { #ifdef DEBUG_dfilter static guint i = 0; @@ -1304,7 +1334,7 @@ semcheck(stnode_t *st_node, GPtrArray *deprecated) * node will be a TEST node, no matter what. So assert that. */ switch (stnode_type_id(st_node)) { case STTYPE_TEST: - check_test(st_node, deprecated); + check_test(dfw, st_node, deprecated); break; default: g_assert_not_reached(); @@ -1328,7 +1358,7 @@ dfw_semcheck(dfwork_t *dfw, GPtrArray *deprecated) * the semantic-checking, the semantic-checking code will * throw an exception if a problem is found. */ TRY { - semcheck(dfw->st_root, deprecated); + semcheck(dfw, dfw->st_root, deprecated); } CATCH(TypeError) { ok_filter = FALSE; diff --git a/epan/dfilter/sttype-function.h b/epan/dfilter/sttype-function.h index 4cd8ca43db..256fd9526a 100644 --- a/epan/dfilter/sttype-function.h +++ b/epan/dfilter/sttype-function.h @@ -22,6 +22,7 @@ #ifndef STTYPE_FUNCTION_H #define STTYPE_FUNCTION_H +#include "dfilter-int.h" #include "dfunctions.h" /* Set the parameters for a function stnode_t. */ diff --git a/epan/dissectors/packet-ncp2222.inc b/epan/dissectors/packet-ncp2222.inc index 9ff102d081..e12e0e4ddd 100644 --- a/epan/dissectors/packet-ncp2222.inc +++ b/epan/dissectors/packet-ncp2222.inc @@ -7405,12 +7405,14 @@ static void ncp2222_compile_dfilters(void) { int i; + gchar *err_msg; for (i = 0; i < NUM_REQ_CONDS; i++) { if (!dfilter_compile((const gchar*)req_conds[i].dfilter_text, - &req_conds[i].dfilter)) { - g_message("NCP dissector failed to compile dfilter: %s\n", - req_conds[i].dfilter_text); + &req_conds[i].dfilter, &err_msg)) { + g_message("NCP dissector failed to compile dfilter \"%s\": %s\n", + req_conds[i].dfilter_text, err_msg); + g_free(err_msg); g_assert_not_reached(); } } diff --git a/epan/ftypes/ftype-bytes.c b/epan/ftypes/ftype-bytes.c index 75552e9115..fc42f0c9f0 100644 --- a/epan/ftypes/ftype-bytes.c +++ b/epan/ftypes/ftype-bytes.c @@ -232,7 +232,7 @@ value_get(fvalue_t *fv) } static gboolean -bytes_from_string(fvalue_t *fv, const char *s, LogFunc logfunc _U_) +bytes_from_string(fvalue_t *fv, const char *s, gchar **err_msg _U_) { GByteArray *bytes; @@ -248,7 +248,7 @@ bytes_from_string(fvalue_t *fv, const char *s, LogFunc logfunc _U_) } static gboolean -bytes_from_unparsed(fvalue_t *fv, const char *s, gboolean allow_partial_value _U_, LogFunc logfunc) +bytes_from_unparsed(fvalue_t *fv, const char *s, gboolean allow_partial_value _U_, gchar **err_msg) { GByteArray *bytes; gboolean res; @@ -258,8 +258,8 @@ bytes_from_unparsed(fvalue_t *fv, const char *s, gboolean allow_partial_value _U res = hex_str_to_bytes(s, bytes, TRUE); if (!res) { - if (logfunc != NULL) - logfunc("\"%s\" is not a valid byte string.", s); + if (err_msg != NULL) + *err_msg = g_strdup_printf("\"%s\" is not a valid byte string.", s); g_byte_array_free(bytes, TRUE); return FALSE; } @@ -273,22 +273,26 @@ bytes_from_unparsed(fvalue_t *fv, const char *s, gboolean allow_partial_value _U } static gboolean -ax25_from_unparsed(fvalue_t *fv, const char *s, gboolean allow_partial_value, LogFunc logfunc) +ax25_from_unparsed(fvalue_t *fv, const char *s, gboolean allow_partial_value, gchar **err_msg) { /* - * Don't log a message if this fails; we'll try looking it - * up as another way if it does, and if that fails, - * we'll log a message. + * Don't request an error message if bytes_from_unparsed fails; + * if it does, we'll report an error specific to this address + * type. */ if (bytes_from_unparsed(fv, s, TRUE, NULL)) { if (fv->value.bytes->len > FT_AX25_ADDR_LEN) { - logfunc("\"%s\" contains too many bytes to be a valid AX.25 address.", - s); + if (err_msg != NULL) { + *err_msg = g_strdup_printf("\"%s\" contains too many bytes to be a valid AX.25 address.", + s); + } return FALSE; } else if (fv->value.bytes->len < FT_AX25_ADDR_LEN && !allow_partial_value) { - logfunc("\"%s\" contains too few bytes to be a valid AX.25 address.", - s); + if (err_msg != NULL) { + *err_msg = g_strdup_printf("\"%s\" contains too few bytes to be a valid AX.25 address.", + s); + } return FALSE; } @@ -326,27 +330,32 @@ ax25_from_unparsed(fvalue_t *fv, const char *s, gboolean allow_partial_value, Lo * * http://www.itu.int/ITU-R/terrestrial/docs/fixedmobile/fxm-art19-sec3.pdf */ - logfunc("\"%s\" is not a valid AX.25 address.", s); + if (err_msg != NULL) + *err_msg = g_strdup_printf("\"%s\" is not a valid AX.25 address.", s); return FALSE; } static gboolean -vines_from_unparsed(fvalue_t *fv, const char *s, gboolean allow_partial_value, LogFunc logfunc) +vines_from_unparsed(fvalue_t *fv, const char *s, gboolean allow_partial_value, gchar **err_msg) { /* - * Don't log a message if this fails; we'll try looking it - * up as another way if it does, and if that fails, - * we'll log a message. + * Don't request an error message if bytes_from_unparsed fails; + * if it does, we'll report an error specific to this address + * type. */ if (bytes_from_unparsed(fv, s, TRUE, NULL)) { if (fv->value.bytes->len > FT_VINES_ADDR_LEN) { - logfunc("\"%s\" contains too many bytes to be a valid Vines address.", - s); + if (err_msg != NULL) { + *err_msg = g_strdup_printf("\"%s\" contains too many bytes to be a valid Vines address.", + s); + } return FALSE; } else if (fv->value.bytes->len < FT_VINES_ADDR_LEN && !allow_partial_value) { - logfunc("\"%s\" contains too few bytes to be a valid Vines address.", - s); + if (err_msg != NULL) { + *err_msg = g_strdup_printf("\"%s\" contains too few bytes to be a valid Vines address.", + s); + } return FALSE; } @@ -355,29 +364,34 @@ vines_from_unparsed(fvalue_t *fv, const char *s, gboolean allow_partial_value, L /* XXX - need better validation of Vines address */ - logfunc("\"%s\" is not a valid Vines address.", s); + if (err_msg != NULL) + *err_msg = g_strdup_printf("\"%s\" is not a valid Vines address.", s); return FALSE; } static gboolean -ether_from_unparsed(fvalue_t *fv, const char *s, gboolean allow_partial_value, LogFunc logfunc) +ether_from_unparsed(fvalue_t *fv, const char *s, gboolean allow_partial_value, gchar **err_msg) { guint8 *mac; /* - * Don't log a message if this fails; we'll try looking it - * up as an Ethernet host name if it does, and if that fails, - * we'll log a message. + * Don't request an error message if bytes_from_unparsed fails; + * if it does, we'll report an error specific to this address + * type. */ if (bytes_from_unparsed(fv, s, TRUE, NULL)) { if (fv->value.bytes->len > FT_ETHER_LEN) { - logfunc("\"%s\" contains too many bytes to be a valid Ethernet address.", - s); + if (err_msg != NULL) { + *err_msg = g_strdup_printf("\"%s\" contains too many bytes to be a valid Ethernet address.", + s); + } return FALSE; } else if (fv->value.bytes->len < FT_ETHER_LEN && !allow_partial_value) { - logfunc("\"%s\" contains too few bytes to be a valid Ethernet address.", - s); + if (err_msg != NULL) { + *err_msg = g_strdup_printf("\"%s\" contains too few bytes to be a valid Ethernet address.", + s); + } return FALSE; } @@ -386,8 +400,10 @@ ether_from_unparsed(fvalue_t *fv, const char *s, gboolean allow_partial_value, L mac = get_ether_addr(s); if (!mac) { - logfunc("\"%s\" is not a valid hostname or Ethernet address.", - s); + if (err_msg != NULL) { + *err_msg = g_strdup_printf("\"%s\" is not a valid hostname or Ethernet address.", + s); + } return FALSE; } @@ -396,28 +412,29 @@ ether_from_unparsed(fvalue_t *fv, const char *s, gboolean allow_partial_value, L } static gboolean -oid_from_unparsed(fvalue_t *fv, const char *s, gboolean allow_partial_value _U_, LogFunc logfunc) +oid_from_unparsed(fvalue_t *fv, const char *s, gboolean allow_partial_value _U_, gchar **err_msg) { GByteArray *bytes; gboolean res; +#if 0 /* * Don't log a message if this fails; we'll try looking it * up as an OID if it does, and if that fails, * we'll log a message. */ - /* do not try it as '.' is handled as valid separator for hexbytes :( + /* do not try it as '.' is handled as valid separator for hexbytes :( */ if (bytes_from_unparsed(fv, s, TRUE, NULL)) { return TRUE; } - */ +#endif bytes = g_byte_array_new(); res = oid_str_to_bytes(s, bytes); if (!res) { - if (logfunc != NULL) - logfunc("\"%s\" is not a valid OBJECT IDENTIFIER.", s); + if (err_msg != NULL) + *err_msg = g_strdup_printf("\"%s\" is not a valid OBJECT IDENTIFIER.", s); g_byte_array_free(bytes, TRUE); return FALSE; } @@ -430,22 +447,16 @@ oid_from_unparsed(fvalue_t *fv, const char *s, gboolean allow_partial_value _U_, } static gboolean -rel_oid_from_unparsed(fvalue_t *fv, const char *s, gboolean allow_partial_value _U_, LogFunc logfunc) +rel_oid_from_unparsed(fvalue_t *fv, const char *s, gboolean allow_partial_value _U_, gchar **err_msg) { GByteArray *bytes; gboolean res; - - /* - * Don't log a message if this fails; we'll try looking it - * up as an OID if it does, and if that fails, - * we'll log a message. - */ bytes = g_byte_array_new(); res = rel_oid_str_to_bytes(s, bytes, FALSE); if (!res) { - if (logfunc != NULL) - logfunc("\"%s\" is not a valid RELATIVE-OID.", s); + if (err_msg != NULL) + *err_msg = g_strdup_printf("\"%s\" is not a valid RELATIVE-OID.", s); g_byte_array_free(bytes, TRUE); return FALSE; } @@ -458,17 +469,19 @@ rel_oid_from_unparsed(fvalue_t *fv, const char *s, gboolean allow_partial_value } static gboolean -system_id_from_unparsed(fvalue_t *fv, const char *s, gboolean allow_partial_value _U_, LogFunc logfunc) +system_id_from_unparsed(fvalue_t *fv, const char *s, gboolean allow_partial_value _U_, gchar **err_msg) { /* - * Don't log a message if this fails; we'll try looking it - * up as another way if it does, and if that fails, - * we'll log a message. + * Don't request an error message if bytes_from_unparsed fails; + * if it does, we'll report an error specific to this address + * type. */ if (bytes_from_unparsed(fv, s, TRUE, NULL)) { if (fv->value.bytes->len > MAX_SYSTEMID_LEN) { - logfunc("\"%s\" contains too many bytes to be a valid OSI System-ID.", - s); + if (err_msg != NULL) { + *err_msg = g_strdup_printf("\"%s\" contains too many bytes to be a valid OSI System-ID.", + s); + } return FALSE; } @@ -477,22 +490,25 @@ system_id_from_unparsed(fvalue_t *fv, const char *s, gboolean allow_partial_valu /* XXX - need better validation of OSI System-ID address */ - logfunc("\"%s\" is not a valid OSI System-ID.", s); + if (err_msg != NULL) + *err_msg = g_strdup_printf("\"%s\" is not a valid OSI System-ID.", s); return FALSE; } static gboolean -fcwwn_from_unparsed(fvalue_t *fv, const char *s, gboolean allow_partial_value _U_, LogFunc logfunc) +fcwwn_from_unparsed(fvalue_t *fv, const char *s, gboolean allow_partial_value _U_, gchar **err_msg) { /* - * Don't log a message if this fails; we'll try looking it - * up as another way if it does, and if that fails, - * we'll log a message. + * Don't request an error message if bytes_from_unparsed fails; + * if it does, we'll report an error specific to this address + * type. */ if (bytes_from_unparsed(fv, s, TRUE, NULL)) { if (fv->value.bytes->len > FT_FCWWN_LEN) { - logfunc("\"%s\" contains too many bytes to be a valid FCWWN.", - s); + if (err_msg != NULL) { + *err_msg = g_strdup_printf("\"%s\" contains too many bytes to be a valid FCWWN.", + s); + } return FALSE; } @@ -501,7 +517,8 @@ fcwwn_from_unparsed(fvalue_t *fv, const char *s, gboolean allow_partial_value _U /* XXX - need better validation of FCWWN address */ - logfunc("\"%s\" is not a valid FCWWN.", s); + if (err_msg != NULL) + *err_msg = g_strdup_printf("\"%s\" is not a valid FCWWN.", s); return FALSE; } diff --git a/epan/ftypes/ftype-double.c b/epan/ftypes/ftype-double.c index ef1991815e..d4778b55ce 100644 --- a/epan/ftypes/ftype-double.c +++ b/epan/ftypes/ftype-double.c @@ -47,7 +47,7 @@ value_get_floating(fvalue_t *fv) } static gboolean -val_from_unparsed(fvalue_t *fv, const char *s, gboolean allow_partial_value _U_, LogFunc logfunc) +val_from_unparsed(fvalue_t *fv, const char *s, gboolean allow_partial_value _U_, gchar **err_msg) { char *endptr = NULL; @@ -55,19 +55,23 @@ val_from_unparsed(fvalue_t *fv, const char *s, gboolean allow_partial_value _U_, if (endptr == s || *endptr != '\0') { /* This isn't a valid number. */ - logfunc("\"%s\" is not a valid number.", s); + if (err_msg != NULL) + *err_msg = g_strdup_printf("\"%s\" is not a valid number.", s); return FALSE; } if (errno == ERANGE) { if (fv->value.floating == 0) { - logfunc("\"%s\" causes floating-point underflow.", s); + if (err_msg != NULL) + *err_msg = g_strdup_printf("\"%s\" causes floating-point underflow.", s); } else if (fv->value.floating == HUGE_VAL) { - logfunc("\"%s\" causes floating-point overflow.", s); + if (err_msg != NULL) + *err_msg = g_strdup_printf("\"%s\" causes floating-point overflow.", s); } else { - logfunc("\"%s\" is not a valid floating-point number.", - s); + if (err_msg != NULL) + *err_msg = g_strdup_printf("\"%s\" is not a valid floating-point number.", + s); } return FALSE; } diff --git a/epan/ftypes/ftype-guid.c b/epan/ftypes/ftype-guid.c index 290738ae20..20d448d078 100644 --- a/epan/ftypes/ftype-guid.c +++ b/epan/ftypes/ftype-guid.c @@ -84,12 +84,13 @@ get_guid(const char *s, e_guid_t *guid) } static gboolean -guid_from_unparsed(fvalue_t *fv, const char *s, gboolean allow_partial_value _U_, LogFunc logfunc) +guid_from_unparsed(fvalue_t *fv, const char *s, gboolean allow_partial_value _U_, gchar **err_msg) { e_guid_t guid; if (!get_guid(s, &guid)) { - logfunc("\"%s\" is not a valid GUID.", s); + if (err_msg != NULL) + *err_msg = g_strdup_printf("\"%s\" is not a valid GUID.", s); return FALSE; } diff --git a/epan/ftypes/ftype-integer.c b/epan/ftypes/ftype-integer.c index 7b1e8577e4..7fe8342cb6 100644 --- a/epan/ftypes/ftype-integer.c +++ b/epan/ftypes/ftype-integer.c @@ -62,7 +62,7 @@ get_sinteger(fvalue_t *fv) static gboolean -uint_from_unparsed(fvalue_t *fv, const char *s, gboolean allow_partial_value _U_, LogFunc logfunc, +uint_from_unparsed(fvalue_t *fv, const char *s, gboolean allow_partial_value _U_, gchar **err_msg, guint32 max) { unsigned long value; @@ -73,8 +73,8 @@ uint_from_unparsed(fvalue_t *fv, const char *s, gboolean allow_partial_value _U_ * Probably a negative integer, but will be * "converted in the obvious manner" by strtoul(). */ - if (logfunc != NULL) - logfunc("\"%s\" too small for this field, minimum 0.", s); + if (err_msg != NULL) + *err_msg = g_strdup_printf("\"%s\" too small for this field, minimum 0.", s); return FALSE; } @@ -83,14 +83,14 @@ uint_from_unparsed(fvalue_t *fv, const char *s, gboolean allow_partial_value _U_ if (errno == EINVAL || endptr == s || *endptr != '\0') { /* This isn't a valid number. */ - if (logfunc != NULL) - logfunc("\"%s\" is not a valid number.", s); + if (err_msg != NULL) + *err_msg = g_strdup_printf("\"%s\" is not a valid number.", s); return FALSE; } if (errno == ERANGE) { - if (logfunc != NULL) { + if (err_msg != NULL) { if (value == ULONG_MAX) { - logfunc("\"%s\" causes an integer overflow.", + *err_msg = g_strdup_printf("\"%s\" causes an integer overflow.", s); } else { @@ -98,15 +98,15 @@ uint_from_unparsed(fvalue_t *fv, const char *s, gboolean allow_partial_value _U_ * XXX - can "strtoul()" set errno to * ERANGE without returning ULONG_MAX? */ - logfunc("\"%s\" is not an integer.", s); + *err_msg = g_strdup_printf("\"%s\" is not an integer.", s); } } return FALSE; } if (value > max) { - if (logfunc != NULL) - logfunc("\"%s\" too big for this field, maximum %u.", s, max); + if (err_msg != NULL) + *err_msg = g_strdup_printf("\"%s\" too big for this field, maximum %u.", s, max); return FALSE; } @@ -115,31 +115,31 @@ uint_from_unparsed(fvalue_t *fv, const char *s, gboolean allow_partial_value _U_ } static gboolean -uint32_from_unparsed(fvalue_t *fv, const char *s, gboolean allow_partial_value, LogFunc logfunc) +uint32_from_unparsed(fvalue_t *fv, const char *s, gboolean allow_partial_value, gchar **err_msg) { - return uint_from_unparsed (fv, s, allow_partial_value, logfunc, G_MAXUINT32); + return uint_from_unparsed (fv, s, allow_partial_value, err_msg, G_MAXUINT32); } static gboolean -uint24_from_unparsed(fvalue_t *fv, const char *s, gboolean allow_partial_value, LogFunc logfunc) +uint24_from_unparsed(fvalue_t *fv, const char *s, gboolean allow_partial_value, gchar **err_msg) { - return uint_from_unparsed (fv, s, allow_partial_value, logfunc, 0xFFFFFF); + return uint_from_unparsed (fv, s, allow_partial_value, err_msg, 0xFFFFFF); } static gboolean -uint16_from_unparsed(fvalue_t *fv, const char *s, gboolean allow_partial_value, LogFunc logfunc) +uint16_from_unparsed(fvalue_t *fv, const char *s, gboolean allow_partial_value, gchar **err_msg) { - return uint_from_unparsed (fv, s, allow_partial_value, logfunc, G_MAXUINT16); + return uint_from_unparsed (fv, s, allow_partial_value, err_msg, G_MAXUINT16); } static gboolean -uint8_from_unparsed(fvalue_t *fv, const char *s, gboolean allow_partial_value, LogFunc logfunc) +uint8_from_unparsed(fvalue_t *fv, const char *s, gboolean allow_partial_value, gchar **err_msg) { - return uint_from_unparsed (fv, s, allow_partial_value, logfunc, G_MAXUINT8); + return uint_from_unparsed (fv, s, allow_partial_value, err_msg, G_MAXUINT8); } static gboolean -sint_from_unparsed(fvalue_t *fv, const char *s, gboolean allow_partial_value _U_, LogFunc logfunc, +sint_from_unparsed(fvalue_t *fv, const char *s, gboolean allow_partial_value _U_, gchar **err_msg, gint32 max, gint32 min) { long value; @@ -150,8 +150,8 @@ sint_from_unparsed(fvalue_t *fv, const char *s, gboolean allow_partial_value _U_ * Probably a positive integer > G_MAXINT32, but will be * "converted in the obvious manner" by strtol(). */ - if (logfunc != NULL) - logfunc("\"%s\" causes an integer overflow.", s); + if (err_msg != NULL) + *err_msg = g_strdup_printf("\"%s\" causes an integer overflow.", s); return FALSE; } @@ -160,37 +160,37 @@ sint_from_unparsed(fvalue_t *fv, const char *s, gboolean allow_partial_value _U_ if (errno == EINVAL || endptr == s || *endptr != '\0') { /* This isn't a valid number. */ - if (logfunc != NULL) - logfunc("\"%s\" is not a valid number.", s); + if (err_msg != NULL) + *err_msg = g_strdup_printf("\"%s\" is not a valid number.", s); return FALSE; } if (errno == ERANGE) { - if (logfunc != NULL) { + if (err_msg != NULL) { if (value == LONG_MAX) { - logfunc("\"%s\" causes an integer overflow.", s); + *err_msg = g_strdup_printf("\"%s\" causes an integer overflow.", s); } else if (value == LONG_MIN) { - logfunc("\"%s\" causes an integer underflow.", s); + *err_msg = g_strdup_printf("\"%s\" causes an integer underflow.", s); } else { /* * XXX - can "strtol()" set errno to * ERANGE without returning ULONG_MAX? */ - logfunc("\"%s\" is not an integer.", s); + *err_msg = g_strdup_printf("\"%s\" is not an integer.", s); } } return FALSE; } if (value > max) { - if (logfunc != NULL) - logfunc("\"%s\" too big for this field, maximum %d.", + if (err_msg != NULL) + *err_msg = g_strdup_printf("\"%s\" too big for this field, maximum %d.", s, max); return FALSE; } else if (value < min) { - if (logfunc != NULL) - logfunc("\"%s\" too small for this field, minimum %d.", + if (err_msg != NULL) + *err_msg = g_strdup_printf("\"%s\" too small for this field, minimum %d.", s, min); return FALSE; } @@ -200,27 +200,27 @@ sint_from_unparsed(fvalue_t *fv, const char *s, gboolean allow_partial_value _U_ } static gboolean -sint32_from_unparsed(fvalue_t *fv, const char *s, gboolean allow_partial_value, LogFunc logfunc) +sint32_from_unparsed(fvalue_t *fv, const char *s, gboolean allow_partial_value, gchar **err_msg) { - return sint_from_unparsed (fv, s, allow_partial_value, logfunc, G_MAXINT32, G_MININT32); + return sint_from_unparsed (fv, s, allow_partial_value, err_msg, G_MAXINT32, G_MININT32); } static gboolean -sint24_from_unparsed(fvalue_t *fv, const char *s, gboolean allow_partial_value, LogFunc logfunc) +sint24_from_unparsed(fvalue_t *fv, const char *s, gboolean allow_partial_value, gchar **err_msg) { - return sint_from_unparsed (fv, s, allow_partial_value, logfunc, 0x7FFFFF, -0x800000); + return sint_from_unparsed (fv, s, allow_partial_value, err_msg, 0x7FFFFF, -0x800000); } static gboolean -sint16_from_unparsed(fvalue_t *fv, const char *s, gboolean allow_partial_value, LogFunc logfunc) +sint16_from_unparsed(fvalue_t *fv, const char *s, gboolean allow_partial_value, gchar **err_msg) { - return sint_from_unparsed (fv, s, allow_partial_value, logfunc, G_MAXINT16, G_MININT16); + return sint_from_unparsed (fv, s, allow_partial_value, err_msg, G_MAXINT16, G_MININT16); } static gboolean -sint8_from_unparsed(fvalue_t *fv, const char *s, gboolean allow_partial_value, LogFunc logfunc) +sint8_from_unparsed(fvalue_t *fv, const char *s, gboolean allow_partial_value, gchar **err_msg) { - return sint_from_unparsed (fv, s, allow_partial_value, logfunc, G_MAXINT8, G_MININT8); + return sint_from_unparsed (fv, s, allow_partial_value, err_msg, G_MAXINT8, G_MININT8); } static int @@ -256,15 +256,15 @@ uinteger_to_repr(fvalue_t *fv, ftrepr_t rtype _U_, int field_display _U_, char * } static gboolean -ipxnet_from_unparsed(fvalue_t *fv, const char *s, gboolean allow_partial_value _U_, LogFunc logfunc) +ipxnet_from_unparsed(fvalue_t *fv, const char *s, gboolean allow_partial_value _U_, gchar **err_msg) { guint32 val; gboolean known; /* - * Don't log a message if this fails; we'll try looking it - * up as an IPX network name if it does, and if that fails, - * we'll log a message. + * Don't request an errror message if uint32_from_unparsed fails; + * if it does, we'll try looking it up as an IPX network name, and + * if that fails, we'll report an error message for that. */ if (uint32_from_unparsed(fv, s, TRUE, NULL)) { return TRUE; @@ -276,7 +276,8 @@ ipxnet_from_unparsed(fvalue_t *fv, const char *s, gboolean allow_partial_value _ return TRUE; } - logfunc("\"%s\" is not a valid IPX network name or address.", s); + if (err_msg != NULL) + *err_msg = g_strdup_printf("\"%s\" is not a valid IPX network name or address.", s); return FALSE; } @@ -377,7 +378,7 @@ get_integer64(fvalue_t *fv) } static gboolean -uint64_from_unparsed(fvalue_t *fv, const char *s, gboolean allow_partial_value _U_, LogFunc logfunc) +uint64_from_unparsed(fvalue_t *fv, const char *s, gboolean allow_partial_value _U_, gchar **err_msg) { guint64 value; char *endptr; @@ -387,8 +388,8 @@ uint64_from_unparsed(fvalue_t *fv, const char *s, gboolean allow_partial_value _ * Probably a negative integer, but will be * "converted in the obvious manner" by g_ascii_strtoull(). */ - if (logfunc != NULL) - logfunc("\"%s\" causes an integer underflow.", s); + if (err_msg != NULL) + *err_msg = g_strdup_printf("\"%s\" causes an integer underflow.", s); return FALSE; } @@ -397,21 +398,21 @@ uint64_from_unparsed(fvalue_t *fv, const char *s, gboolean allow_partial_value _ if (errno == EINVAL || endptr == s || *endptr != '\0') { /* This isn't a valid number. */ - if (logfunc != NULL) - logfunc("\"%s\" is not a valid number.", s); + if (err_msg != NULL) + *err_msg = g_strdup_printf("\"%s\" is not a valid number.", s); return FALSE; } if (errno == ERANGE) { - if (logfunc != NULL) { + if (err_msg != NULL) { if (value == G_MAXUINT64) { - logfunc("\"%s\" causes an integer overflow.", s); + *err_msg = g_strdup_printf("\"%s\" causes an integer overflow.", s); } else { /* * XXX - can "strtoul()" set errno to * ERANGE without returning ULONG_MAX? */ - logfunc("\"%s\" is not an integer.", s); + *err_msg = g_strdup_printf("\"%s\" is not an integer.", s); } } return FALSE; @@ -422,7 +423,7 @@ uint64_from_unparsed(fvalue_t *fv, const char *s, gboolean allow_partial_value _ } static gboolean -sint64_from_unparsed(fvalue_t *fv, const char *s, gboolean allow_partial_value _U_, LogFunc logfunc) +sint64_from_unparsed(fvalue_t *fv, const char *s, gboolean allow_partial_value _U_, gchar **err_msg) { gint64 value; char *endptr; @@ -432,8 +433,8 @@ sint64_from_unparsed(fvalue_t *fv, const char *s, gboolean allow_partial_value _ * Probably a positive integer > G_MAXINT64, but will be * "converted in the obvious manner" by g_ascii_strtoll(). */ - if (logfunc != NULL) - logfunc("\"%s\" causes an integer overflow.", s); + if (err_msg != NULL) + *err_msg = g_strdup_printf("\"%s\" causes an integer overflow.", s); return FALSE; } @@ -442,24 +443,24 @@ sint64_from_unparsed(fvalue_t *fv, const char *s, gboolean allow_partial_value _ if (errno == EINVAL || endptr == s || *endptr != '\0') { /* This isn't a valid number. */ - if (logfunc != NULL) - logfunc("\"%s\" is not a valid number.", s); + if (err_msg != NULL) + *err_msg = g_strdup_printf("\"%s\" is not a valid number.", s); return FALSE; } if (errno == ERANGE) { - if (logfunc != NULL) { + if (err_msg != NULL) { if (value == G_MAXINT64) { - logfunc("\"%s\" causes an integer overflow.", s); + *err_msg = g_strdup_printf("\"%s\" causes an integer overflow.", s); } else if (value == G_MININT64) { - logfunc("\"%s\" causes an integer underflow.", s); + *err_msg = g_strdup_printf("\"%s\" causes an integer underflow.", s); } else { /* * XXX - can "strtol()" set errno to * ERANGE without returning LONG_MAX? */ - logfunc("\"%s\" is not an integer.", s); + *err_msg = g_strdup_printf("\"%s\" is not an integer.", s); } } return FALSE; @@ -611,19 +612,19 @@ bool_ne(const fvalue_t *a, const fvalue_t *b) /* EUI64-specific */ static gboolean -eui64_from_unparsed(fvalue_t *fv, const char *s, gboolean allow_partial_value _U_, LogFunc logfunc) +eui64_from_unparsed(fvalue_t *fv, const char *s, gboolean allow_partial_value _U_, gchar **err_msg) { - /* - * Don't log a message if this fails; we'll try looking it - * up as an EUI64 Address if it does, and if that fails, - * we'll log a message. + * Don't request an error message if uint64_from_unparsed fails; + * if it does, we'll report an error specific to this address + * type. */ if (uint64_from_unparsed(fv, s, TRUE, NULL)) { return TRUE; } - logfunc("\"%s\" is not a valid EUI64 Address", s); + if (err_msg != NULL) + *err_msg = g_strdup_printf("\"%s\" is not a valid EUI64 Address", s); return FALSE; } diff --git a/epan/ftypes/ftype-ipv4.c b/epan/ftypes/ftype-ipv4.c index d7dada34ea..7f46a35e12 100644 --- a/epan/ftypes/ftype-ipv4.c +++ b/epan/ftypes/ftype-ipv4.c @@ -41,7 +41,7 @@ value_get(fvalue_t *fv) } static gboolean -val_from_unparsed(fvalue_t *fv, const char *s, gboolean allow_partial_value _U_, LogFunc logfunc) +val_from_unparsed(fvalue_t *fv, const char *s, gboolean allow_partial_value _U_, gchar **err_msg) { guint32 addr; unsigned int nmask_bits; @@ -64,7 +64,10 @@ val_from_unparsed(fvalue_t *fv, const char *s, gboolean allow_partial_value _U_, } if (!get_host_ipaddr(addr_str, &addr)) { - logfunc("\"%s\" is not a valid hostname or IPv4 address.", addr_str); + if (err_msg != NULL) { + *err_msg = g_strdup_printf("\"%s\" is not a valid hostname or IPv4 address.", + addr_str); + } if (free_addr_str) wmem_free(NULL, addr_str); return FALSE; @@ -80,7 +83,7 @@ val_from_unparsed(fvalue_t *fv, const char *s, gboolean allow_partial_value _U_, net_str = has_slash + 1; /* XXX - this is inefficient */ - nmask_fvalue = fvalue_from_unparsed(FT_UINT32, net_str, FALSE, logfunc); + nmask_fvalue = fvalue_from_unparsed(FT_UINT32, net_str, FALSE, err_msg); if (!nmask_fvalue) { return FALSE; } @@ -88,8 +91,10 @@ val_from_unparsed(fvalue_t *fv, const char *s, gboolean allow_partial_value _U_, FVALUE_FREE(nmask_fvalue); if (nmask_bits > 32) { - logfunc("Netmask bits in a CIDR IPv4 address should be <= 32, not %u", - nmask_bits); + if (err_msg != NULL) { + *err_msg = g_strdup_printf("Netmask bits in a CIDR IPv4 address should be <= 32, not %u", + nmask_bits); + } return FALSE; } ipv4_addr_set_netmask_bits(&fv->value.ipv4, nmask_bits); diff --git a/epan/ftypes/ftype-ipv6.c b/epan/ftypes/ftype-ipv6.c index bc72f58144..b69139df11 100644 --- a/epan/ftypes/ftype-ipv6.c +++ b/epan/ftypes/ftype-ipv6.c @@ -34,7 +34,7 @@ ipv6_fvalue_set(fvalue_t *fv, const guint8 *value) } static gboolean -ipv6_from_unparsed(fvalue_t *fv, const char *s, gboolean allow_partial_value _U_, LogFunc logfunc) +ipv6_from_unparsed(fvalue_t *fv, const char *s, gboolean allow_partial_value _U_, gchar **err_msg) { const char *has_slash; char *addr_str; @@ -51,7 +51,8 @@ ipv6_from_unparsed(fvalue_t *fv, const char *s, gboolean allow_partial_value _U_ addr_str = (char*)s; if (!get_host_ipaddr6(addr_str, &(fv->value.ipv6.addr))) { - logfunc("\"%s\" is not a valid hostname or IPv6 address.", s); + if (err_msg != NULL) + *err_msg = g_strdup_printf("\"%s\" is not a valid hostname or IPv6 address.", s); if (free_addr_str) wmem_free(NULL, addr_str); return FALSE; @@ -63,7 +64,7 @@ ipv6_from_unparsed(fvalue_t *fv, const char *s, gboolean allow_partial_value _U_ /* If prefix */ if (has_slash) { /* XXX - this is inefficient */ - nmask_fvalue = fvalue_from_unparsed(FT_UINT32, has_slash+1, FALSE, logfunc); + nmask_fvalue = fvalue_from_unparsed(FT_UINT32, has_slash+1, FALSE, err_msg); if (!nmask_fvalue) { return FALSE; } @@ -71,8 +72,10 @@ ipv6_from_unparsed(fvalue_t *fv, const char *s, gboolean allow_partial_value _U_ FVALUE_FREE(nmask_fvalue); if (nmask_bits > 128) { - logfunc("Prefix in a IPv6 address should be <= 128, not %u", - nmask_bits); + if (err_msg != NULL) { + *err_msg = g_strdup_printf("Prefix in a IPv6 address should be <= 128, not %u", + nmask_bits); + } return FALSE; } fv->value.ipv6.prefix = nmask_bits; diff --git a/epan/ftypes/ftype-pcre.c b/epan/ftypes/ftype-pcre.c index f324370527..88ecb104d4 100644 --- a/epan/ftypes/ftype-pcre.c +++ b/epan/ftypes/ftype-pcre.c @@ -68,9 +68,10 @@ raw_flag_needed(const gchar *pattern) } /* Generate a FT_PCRE from a parsed string pattern. - * Uses the specified logfunc() to report errors. */ + * On failure, if err_msg is non-null, set *err_msg to point to a + * g_malloc()ed error message. */ static gboolean -val_from_string(fvalue_t *fv, const char *pattern, LogFunc logfunc) +val_from_string(fvalue_t *fv, const char *pattern, gchar **err_msg) { GError *regex_error = NULL; GRegexCompileFlags cflags = G_REGEX_OPTIMIZE; @@ -93,8 +94,8 @@ val_from_string(fvalue_t *fv, const char *pattern, LogFunc logfunc) ); if (regex_error) { - if (logfunc) { - logfunc(regex_error->message); + if (err_msg) { + *err_msg = g_strdup(regex_error->message); } g_error_free(regex_error); if (fv->value.re) { @@ -106,13 +107,14 @@ val_from_string(fvalue_t *fv, const char *pattern, LogFunc logfunc) } /* Generate a FT_PCRE from an unparsed string pattern. - * Uses the specified logfunc() to report errors. */ + * On failure, if err_msg is non-null, set *err_msg to point to a + * g_malloc()ed error message. */ static gboolean -val_from_unparsed(fvalue_t *fv, const char *pattern, gboolean allow_partial_value _U_, LogFunc logfunc) +val_from_unparsed(fvalue_t *fv, const char *pattern, gboolean allow_partial_value _U_, gchar **err_msg) { g_assert(! allow_partial_value); - return val_from_string(fv, pattern, logfunc); + return val_from_string(fv, pattern, err_msg); } static int diff --git a/epan/ftypes/ftype-string.c b/epan/ftypes/ftype-string.c index ff3b9c3c6c..d7d0a0060e 100644 --- a/epan/ftypes/ftype-string.c +++ b/epan/ftypes/ftype-string.c @@ -89,7 +89,7 @@ value_get(fvalue_t *fv) } static gboolean -val_from_string(fvalue_t *fv, const char *s, LogFunc logfunc _U_) +val_from_string(fvalue_t *fv, const char *s, gchar **err_msg _U_) { /* Free up the old value, if we have one */ string_fvalue_free(fv); @@ -99,7 +99,7 @@ val_from_string(fvalue_t *fv, const char *s, LogFunc logfunc _U_) } static gboolean -val_from_unparsed(fvalue_t *fv, const char *s, gboolean allow_partial_value _U_, LogFunc logfunc) +val_from_unparsed(fvalue_t *fv, const char *s, gboolean allow_partial_value _U_, gchar **err_msg) { fvalue_t *fv_bytes; @@ -123,7 +123,7 @@ val_from_unparsed(fvalue_t *fv, const char *s, gboolean allow_partial_value _U_, } /* Just turn it into a string */ - return val_from_string(fv, s, logfunc); + return val_from_string(fv, s, err_msg); } static guint diff --git a/epan/ftypes/ftype-time.c b/epan/ftypes/ftype-time.c index 09ae23f869..6ee8907142 100644 --- a/epan/ftypes/ftype-time.c +++ b/epan/ftypes/ftype-time.c @@ -168,7 +168,7 @@ get_nsecs(const char *startp, int *nsecs) } static gboolean -relative_val_from_unparsed(fvalue_t *fv, const char *s, gboolean allow_partial_value _U_, LogFunc logfunc) +relative_val_from_unparsed(fvalue_t *fv, const char *s, gboolean allow_partial_value _U_, gchar **err_msg) { const char *curptr; char *endptr; @@ -227,14 +227,14 @@ relative_val_from_unparsed(fvalue_t *fv, const char *s, gboolean allow_partial_v return TRUE; fail: - if (logfunc != NULL) - logfunc("\"%s\" is not a valid time.", s); + if (err_msg != NULL) + *err_msg = g_strdup_printf("\"%s\" is not a valid time.", s); return FALSE; } static gboolean -absolute_val_from_string(fvalue_t *fv, const char *s, LogFunc logfunc) +absolute_val_from_string(fvalue_t *fv, const char *s, gchar **err_msg) { struct tm tm; char *curptr; @@ -291,16 +291,16 @@ absolute_val_from_string(fvalue_t *fv, const char *s, LogFunc logfunc) return TRUE; fail: - if (logfunc != NULL) - logfunc("\"%s\" is not a valid absolute time. Example: \"Nov 12, 1999 08:55:44.123\" or \"2011-07-04 12:34:56\"", + if (err_msg != NULL) + *err_msg = g_strdup_printf("\"%s\" is not a valid absolute time. Example: \"Nov 12, 1999 08:55:44.123\" or \"2011-07-04 12:34:56\"", s); return FALSE; } static gboolean -absolute_val_from_unparsed(fvalue_t *fv, const char *s, gboolean allow_partial_value _U_, LogFunc logfunc) +absolute_val_from_unparsed(fvalue_t *fv, const char *s, gboolean allow_partial_value _U_, gchar **err_msg) { - return absolute_val_from_string(fv, s, logfunc); + return absolute_val_from_string(fv, s, err_msg); } static void diff --git a/epan/ftypes/ftype-tvbuff.c b/epan/ftypes/ftype-tvbuff.c index 714f545dfe..950379a879 100644 --- a/epan/ftypes/ftype-tvbuff.c +++ b/epan/ftypes/ftype-tvbuff.c @@ -61,7 +61,7 @@ free_tvb_data(void *data) } static gboolean -val_from_string(fvalue_t *fv, const char *s, LogFunc logfunc _U_) +val_from_string(fvalue_t *fv, const char *s, gchar **err_msg _U_) { tvbuff_t *new_tvb; guint8 *private_data; @@ -85,7 +85,7 @@ val_from_string(fvalue_t *fv, const char *s, LogFunc logfunc _U_) } static gboolean -val_from_unparsed(fvalue_t *fv, const char *s, gboolean allow_partial_value _U_, LogFunc logfunc) +val_from_unparsed(fvalue_t *fv, const char *s, gboolean allow_partial_value _U_, gchar **err_msg) { fvalue_t *fv_bytes; tvbuff_t *new_tvb; @@ -114,7 +114,7 @@ val_from_unparsed(fvalue_t *fv, const char *s, gboolean allow_partial_value _U_, } /* Treat it as a string. */ - return val_from_string(fv, s, logfunc); + return val_from_string(fv, s, err_msg); } static int diff --git a/epan/ftypes/ftypes-int.h b/epan/ftypes/ftypes-int.h index c2aaf11427..020a571f21 100644 --- a/epan/ftypes/ftypes-int.h +++ b/epan/ftypes/ftypes-int.h @@ -48,8 +48,8 @@ void ftype_register_pcre(void); typedef void (*FvalueNewFunc)(fvalue_t*); typedef void (*FvalueFreeFunc)(fvalue_t*); -typedef gboolean (*FvalueFromUnparsed)(fvalue_t*, const char*, gboolean, LogFunc); -typedef gboolean (*FvalueFromString)(fvalue_t*, const char*, LogFunc); +typedef gboolean (*FvalueFromUnparsed)(fvalue_t*, const char*, gboolean, gchar **); +typedef gboolean (*FvalueFromString)(fvalue_t*, const char*, gchar **); typedef void (*FvalueToStringRepr)(fvalue_t*, ftrepr_t, int field_display, char*volatile); typedef int (*FvalueStringReprLen)(fvalue_t*, ftrepr_t, int field_display); diff --git a/epan/ftypes/ftypes.c b/epan/ftypes/ftypes.c index a06594392c..7f4aba791c 100644 --- a/epan/ftypes/ftypes.c +++ b/epan/ftypes/ftypes.c @@ -288,38 +288,48 @@ fvalue_init(fvalue_t *fv, ftenum_t ftype) } fvalue_t* -fvalue_from_unparsed(ftenum_t ftype, const char *s, gboolean allow_partial_value, LogFunc logfunc) +fvalue_from_unparsed(ftenum_t ftype, const char *s, gboolean allow_partial_value, gchar **err_msg) { fvalue_t *fv; fv = fvalue_new(ftype); if (fv->ftype->val_from_unparsed) { - if (fv->ftype->val_from_unparsed(fv, s, allow_partial_value, logfunc)) { + if (fv->ftype->val_from_unparsed(fv, s, allow_partial_value, err_msg)) { + /* Success */ + if (err_msg != NULL) + *err_msg = NULL; return fv; } } else { - logfunc("\"%s\" cannot be converted to %s.", - s, ftype_pretty_name(ftype)); + if (err_msg != NULL) { + *err_msg = g_strdup_printf("\"%s\" cannot be converted to %s.", + s, ftype_pretty_name(ftype)); + } } FVALUE_FREE(fv); return NULL; } fvalue_t* -fvalue_from_string(ftenum_t ftype, const char *s, LogFunc logfunc) +fvalue_from_string(ftenum_t ftype, const char *s, gchar **err_msg) { fvalue_t *fv; fv = fvalue_new(ftype); if (fv->ftype->val_from_string) { - if (fv->ftype->val_from_string(fv, s, logfunc)) { + if (fv->ftype->val_from_string(fv, s, err_msg)) { + /* Success */ + if (err_msg != NULL) + *err_msg = NULL; return fv; } } else { - logfunc("\"%s\" cannot be converted to %s.", - s, ftype_pretty_name(ftype)); + if (err_msg != NULL) { + *err_msg = g_strdup_printf("\"%s\" cannot be converted to %s.", + s, ftype_pretty_name(ftype)); + } } FVALUE_FREE(fv); return NULL; diff --git a/epan/ftypes/ftypes.h b/epan/ftypes/ftypes.h index 6e969043ca..d830722fc4 100644 --- a/epan/ftypes/ftypes.h +++ b/epan/ftypes/ftypes.h @@ -203,8 +203,6 @@ typedef struct _fvalue_t { } fvalue_t; -typedef void (*LogFunc)(const char*,...); - fvalue_t* fvalue_new(ftenum_t ftype); @@ -213,10 +211,10 @@ fvalue_init(fvalue_t *fv, ftenum_t ftype); WS_DLL_PUBLIC fvalue_t* -fvalue_from_unparsed(ftenum_t ftype, const char *s, gboolean allow_partial_value, LogFunc logfunc); +fvalue_from_unparsed(ftenum_t ftype, const char *s, gboolean allow_partial_value, gchar **err_msg); fvalue_t* -fvalue_from_string(ftenum_t ftype, const char *s, LogFunc logfunc); +fvalue_from_string(ftenum_t ftype, const char *s, gchar **err_msg); /* Returns the length of the string required to hold the * string representation of the the field value. diff --git a/epan/funnel.h b/epan/funnel.h index 2b2282ab75..3d66f54c63 100644 --- a/epan/funnel.h +++ b/epan/funnel.h @@ -79,7 +79,7 @@ typedef struct _funnel_ops_t { gchar * (*get_filter)(void); void (*set_filter)(const char*); void (*set_color_filter_slot)(guint8 flit_nr, const gchar* filter); - gboolean (*open_file)(const char* fname, const char* filter, const char** error); + gboolean (*open_file)(const char* fname, const char* filter, char** error); void (*reload)(void); void (*apply_filter)(void); diff --git a/epan/tap.c b/epan/tap.c index d2b6fe9183..ba4a1839e5 100644 --- a/epan/tap.c +++ b/epan/tap.c @@ -472,6 +472,7 @@ register_tap_listener(const char *tapname, void *tapdata, const char *fstring, tap_listener_t *tl; int tap_id; GString *error_string; + gchar *err_msg; tap_id=find_tap_id(tapname); if(!tap_id){ @@ -485,11 +486,12 @@ register_tap_listener(const char *tapname, void *tapdata, const char *fstring, tl->needs_redraw=TRUE; tl->flags=flags; if(fstring){ - if(!dfilter_compile(fstring, &tl->code)){ + if(!dfilter_compile(fstring, &tl->code, &err_msg)){ error_string = g_string_new(""); g_string_printf(error_string, "Filter \"%s\" is invalid - %s", - fstring, dfilter_error_msg); + fstring, err_msg); + g_free(err_msg); g_free(tl); return error_string; } @@ -514,6 +516,7 @@ set_tap_dfilter(void *tapdata, const char *fstring) { tap_listener_t *tl=NULL,*tl2; GString *error_string; + gchar *err_msg; if(!tap_listener_queue){ return NULL; @@ -538,11 +541,12 @@ set_tap_dfilter(void *tapdata, const char *fstring) } tl->needs_redraw=TRUE; if(fstring){ - if(!dfilter_compile(fstring, &tl->code)){ + if(!dfilter_compile(fstring, &tl->code, &err_msg)){ error_string = g_string_new(""); g_string_printf(error_string, "Filter \"%s\" is invalid - %s", - fstring, dfilter_error_msg); + fstring, err_msg); + g_free(err_msg); return error_string; } } diff --git a/epan/wslua/wslua_field.c b/epan/wslua/wslua_field.c index 5fe0715bba..5e96f25c83 100644 --- a/epan/wslua/wslua_field.c +++ b/epan/wslua/wslua_field.c @@ -475,6 +475,7 @@ void lua_prime_all_fields(proto_tree* tree _U_) { GString* fake_tap_filter = g_string_new("frame"); guint i; static gboolean fake_tap = FALSE; + gchar *err_msg; for(i=0; i < wanted_fields->len; i++) { Field f = (Field)g_ptr_array_index(wanted_fields,i); @@ -514,8 +515,9 @@ void lua_prime_all_fields(proto_tree* tree _U_) { dfilter_free(wslua_dfilter); wslua_dfilter = NULL; } - if (!dfilter_compile(fake_tap_filter->str, &wslua_dfilter)) { - report_failure("while compiling dfilter for wslua: '%s'", fake_tap_filter->str); + if (!dfilter_compile(fake_tap_filter->str, &wslua_dfilter, &err_msg)) { + report_failure("while compiling dfilter \"%s\" for wslua: %s", fake_tap_filter->str, err_msg); + g_free(err_msg); } } } diff --git a/epan/wslua/wslua_gui.c b/epan/wslua/wslua_gui.c index b73564eff9..34623dfd71 100644 --- a/epan/wslua/wslua_gui.c +++ b/epan/wslua/wslua_gui.c @@ -730,7 +730,7 @@ WSLUA_FUNCTION wslua_open_capture_file(lua_State* L) { /* Open and display a cap const char* fname = luaL_checkstring(L,WSLUA_ARG_open_capture_file_FILENAME); const char* filter = luaL_optstring(L,WSLUA_ARG_open_capture_file_FILTER,NULL); - const char* error = NULL; + char* error = NULL; if (!ops->open_file) { WSLUA_ERROR(open_capture_file, "GUI not available"); @@ -740,9 +740,10 @@ WSLUA_FUNCTION wslua_open_capture_file(lua_State* L) { /* Open and display a cap if (! ops->open_file(fname,filter,&error) ) { lua_pushboolean(L,FALSE); - if (error) + if (error) { lua_pushstring(L,error); - else + g_free(error); + } else lua_pushnil(L); return 2; diff --git a/file.c b/file.c index d3077039fe..01ed0d4fda 100644 --- a/file.c +++ b/file.c @@ -546,7 +546,7 @@ cf_read(capture_file *cf, gboolean reloading) * We assume this will not fail since cf->dfilter is only set in * cf_filter IFF the filter was valid. */ - compiled = dfilter_compile(cf->dfilter, &dfcode); + compiled = dfilter_compile(cf->dfilter, &dfcode, NULL); g_assert(!cf->dfilter || (compiled && dfcode)); /* Get the union of the flags for all tap listeners. */ @@ -793,7 +793,7 @@ cf_continue_tail(capture_file *cf, volatile int to_read, int *err) * We assume this will not fail since cf->dfilter is only set in * cf_filter IFF the filter was valid. */ - compiled = dfilter_compile(cf->dfilter, &dfcode); + compiled = dfilter_compile(cf->dfilter, &dfcode, NULL); g_assert(!cf->dfilter || (compiled && dfcode)); /* Get the union of the flags for all tap listeners. */ @@ -920,7 +920,7 @@ cf_finish_tail(capture_file *cf, int *err) * We assume this will not fail since cf->dfilter is only set in * cf_filter IFF the filter was valid. */ - compiled = dfilter_compile(cf->dfilter, &dfcode); + compiled = dfilter_compile(cf->dfilter, &dfcode, NULL); g_assert(!cf->dfilter || (compiled && dfcode)); /* Get the union of the flags for all tap listeners. */ @@ -1652,6 +1652,7 @@ cf_filter_packets(capture_file *cf, gchar *dftext, gboolean force) const char *filter_new = dftext ? dftext : ""; const char *filter_old = cf->dfilter ? cf->dfilter : ""; dfilter_t *dfcode; + gchar *err_msg; GTimeVal start_time; /* if new filter equals old one, do nothing unless told to do so */ @@ -1671,12 +1672,13 @@ cf_filter_packets(capture_file *cf, gchar *dftext, gboolean force) * and try to compile it. */ dftext = g_strdup(dftext); - if (!dfilter_compile(dftext, &dfcode)) { + if (!dfilter_compile(dftext, &dfcode, &err_msg)) { /* The attempt failed; report an error. */ simple_message_box(ESD_TYPE_ERROR, NULL, "See the help for a description of the display filter syntax.", "\"%s\" isn't a valid display filter: %s", - dftext, dfilter_error_msg); + dftext, err_msg); + g_free(err_msg); g_free(dftext); return CF_ERROR; } @@ -1819,7 +1821,7 @@ rescan_packets(capture_file *cf, const char *action, const char *action_item, gb * We assume this will not fail since cf->dfilter is only set in * cf_filter IFF the filter was valid. */ - compiled = dfilter_compile(cf->dfilter, &dfcode); + compiled = dfilter_compile(cf->dfilter, &dfcode, NULL); g_assert(!cf->dfilter || (compiled && dfcode)); /* Get the union of the flags for all tap listeners. */ @@ -3447,7 +3449,7 @@ cf_find_packet_dfilter_string(capture_file *cf, const char *filter, dfilter_t *sfcode; gboolean result; - if (!dfilter_compile(filter, &sfcode)) { + if (!dfilter_compile(filter, &sfcode, NULL)) { /* * XXX - this shouldn't happen, as the filter string is machine * generated diff --git a/rawshark.c b/rawshark.c index 29f4347787..41fce66ecf 100644 --- a/rawshark.c +++ b/rawshark.c @@ -806,8 +806,11 @@ main(int argc, char *argv[]) if (n_rfilters != 0) { for (i = 0; i < n_rfilters; i++) { - if (!dfilter_compile(rfilters[i], &rfcodes[n_rfcodes])) { - cmdarg_err("%s", dfilter_error_msg); + gchar *err_msg; + + if (!dfilter_compile(rfilters[i], &rfcodes[n_rfcodes], &err_msg)) { + cmdarg_err("%s", err_msg); + g_free(err_msg); epan_free(cfile.epan); epan_cleanup(); exit(2); diff --git a/tfshark.c b/tfshark.c index 0132208e60..c05dbadcdd 100644 --- a/tfshark.c +++ b/tfshark.c @@ -793,6 +793,7 @@ main(int argc, char *argv[]) gchar *dfilter = NULL; dfilter_t *rfcode = NULL; dfilter_t *dfcode = NULL; + gchar *err_msg; e_prefs *prefs_p; int log_flags; gchar *output_only = NULL; @@ -1430,8 +1431,9 @@ main(int argc, char *argv[]) build_column_format_array(&cfile.cinfo, prefs_p->num_cols, TRUE); if (rfilter != NULL) { - if (!dfilter_compile(rfilter, &rfcode)) { - cmdarg_err("%s", dfilter_error_msg); + if (!dfilter_compile(rfilter, &rfcode, &err_msg)) { + cmdarg_err("%s", err_msg); + g_free(err_msg); epan_cleanup(); return 2; } @@ -1439,8 +1441,9 @@ main(int argc, char *argv[]) cfile.rfcode = rfcode; if (dfilter != NULL) { - if (!dfilter_compile(dfilter, &dfcode)) { - cmdarg_err("%s", dfilter_error_msg); + if (!dfilter_compile(dfilter, &dfcode, &err_msg)) { + cmdarg_err("%s", err_msg); + g_free(err_msg); epan_cleanup(); return 2; } diff --git a/tshark.c b/tshark.c index 54a70516c8..8c3b935663 100644 --- a/tshark.c +++ b/tshark.c @@ -993,6 +993,7 @@ main(int argc, char *argv[]) #endif dfilter_t *rfcode = NULL; dfilter_t *dfcode = NULL; + gchar *err_msg; e_prefs *prefs_p; char badopt; int log_flags; @@ -2026,8 +2027,9 @@ main(int argc, char *argv[]) #endif if (rfilter != NULL) { - if (!dfilter_compile(rfilter, &rfcode)) { - cmdarg_err("%s", dfilter_error_msg); + if (!dfilter_compile(rfilter, &rfcode, &err_msg)) { + cmdarg_err("%s", err_msg); + g_free(err_msg); epan_cleanup(); #ifdef HAVE_PCAP_OPEN_DEAD { @@ -2050,8 +2052,9 @@ main(int argc, char *argv[]) cfile.rfcode = rfcode; if (dfilter != NULL) { - if (!dfilter_compile(dfilter, &dfcode)) { - cmdarg_err("%s", dfilter_error_msg); + if (!dfilter_compile(dfilter, &dfcode, &err_msg)) { + cmdarg_err("%s", err_msg); + g_free(err_msg); epan_cleanup(); #ifdef HAVE_PCAP_OPEN_DEAD { @@ -2587,7 +2590,7 @@ capture_input_cfilter_error_message(capture_session *cap_session, guint i, char g_assert(i < capture_opts->ifaces->len); interface_opts = g_array_index(capture_opts->ifaces, interface_options, i); - if (dfilter_compile(interface_opts.cfilter, &rfcode) && rfcode != NULL) { + if (dfilter_compile(interface_opts.cfilter, &rfcode, NULL) && rfcode != NULL) { cmdarg_err( "Invalid capture filter \"%s\" for interface '%s'.\n" "\n" diff --git a/ui/capture.c b/ui/capture.c index 254cda3f4e..1a9543db42 100644 --- a/ui/capture.c +++ b/ui/capture.c @@ -514,7 +514,7 @@ capture_input_cfilter_error_message(capture_session *cap_session, guint i, safe_descr = simple_dialog_format_message(interface_opts.descr); safe_cfilter_error_msg = simple_dialog_format_message(error_message); /* Did the user try a display filter? */ - if (dfilter_compile(interface_opts.cfilter, &rfcode) && rfcode != NULL) { + if (dfilter_compile(interface_opts.cfilter, &rfcode, NULL) && rfcode != NULL) { simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "%sInvalid capture filter \"%s\" for interface %s.%s\n" "\n" diff --git a/ui/gtk/capture_file_dlg.c b/ui/gtk/capture_file_dlg.c index 030a10b8c6..6d94cf796b 100644 --- a/ui/gtk/capture_file_dlg.c +++ b/ui/gtk/capture_file_dlg.c @@ -684,6 +684,7 @@ file_open_cmd(capture_file *cf, GtkWidget *w _U_) GString *file_name = g_string_new(""); GString *display_filter = g_string_new(""); dfilter_t *rfcode = NULL; + gchar *err_msg; int err; int type = WTAP_TYPE_AUTO; @@ -700,12 +701,13 @@ file_open_cmd(capture_file *cf, GtkWidget *w _U_) /* Only close the old file now that we know we want to open another one. */ cf_close(cf); /* apply our filter */ - if (dfilter_compile(display_filter->str, &rfcode)) { + if (dfilter_compile(display_filter->str, &rfcode, &err_msg)) { cf_set_rfcode(&cfile, rfcode); } else { /* Not valid. Tell the user, and go back and run the file selection box again once they dismiss the alert. */ - bad_dfilter_alert_box(top_level, display_filter->str); + bad_dfilter_alert_box(top_level, display_filter->str, err_msg); + g_free(err_msg); continue; } @@ -935,6 +937,7 @@ file_merge_cmd(GtkWidget *w _U_) GString *display_filter = g_string_new(""); int merge_type; dfilter_t *rfcode = NULL; + gchar *err_msg; int err; int file_type; cf_status_t merge_status; @@ -954,10 +957,11 @@ file_merge_cmd(GtkWidget *w _U_) #endif /* USE_WIN32_FILE_DIALOGS */ /* Get the specified read filter and try to compile it. */ - if (!dfilter_compile(display_filter->str, &rfcode)) { + if (!dfilter_compile(display_filter->str, &rfcode, &err_msg)) { /* Not valid. Tell the user, and go back and run the file selection box again once they dismiss the alert. */ - bad_dfilter_alert_box(top_level, display_filter->str); + bad_dfilter_alert_box(top_level, display_filter->str, err_msg); + g_free(err_msg); continue; } diff --git a/ui/gtk/color_edit_dlg.c b/ui/gtk/color_edit_dlg.c index d9c2354f60..33aa800c9c 100644 --- a/ui/gtk/color_edit_dlg.c +++ b/ui/gtk/color_edit_dlg.c @@ -369,6 +369,7 @@ color_edit_dlg_ok_cb(GtkWidget *w _U_, gpointer user_data) gboolean filter_disabled; color_filter_t *colorf; dfilter_t *compiled_filter; + gchar *err_msg; GtkTreeModel *model; GtkTreeIter iter; gchar fg_str[14], bg_str[14]; @@ -386,11 +387,12 @@ color_edit_dlg_ok_cb(GtkWidget *w _U_, gpointer user_data) return; } - if (!dfilter_compile(filter_text, &compiled_filter)) { + if (!dfilter_compile(filter_text, &compiled_filter, &err_msg)) { simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "Filter \"%s\" didn't compile correctly.\n" " Please try again. Filter unchanged.\n%s\n", filter_name, - dfilter_error_msg); + err_msg); + g_free(err_msg); g_free(filter_name); g_free(filter_text); return; diff --git a/ui/gtk/dfilter_expr_dlg.c b/ui/gtk/dfilter_expr_dlg.c index affc7f806c..4256090b3c 100644 --- a/ui/gtk/dfilter_expr_dlg.c +++ b/ui/gtk/dfilter_expr_dlg.c @@ -582,19 +582,6 @@ value_list_sel_cb(GtkTreeSelection *sel, gpointer value_entry_arg) g_free (value_display_string); } -static void -dfilter_report_bad_value(const char *format, ...) -{ - char error_msg_buf[1024]; - va_list args; - - va_start(args, format); - g_vsnprintf(error_msg_buf, sizeof error_msg_buf, format, args); - va_end(args); - - simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "%s", error_msg_buf); -} - static void dfilter_expr_dlg_accept_cb(GtkWidget *w, gpointer filter_te_arg) { @@ -615,6 +602,7 @@ dfilter_expr_dlg_accept_cb(GtkWidget *w, gpointer filter_te_arg) ftenum_t ftype; gboolean can_compare; fvalue_t *fvalue; + gchar *err_msg; GtkTreeModel *model; GtkTreeIter iter; gboolean quote_it; @@ -743,19 +731,18 @@ dfilter_expr_dlg_accept_cb(GtkWidget *w, gpointer filter_te_arg) */ if (strcmp(item_str, "contains") == 0) { fvalue = fvalue_from_unparsed(ftype, stripped_value_str, TRUE, - dfilter_report_bad_value); + &err_msg); } else { fvalue = fvalue_from_unparsed(ftype, stripped_value_str, FALSE, - dfilter_report_bad_value); + &err_msg); } if (fvalue == NULL) { /* * It's not valid. - * - * The dialog box was already popped up by - * "dfilter_report_bad_value()". */ + simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "%s", err_msg); + g_free(err_msg); g_free(range_str); g_free(value_str); g_free(item_str); diff --git a/ui/gtk/filter_dlg.c b/ui/gtk/filter_dlg.c index f5a68b579e..a12a7bfd9c 100644 --- a/ui/gtk/filter_dlg.c +++ b/ui/gtk/filter_dlg.c @@ -1345,7 +1345,7 @@ filter_te_syntax_check_cb(GtkWidget *w, gpointer user_data _U_) statusbar_pop_filter_msg(); } - if (strval && g_object_get_data(G_OBJECT(w), E_FILT_MULTI_FIELD_NAME_ONLY_KEY)) { + if (g_object_get_data(G_OBJECT(w), E_FILT_MULTI_FIELD_NAME_ONLY_KEY)) { gchar **fields; guint i_field = 0; @@ -1369,41 +1369,41 @@ filter_te_syntax_check_cb(GtkWidget *w, gpointer user_data _U_) /* colorize filter string entry */ if (g_object_get_data(G_OBJECT(w), E_FILT_FIELD_NAME_ONLY_KEY) && - strval && (c = proto_check_field_name(strval)) != 0) + (c = proto_check_field_name(strval)) != 0) { colorize_filter_te_as_invalid(w); if (use_statusbar) { statusbar_push_filter_msg(" Illegal character in field name: '%c'", c); } - } else if (strval && dfilter_compile(strval, &dfp)) { - if (dfp != NULL) { - depr = dfilter_deprecated_tokens(dfp); - } - if (strlen(strval) == 0) { - colorize_filter_te_as_empty(w); - } else if (depr) { - /* You keep using that word. I do not think it means what you think it means. */ - colorize_filter_te_as_deprecated(w); - if (use_statusbar) { - /* - * We're being lazy and only printing the first "problem" token. - * Would it be better to print all of them? - */ - statusbar_push_temporary_msg(" \"%s\" may have unexpected results (see the User's Guide)", - (const char *) g_ptr_array_index(depr, 0)); - } - } else { - colorize_filter_te_as_valid(w); - } - dfilter_free(dfp); } else { - colorize_filter_te_as_invalid(w); - if (use_statusbar) { - if (dfilter_error_msg) { - statusbar_push_filter_msg(" Invalid filter: %s", dfilter_error_msg); - } else { - statusbar_push_filter_msg(" Invalid filter"); + gchar *err_msg; + + if (dfilter_compile(strval, &dfp, &err_msg)) { + if (dfp != NULL) { + depr = dfilter_deprecated_tokens(dfp); } + if (strlen(strval) == 0) { + colorize_filter_te_as_empty(w); + } else if (depr) { + /* You keep using that word. I do not think it means what you think it means. */ + colorize_filter_te_as_deprecated(w); + if (use_statusbar) { + /* + * We're being lazy and only printing the first "problem" token. + * Would it be better to print all of them? + */ + statusbar_push_temporary_msg(" \"%s\" may have unexpected results (see the User's Guide)", + (const char *) g_ptr_array_index(depr, 0)); + } + } else { + colorize_filter_te_as_valid(w); + } + dfilter_free(dfp); + } else { + colorize_filter_te_as_invalid(w); + if (use_statusbar) + statusbar_push_filter_msg(" Invalid filter: %s", err_msg); + g_free(err_msg); } } } diff --git a/ui/gtk/find_dlg.c b/ui/gtk/find_dlg.c index faa9f48b83..7a128e552d 100644 --- a/ui/gtk/find_dlg.c +++ b/ui/gtk/find_dlg.c @@ -626,9 +626,12 @@ find_frame_ok_cb(GtkWidget *ok_bt _U_, gpointer parent_w) /* * Display filter search - try to compile the filter. */ - if (!dfilter_compile(filter_text, &sfcode)) { + gchar *err_msg; + + if (!dfilter_compile(filter_text, &sfcode, &err_msg)) { /* The attempt failed; report an error. */ - bad_dfilter_alert_box(GTK_WIDGET(parent_w), filter_text); + bad_dfilter_alert_box(GTK_WIDGET(parent_w), filter_text, err_msg); + g_free(err_msg); return; } @@ -752,7 +755,7 @@ find_previous_next(GtkWidget *w, gpointer d, search_direction dir) } g_free(string); } else { - if (!dfilter_compile(cfile.sfilter, &sfcode)) { + if (!dfilter_compile(cfile.sfilter, &sfcode, NULL)) { /* * XXX - this shouldn't happen, as we've already successfully * translated the string once. diff --git a/ui/gtk/funnel_stat.c b/ui/gtk/funnel_stat.c index 13bf97a3e6..c61de1bd1f 100644 --- a/ui/gtk/funnel_stat.c +++ b/ui/gtk/funnel_stat.c @@ -486,11 +486,11 @@ static void funnel_retap_packets(void) { cf_retap_packets(&cfile); } -static gboolean funnel_open_file(const char* fname, const char* filter, const char** err_str) { +static gboolean funnel_open_file(const char* fname, const char* filter, char** err_str) { int err = 0; dfilter_t *rfcode = NULL; - *err_str = "no error"; + *err_str = NULL; switch (cfile.state) { case FILE_CLOSED: @@ -498,20 +498,19 @@ static gboolean funnel_open_file(const char* fname, const char* filter, const ch case FILE_READ_ABORTED: break; case FILE_READ_IN_PROGRESS: - *err_str = "file read in progress"; + *err_str = g_strdup("file read in progress"); return FALSE; } if (filter) { - if (!dfilter_compile(filter, &rfcode)) { - *err_str = dfilter_error_msg ? dfilter_error_msg : "cannot compile filter"; + if (!dfilter_compile(filter, &rfcode, err_str)) { return FALSE; } } /* This closes the current file if it succeeds. */ if (cf_open(&cfile, fname, WTAP_TYPE_AUTO, FALSE, &err) != CF_OK) { - *err_str = g_strerror(err); + *err_str = g_strdup(g_strerror(err)); if (rfcode != NULL) dfilter_free(rfcode); return FALSE; } @@ -523,7 +522,7 @@ static gboolean funnel_open_file(const char* fname, const char* filter, const ch case CF_READ_ERROR: break; default: - *err_str = "problem while reading file"; + *err_str = g_strdup("problem while reading file"); return FALSE; } diff --git a/ui/gtk/gui_utils.c b/ui/gtk/gui_utils.c index 5643f3e1fd..b30cc87246 100644 --- a/ui/gtk/gui_utils.c +++ b/ui/gtk/gui_utils.c @@ -535,7 +535,8 @@ pixbuf_to_widget(const guint8 *pb_data) { */ void bad_dfilter_alert_box(GtkWidget *parent, - const char *dftext) + const char *dftext, + gchar *err_msg) { GtkWidget *msg_dialog; @@ -544,7 +545,7 @@ bad_dfilter_alert_box(GtkWidget *parent, GTK_MESSAGE_ERROR, GTK_BUTTONS_OK, "The filter expression \"%s\" isn't a valid display filter. (%s)", - dftext, dfilter_error_msg); + dftext, err_msg); gtk_message_dialog_format_secondary_text(GTK_MESSAGE_DIALOG(msg_dialog), "See the help for a description of the display filter syntax."); gtk_dialog_run(GTK_DIALOG(msg_dialog)); diff --git a/ui/gtk/gui_utils.h b/ui/gtk/gui_utils.h index 9277824ac8..468c862817 100644 --- a/ui/gtk/gui_utils.h +++ b/ui/gtk/gui_utils.h @@ -189,13 +189,12 @@ extern void reactivate_window(GtkWidget *win); /** @} */ /** Alert box for an invalid display filter expression. - * Assumes "dfilter_error_msg" has been set by "dfilter_compile()" to the - * error message for the filter. * * @param parent parent window from which the display filter came * @param dftext text of the display filter + * @param err_msg text of the error message for the filter */ -extern void bad_dfilter_alert_box(GtkWidget *parent, const char *dftext); +extern void bad_dfilter_alert_box(GtkWidget *parent, const char *dftext, gchar *err_msg); /** Create a GtkScrolledWindow, set its scrollbar placement appropriately, * and remember it. diff --git a/ui/gtk/iax2_analysis.c b/ui/gtk/iax2_analysis.c index 28efc2eb22..7c18c755d5 100644 --- a/ui/gtk/iax2_analysis.c +++ b/ui/gtk/iax2_analysis.c @@ -3703,6 +3703,7 @@ void iax2_analysis_cb(GtkAction *action _U_, gpointer user_data _U_) gchar filter_text[256]; dfilter_t *sfcode; + gchar *err_msg; capture_file *cf; frame_data *fdata; GList *strinfo_list; @@ -3713,8 +3714,9 @@ void iax2_analysis_cb(GtkAction *action _U_, gpointer user_data _U_) /* Try to compile the filter. */ g_strlcpy(filter_text,"iax2 && (ip || ipv6)",256); - if (!dfilter_compile(filter_text, &sfcode)) { - simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "%s", dfilter_error_msg); + if (!dfilter_compile(filter_text, &sfcode, &err_msg)) { + simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "%s", err_msg); + g_free(err_msg); return; } /* we load the current file into cf variable */ diff --git a/ui/gtk/io_stat.c b/ui/gtk/io_stat.c index 535211b8aa..d67d35bbd2 100644 --- a/ui/gtk/io_stat.c +++ b/ui/gtk/io_stat.c @@ -1784,6 +1784,7 @@ filter_callback(GtkWidget *widget, gpointer user_data) io_stat_graph_t *gio = (io_stat_graph_t *)user_data; const char *filter; dfilter_t *dfilter; + gchar *err_msg; const char *field_name = NULL; /* this graph is not active, just update display and redraw */ @@ -1813,9 +1814,10 @@ filter_callback(GtkWidget *widget, gpointer user_data) /* first check if the filter string is valid. */ filter = gtk_entry_get_text(GTK_ENTRY(gio->filter_field)); - if (!dfilter_compile(filter, &dfilter)) { + if (!dfilter_compile(filter, &dfilter, &err_msg)) { bad_dfilter_alert_box(gtk_widget_get_toplevel(widget), - filter); + filter, err_msg); + g_free(err_msg); disable_graph(gio); io_stat_redraw(gio->io); return; diff --git a/ui/gtk/main.c b/ui/gtk/main.c index f5b6028a98..224491a1f1 100644 --- a/ui/gtk/main.c +++ b/ui/gtk/main.c @@ -2163,6 +2163,7 @@ main(int argc, char *argv[]) gint pl_size = 280, tv_size = 95, bv_size = 75; gchar *rc_file, *cf_name = NULL, *rfilter = NULL, *dfilter = NULL, *jfilter = NULL; dfilter_t *rfcode = NULL; + gchar *err_msg; gboolean rfilter_parse_failed = FALSE; e_prefs *prefs_p; char badopt; @@ -3082,8 +3083,9 @@ main(int argc, char *argv[]) show_main_window(TRUE); check_and_warn_user_startup(cf_name); if (rfilter != NULL) { - if (!dfilter_compile(rfilter, &rfcode)) { - bad_dfilter_alert_box(top_level, rfilter); + if (!dfilter_compile(rfilter, &rfcode, &err_msg)) { + bad_dfilter_alert_box(top_level, rfilter, err_msg); + g_free(err_msg); rfilter_parse_failed = TRUE; } } @@ -3121,8 +3123,9 @@ main(int argc, char *argv[]) cf_goto_frame(&cfile, go_to_packet); } else if (jfilter != NULL) { /* try to compile given filter */ - if (!dfilter_compile(jfilter, &jump_to_filter)) { - bad_dfilter_alert_box(top_level, jfilter); + if (!dfilter_compile(jfilter, &jump_to_filter, &err_msg)) { + bad_dfilter_alert_box(top_level, jfilter, err_msg); + g_free(err_msg); } else { /* Filter ok, jump to the first packet matching the filter conditions. Default search direction is forward, but if @@ -3859,7 +3862,7 @@ main_fields_changed (void) if (cfile.dfilter) { /* Check if filter is still valid */ dfilter_t *dfp = NULL; - if (!dfilter_compile(cfile.dfilter, &dfp)) { + if (!dfilter_compile(cfile.dfilter, &dfp, NULL)) { /* Not valid. Enable 'Apply' button and remove dfilter. */ g_signal_emit_by_name(G_OBJECT(main_display_filter_widget), "changed"); g_free(cfile.dfilter); diff --git a/ui/gtk/main_menubar.c b/ui/gtk/main_menubar.c index fe1d0a3563..a925b4ac75 100644 --- a/ui/gtk/main_menubar.c +++ b/ui/gtk/main_menubar.c @@ -271,7 +271,7 @@ goto_conversation_frame(gboolean dir) return; } - if (!dfilter_compile(filter, &dfcode)) { + if (!dfilter_compile(filter, &dfcode, NULL)) { /* The attempt failed; report an error. */ statusbar_push_temporary_msg("Error compiling filter for this conversation."); g_free(filter); diff --git a/ui/gtk/rlc_lte_graph.c b/ui/gtk/rlc_lte_graph.c index 05ad9e03a0..3b0323dcab 100644 --- a/ui/gtk/rlc_lte_graph.c +++ b/ui/gtk/rlc_lte_graph.c @@ -892,6 +892,7 @@ static rlc_lte_tap_info *select_rlc_lte_session(capture_file *cf, struct segment frame_data *fdata; epan_dissect_t edt; dfilter_t *sfcode; + gchar *err_msg; GString *error_string; nstime_t rel_ts; th_t th = {0, {NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL}}; @@ -903,8 +904,9 @@ static rlc_lte_tap_info *select_rlc_lte_session(capture_file *cf, struct segment fdata = cf->current_frame; /* no real filter yet */ - if (!dfilter_compile("rlc-lte", &sfcode)) { - simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "%s", dfilter_error_msg); + if (!dfilter_compile("rlc-lte", &sfcode, &err_msg)) { + simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "%s", err_msg); + g_free(err_msg); return NULL; } diff --git a/ui/gtk/rtp_analysis.c b/ui/gtk/rtp_analysis.c index c2446a6649..6feac4a2e0 100644 --- a/ui/gtk/rtp_analysis.c +++ b/ui/gtk/rtp_analysis.c @@ -3933,6 +3933,7 @@ rtp_analysis_cb(GtkAction *action _U_, gpointer user_data _U_) gchar filter_text[256]; dfilter_t *sfcode; + gchar *err_msg; capture_file *cf; frame_data *fdata; GList *strinfo_list; @@ -3943,8 +3944,9 @@ rtp_analysis_cb(GtkAction *action _U_, gpointer user_data _U_) /* Try to compile the filter. */ g_strlcpy(filter_text, "rtp && rtp.version && rtp.ssrc && (ip || ipv6)", sizeof(filter_text)); - if (!dfilter_compile(filter_text, &sfcode)) { - simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "%s", dfilter_error_msg); + if (!dfilter_compile(filter_text, &sfcode, &err_msg)) { + simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "%s", err_msg); + g_free(err_msg); return; } /* we load the current file into cf variable */ diff --git a/ui/gtk/sctp_assoc_analyse.c b/ui/gtk/sctp_assoc_analyse.c index 9b47435c5c..ad914efda3 100644 --- a/ui/gtk/sctp_assoc_analyse.c +++ b/ui/gtk/sctp_assoc_analyse.c @@ -973,6 +973,7 @@ sctp_analyse_cb(struct sctp_analyse *u_data, gboolean ext) { GList *list; dfilter_t *sfcode; + gchar *err_msg; capture_file *cf; epan_dissect_t edt; gboolean frame_found = FALSE; @@ -980,8 +981,9 @@ sctp_analyse_cb(struct sctp_analyse *u_data, gboolean ext) gchar filter_text[256]; g_strlcpy(filter_text, "sctp", 250); - if (!dfilter_compile(filter_text, &sfcode)) { - simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "%s", dfilter_error_msg); + if (!dfilter_compile(filter_text, &sfcode, &err_msg)) { + simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "%s", err_msg); + g_free(err_msg); return; } diff --git a/ui/qt/display_filter_edit.cpp b/ui/qt/display_filter_edit.cpp index 7d80f76697..f6d92a1217 100644 --- a/ui/qt/display_filter_edit.cpp +++ b/ui/qt/display_filter_edit.cpp @@ -283,10 +283,8 @@ void DisplayFilterEdit::checkFilter(const QString& text) } case Invalid: { - QString invalidMsg(tr("Invalid filter")); - if (dfilter_error_msg) { - invalidMsg.append(QString().sprintf(": %s", dfilter_error_msg)); - } + QString invalidMsg(tr("Invalid filter: ")); + invalidMsg.append(syntaxErrorMessage()); emit pushFilterSyntaxStatus(invalidMsg); break; } diff --git a/ui/qt/io_graph_dialog.cpp b/ui/qt/io_graph_dialog.cpp index 5e49bfb493..be4dc2ab18 100644 --- a/ui/qt/io_graph_dialog.cpp +++ b/ui/qt/io_graph_dialog.cpp @@ -1555,10 +1555,12 @@ void IOGraph::setFilter(const QString &filter) if (!full_filter.isEmpty()) { dfilter_t *dfilter; bool status; - status = dfilter_compile(full_filter.toUtf8().constData(), &dfilter); + gchar *err_msg; + status = dfilter_compile(full_filter.toUtf8().constData(), &dfilter, &err_msg); dfilter_free(dfilter); if (!status) { - config_err_ = dfilter_error_msg; + config_err_ = QString::fromUtf8(err_msg); + g_free(err_msg); filter_ = full_filter; return; } diff --git a/ui/qt/main_window.cpp b/ui/qt/main_window.cpp index 48b418442f..3a5afcc2ba 100644 --- a/ui/qt/main_window.cpp +++ b/ui/qt/main_window.cpp @@ -714,15 +714,18 @@ void MainWindow::mergeCaptureFile() } if (merge_dlg.merge(file_name)) { - if (dfilter_compile(display_filter.toUtf8().constData(), &rfcode)) { + gchar *err_msg; + + if (dfilter_compile(display_filter.toUtf8().constData(), &rfcode, &err_msg)) { cf_set_rfcode(capture_file_.capFile(), rfcode); } else { /* Not valid. Tell the user, and go back and run the file selection box again once they dismiss the alert. */ //bad_dfilter_alert_box(top_level, display_filter->str); QMessageBox::warning(this, tr("Invalid Display Filter"), - QString(tr("The filter expression %1 isn't a valid display filter. (%2).").arg(display_filter, dfilter_error_msg)), + QString(tr("The filter expression %1 isn't a valid display filter. (%2).").arg(display_filter, err_msg)), QMessageBox::Ok); + g_free(err_msg); continue; } } else { diff --git a/ui/qt/main_window_slots.cpp b/ui/qt/main_window_slots.cpp index 50aef1b079..d53e9545bd 100644 --- a/ui/qt/main_window_slots.cpp +++ b/ui/qt/main_window_slots.cpp @@ -115,6 +115,7 @@ void MainWindow::openCaptureFile(QString& cf_path, QString& read_filter, unsigne { QString file_name = ""; dfilter_t *rfcode = NULL; + gchar *err_msg; int err; gboolean name_param; @@ -155,7 +156,7 @@ void MainWindow::openCaptureFile(QString& cf_path, QString& read_filter, unsigne } } - if (dfilter_compile(read_filter.toUtf8().constData(), &rfcode)) { + if (dfilter_compile(read_filter.toUtf8().constData(), &rfcode, &err_msg)) { cf_set_rfcode(CaptureFile::globalCapFile(), rfcode); } else { /* Not valid. Tell the user, and go back and run the file @@ -165,7 +166,7 @@ void MainWindow::openCaptureFile(QString& cf_path, QString& read_filter, unsigne QString("The filter expression ") + read_filter + QString(" isn't a valid display filter. (") + - dfilter_error_msg + QString(")."), + err_msg + QString(")."), QMessageBox::Ok); if (!name_param) { @@ -1259,8 +1260,9 @@ void MainWindow::fieldsChanged() if (CaptureFile::globalCapFile()->dfilter) { // Check if filter is still valid dfilter_t *dfp = NULL; - if (!dfilter_compile(CaptureFile::globalCapFile()->dfilter, &dfp)) { + if (!dfilter_compile(CaptureFile::globalCapFile()->dfilter, &dfp, NULL)) { // TODO: Not valid, enable "Apply" button. + // TODO: get an error message and display it? g_free(CaptureFile::globalCapFile()->dfilter); CaptureFile::globalCapFile()->dfilter = NULL; } diff --git a/ui/qt/search_frame.cpp b/ui/qt/search_frame.cpp index 68f22d76f9..e07c6221c4 100644 --- a/ui/qt/search_frame.cpp +++ b/ui/qt/search_frame.cpp @@ -212,7 +212,7 @@ void SearchFrame::on_findButton_clicked() switch (sf_ui_->searchTypeComboBox->currentIndex()) { case df_search: - if (!dfilter_compile(sf_ui_->searchLineEdit->text().toUtf8().constData(), &dfp)) { + if (!dfilter_compile(sf_ui_->searchLineEdit->text().toUtf8().constData(), &dfp, NULL)) { err_string = tr("Invalid filter."); emit pushFilterSyntaxStatus(err_string); return; diff --git a/ui/qt/syntax_line_edit.cpp b/ui/qt/syntax_line_edit.cpp index f1edfdbca6..483bdcb7ce 100644 --- a/ui/qt/syntax_line_edit.cpp +++ b/ui/qt/syntax_line_edit.cpp @@ -66,6 +66,10 @@ void SyntaxLineEdit::setSyntaxState(SyntaxState state) { setStyleSheet(style_sheet_); } +QString SyntaxLineEdit::syntaxErrorMessage() { + return syntax_error_message_; +} + QString SyntaxLineEdit::styleSheet() const { return style_sheet_; } @@ -89,21 +93,23 @@ void SyntaxLineEdit::checkDisplayFilter(QString filter) deprecated_token_.clear(); dfilter_t *dfp = NULL; - bool valid = dfilter_compile(filter.toUtf8().constData(), &dfp); - - if (valid) { - setSyntaxState(SyntaxLineEdit::Valid); - } else { + gchar *err_msg; + if (dfilter_compile(filter.toUtf8().constData(), &dfp, &err_msg)) { GPtrArray *depr = NULL; if (dfp) { depr = dfilter_deprecated_tokens(dfp); } if (depr) { + // You keep using that word. I do not think it means what you think it means. setSyntaxState(SyntaxLineEdit::Deprecated); deprecated_token_ = (const char *) g_ptr_array_index(depr, 0); } else { - setSyntaxState(SyntaxLineEdit::Invalid); + setSyntaxState(SyntaxLineEdit::Valid); } + } else { + setSyntaxState(SyntaxLineEdit::Invalid); + syntax_error_message_ = QString::fromUtf8(err_msg); + g_free(err_msg); } dfilter_free(dfp); } diff --git a/ui/qt/syntax_line_edit.h b/ui/qt/syntax_line_edit.h index f6872c31f8..77edf92e84 100644 --- a/ui/qt/syntax_line_edit.h +++ b/ui/qt/syntax_line_edit.h @@ -35,6 +35,7 @@ public: SyntaxState syntaxState() const { return syntax_state_; } void setSyntaxState(SyntaxState state = Empty); + QString syntaxErrorMessage(); QString styleSheet() const; QString deprecatedToken(); @@ -51,6 +52,7 @@ private: QString style_sheet_; QString state_style_sheet_; QString deprecated_token_; + QString syntax_error_message_; signals: diff --git a/ui/tap-tcp-stream.c b/ui/tap-tcp-stream.c index 370cdfd76d..c9b952b184 100644 --- a/ui/tap-tcp-stream.c +++ b/ui/tap-tcp-stream.c @@ -287,6 +287,7 @@ select_tcpip_session(capture_file *cf, struct segment *hdrs) frame_data *fdata; epan_dissect_t edt; dfilter_t *sfcode; + gchar *err_msg; GString *error_string; nstime_t rel_ts; th_t th = {0, {NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL}}; @@ -297,8 +298,9 @@ select_tcpip_session(capture_file *cf, struct segment *hdrs) fdata = cf->current_frame; /* no real filter yet */ - if (!dfilter_compile("tcp", &sfcode)) { - simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "%s", dfilter_error_msg); + if (!dfilter_compile("tcp", &sfcode, &err_msg)) { + simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "%s", err_msg); + g_free(err_msg); return NULL; }