dfilter: Return an error object instead of string

Return an struct containing error information. This simplifies
the interface to more easily provide richer diagnostics in the future.

Add an error code besides a human-readable error string to allow
checking programmatically for errors in a robust manner. Currently
there is only a generic error code, it is expected to increase
in the future.

Move error location information to the struct. Change callers and
implementation to use the new interface.
This commit is contained in:
João Valverde 2022-11-19 19:21:19 +00:00
parent b4196ab772
commit a0d77e9329
30 changed files with 290 additions and 215 deletions

View File

@ -75,7 +75,7 @@ main(int argc, char **argv)
char *expanded_text; char *expanded_text;
dfilter_t *df; dfilter_t *df;
gchar *err_msg; gchar *err_msg;
dfilter_loc_t err_loc; df_error_t *df_err;
cmdarg_err_init(dftest_cmdarg_err, dftest_cmdarg_err_cont); cmdarg_err_init(dftest_cmdarg_err, dftest_cmdarg_err_cont);
@ -164,15 +164,15 @@ main(int argc, char **argv)
printf("Filter: %s\n", expanded_text); printf("Filter: %s\n", expanded_text);
/* Compile it */ /* Compile it */
if (!dfilter_compile_real(expanded_text, &df, &err_msg, &err_loc, if (!dfilter_compile_real(expanded_text, &df, &df_err,
"dftest", TRUE, FALSE)) { "dftest", TRUE, FALSE)) {
fprintf(stderr, "dftest: %s\n", err_msg); fprintf(stderr, "dftest: %s\n", df_err->msg);
if (err_loc.col_start >= 0) { if (df_err->loc.col_start >= 0) {
fprintf(stderr, "\t%s\n", expanded_text); fprintf(stderr, "\t%s\n", expanded_text);
fputc('\t', stderr); fputc('\t', stderr);
putloc(stderr, err_loc); putloc(stderr, df_err->loc);
} }
g_free(err_msg); dfilter_error_free(df_err);
g_free(expanded_text); g_free(expanded_text);
epan_cleanup(); epan_cleanup();
exit(2); exit(2);

View File

@ -156,7 +156,7 @@ color_filters_set_tmp(guint8 filt_nr, const gchar *filter, gboolean disabled, gc
color_filter_t *colorf; color_filter_t *colorf;
dfilter_t *compiled_filter; dfilter_t *compiled_filter;
guint8 i; guint8 i;
gchar *local_err_msg = NULL; df_error_t *df_err = NULL;
/* Go through the temporary filters and look for the same filter string. /* Go through the temporary filters and look for the same filter string.
* If found, clear it so that a filter can be "moved" up and down the list * If found, clear it so that a filter can be "moved" up and down the list
*/ */
@ -179,9 +179,9 @@ color_filters_set_tmp(guint8 filt_nr, const gchar *filter, gboolean disabled, gc
* or if we found a matching filter string which need to be cleared * or if we found a matching filter string which need to be cleared
*/ */
tmpfilter = ( (filter==NULL) || (i!=filt_nr) ) ? "frame" : filter; tmpfilter = ( (filter==NULL) || (i!=filt_nr) ) ? "frame" : filter;
if (!dfilter_compile(tmpfilter, &compiled_filter, &local_err_msg)) { if (!dfilter_compile(tmpfilter, &compiled_filter, &df_err)) {
*err_msg = ws_strdup_printf( "Could not compile color filter name: \"%s\" text: \"%s\".\n%s", name, filter, local_err_msg); *err_msg = ws_strdup_printf( "Could not compile color filter name: \"%s\" text: \"%s\".\n%s", name, filter, df_err->msg);
g_free(local_err_msg); dfilter_error_free(df_err);
g_free(name); g_free(name);
return FALSE; return FALSE;
} else { } else {
@ -405,17 +405,17 @@ color_filter_compile_cb(gpointer filter_arg, gpointer err)
{ {
color_filter_t *colorf = (color_filter_t *)filter_arg; color_filter_t *colorf = (color_filter_t *)filter_arg;
gchar **err_msg = (gchar**)err; gchar **err_msg = (gchar**)err;
gchar *local_err_msg = NULL; df_error_t *df_err = NULL;
ws_assert(colorf->c_colorfilter == NULL); ws_assert(colorf->c_colorfilter == NULL);
/* If the filter is disabled it doesn't matter if it compiles or not. */ /* If the filter is disabled it doesn't matter if it compiles or not. */
if (colorf->disabled) return; if (colorf->disabled) return;
if (!dfilter_compile(colorf->filter_text, &colorf->c_colorfilter, &local_err_msg)) { if (!dfilter_compile(colorf->filter_text, &colorf->c_colorfilter, &df_err)) {
*err_msg = ws_strdup_printf("Could not compile color filter name: \"%s\" text: \"%s\".\n%s", *err_msg = ws_strdup_printf("Could not compile color filter name: \"%s\" text: \"%s\".\n%s",
colorf->filter_name, colorf->filter_text, local_err_msg); colorf->filter_name, colorf->filter_text, df_err->msg);
g_free(local_err_msg); dfilter_error_free(df_err);
/* this filter was compilable before, so this should never happen */ /* this filter was compilable before, so this should never happen */
/* except if the OK button of the parent window has been clicked */ /* except if the OK button of the parent window has been clicked */
/* so don't use ws_assert_not_reached() but check the filters again */ /* so don't use ws_assert_not_reached() but check the filters again */
@ -427,17 +427,17 @@ color_filter_validate_cb(gpointer filter_arg, gpointer err)
{ {
color_filter_t *colorf = (color_filter_t *)filter_arg; color_filter_t *colorf = (color_filter_t *)filter_arg;
gchar **err_msg = (gchar**)err; gchar **err_msg = (gchar**)err;
gchar *local_err_msg; df_error_t *df_err = NULL;
ws_assert(colorf->c_colorfilter == NULL); ws_assert(colorf->c_colorfilter == NULL);
/* If the filter is disabled it doesn't matter if it compiles or not. */ /* If the filter is disabled it doesn't matter if it compiles or not. */
if (colorf->disabled) return; if (colorf->disabled) return;
if (!dfilter_compile(colorf->filter_text, &colorf->c_colorfilter, &local_err_msg)) { if (!dfilter_compile(colorf->filter_text, &colorf->c_colorfilter, &df_err)) {
*err_msg = ws_strdup_printf("Disabling color filter name: \"%s\" filter: \"%s\".\n%s", *err_msg = ws_strdup_printf("Disabling color filter name: \"%s\" filter: \"%s\".\n%s",
colorf->filter_name, colorf->filter_text, local_err_msg); colorf->filter_name, colorf->filter_text, df_err->msg);
g_free(local_err_msg); dfilter_error_free(df_err);
/* Disable the color filter in the list of color filters. */ /* Disable the color filter in the list of color filters. */
colorf->disabled = TRUE; colorf->disabled = TRUE;
@ -651,12 +651,12 @@ read_filters_file(const gchar *path, FILE *f, gpointer user_data, color_filter_a
color_t bg_color, fg_color; color_t bg_color, fg_color;
color_filter_t *colorf; color_filter_t *colorf;
dfilter_t *temp_dfilter = NULL; dfilter_t *temp_dfilter = NULL;
gchar *local_err_msg = NULL; df_error_t *df_err = NULL;
if (!disabled && !dfilter_compile(filter_exp, &temp_dfilter, &local_err_msg)) { if (!disabled && !dfilter_compile(filter_exp, &temp_dfilter, &df_err)) {
ws_warning("Could not compile \"%s\" in colorfilters file \"%s\".\n%s", ws_warning("Could not compile \"%s\" in colorfilters file \"%s\".\n%s",
name, path, local_err_msg); name, path, df_err->msg);
g_free(local_err_msg); dfilter_error_free(df_err);
prefs.unknown_colorfilters = TRUE; prefs.unknown_colorfilters = TRUE;
/* skip_end_of_line = TRUE; */ /* skip_end_of_line = TRUE; */

View File

@ -43,8 +43,8 @@ struct epan_dfilter {
typedef struct { typedef struct {
/* Syntax Tree stuff */ /* Syntax Tree stuff */
stnode_t *st_root; stnode_t *st_root;
gboolean syntax_error; gboolean parse_failure;
gchar *error_message; df_error_t error;
GPtrArray *insns; GPtrArray *insns;
GHashTable *loaded_fields; GHashTable *loaded_fields;
GHashTable *loaded_raw_fields; GHashTable *loaded_raw_fields;
@ -55,7 +55,6 @@ typedef struct {
GHashTable *references; /* hfinfo -> pointer to array of references */ GHashTable *references; /* hfinfo -> pointer to array of references */
GHashTable *raw_references; /* hfinfo -> pointer to array of references */ GHashTable *raw_references; /* hfinfo -> pointer to array of references */
char *expanded_text; char *expanded_text;
stloc_t err_loc;
} dfwork_t; } dfwork_t;
/* /*
@ -80,17 +79,17 @@ void Dfilter(void*, int, stnode_t*, dfwork_t*);
#define SCAN_FAILED -1 /* not 0, as that means end-of-input */ #define SCAN_FAILED -1 /* not 0, as that means end-of-input */
void void
dfilter_vfail(dfwork_t *dfw, stloc_t *err_loc, dfilter_vfail(dfwork_t *dfw, int code, stloc_t *err_loc,
const char *format, va_list args); const char *format, va_list args);
void void
dfilter_fail(dfwork_t *dfw, stloc_t *err_loc, dfilter_fail(dfwork_t *dfw, int code, stloc_t *err_loc,
const char *format, ...) G_GNUC_PRINTF(3, 4); const char *format, ...) G_GNUC_PRINTF(4, 5);
WS_NORETURN WS_NORETURN
void void
dfilter_fail_throw(dfwork_t *dfw, stloc_t *err_loc, dfilter_fail_throw(dfwork_t *dfw, int code, stloc_t *err_loc,
const char *format, ...) G_GNUC_PRINTF(3, 4); const char *format, ...) G_GNUC_PRINTF(4, 5);
void void
dfw_set_error_location(dfwork_t *dfw, stloc_t *err_loc); dfw_set_error_location(dfwork_t *dfw, stloc_t *err_loc);
@ -126,4 +125,13 @@ reference_new(const field_info *finfo, gboolean raw);
void void
reference_free(df_reference_t *ref); reference_free(df_reference_t *ref);
void dfw_error_init(df_error_t *err);
void dfw_error_clear(df_error_t *err);
void dfw_error_set_msg(df_error_t **errp, const char *fmt, ...)
G_GNUC_PRINTF(2, 3);
void dfw_error_take(df_error_t **errp, df_error_t *src);
#endif #endif

View File

@ -42,46 +42,44 @@ static void* ParserObj = NULL;
dfwork_t *global_dfw; dfwork_t *global_dfw;
void void
dfilter_vfail(dfwork_t *dfw, stloc_t *loc, dfilter_vfail(dfwork_t *dfw, int code, stloc_t *loc,
const char *format, va_list args) const char *format, va_list args)
{ {
/* Flag a syntax error. This is currently only used in dfw->parse_failure = TRUE;
* the grammar parsing stage to terminate the parsing
* loop. */
dfw->syntax_error = TRUE;
/* If we've already reported one error, don't overwite it */ /* If we've already reported one error, don't overwite it */
if (dfw->error_message != NULL) if (dfw->error.code < 0 || dfw->error.msg != NULL)
return; return;
dfw->error_message = ws_strdup_vprintf(format, args); dfw->error.code = code;
dfw->error.msg = ws_strdup_vprintf(format, args);
if (loc) { if (loc) {
dfw->err_loc = *loc; dfw->error.loc = *(dfilter_loc_t *)loc;
} }
else { else {
dfw->err_loc.col_start = -1; dfw->error.loc.col_start = -1;
dfw->err_loc.col_len = 0; dfw->error.loc.col_len = 0;
} }
} }
void void
dfilter_fail(dfwork_t *dfw, stloc_t *loc, dfilter_fail(dfwork_t *dfw, int code, stloc_t *loc,
const char *format, ...) const char *format, ...)
{ {
va_list args; va_list args;
va_start(args, format); va_start(args, format);
dfilter_vfail(dfw, loc, format, args); dfilter_vfail(dfw, code, loc, format, args);
va_end(args); va_end(args);
} }
void void
dfilter_fail_throw(dfwork_t *dfw, stloc_t *loc, const char *format, ...) dfilter_fail_throw(dfwork_t *dfw, int code, stloc_t *loc, const char *format, ...)
{ {
va_list args; va_list args;
va_start(args, format); va_start(args, format);
dfilter_vfail(dfw, loc, format, args); dfilter_vfail(dfw, code, loc, format, args);
va_end(args); va_end(args);
THROW(TypeError); THROW(TypeError);
} }
@ -91,7 +89,7 @@ dfw_set_error_location(dfwork_t *dfw, stloc_t *loc)
{ {
/* Set new location. */ /* Set new location. */
ws_assert(loc); ws_assert(loc);
dfw->err_loc = *loc; dfw->error.loc = *(dfilter_loc_t *)loc;
} }
header_field_info * header_field_info *
@ -232,6 +230,8 @@ dfwork_new(void)
{ {
dfwork_t *dfw = g_new0(dfwork_t, 1); dfwork_t *dfw = g_new0(dfwork_t, 1);
dfw_error_init(&dfw->error);
dfw->references = dfw->references =
g_hash_table_new_full(g_direct_hash, g_direct_equal, g_hash_table_new_full(g_direct_hash, g_direct_equal,
NULL, (GDestroyNotify)free_refs_array); NULL, (GDestroyNotify)free_refs_array);
@ -355,7 +355,7 @@ dfilter_expand(const char *expr, char **err_ret)
gboolean gboolean
dfilter_compile_real(const gchar *text, dfilter_t **dfp, dfilter_compile_real(const gchar *text, dfilter_t **dfp,
gchar **error_ret, dfilter_loc_t *loc_ptr, df_error_t **errpp,
const char *caller, gboolean save_tree, const char *caller, gboolean save_tree,
gboolean apply_macros) gboolean apply_macros)
{ {
@ -376,10 +376,8 @@ dfilter_compile_real(const gchar *text, dfilter_t **dfp,
ws_log(WS_LOG_DOMAIN, LOG_LEVEL_DEBUG, ws_log(WS_LOG_DOMAIN, LOG_LEVEL_DEBUG,
"%s() called from %s() with null filter", "%s() called from %s() with null filter",
__func__, caller); __func__, caller);
if (error_ret != NULL) { /* XXX This BUG happens often. Some callers are ignoring these errors. */
/* XXX This BUG happens often. Some callers are ignoring these errors. */ dfw_error_set_msg(errpp, "BUG: NULL text pointer passed to dfilter_compile");
*error_ret = g_strdup("BUG: NULL text pointer passed to dfilter_compile");
}
return FALSE; return FALSE;
} }
else if (*text == '\0') { else if (*text == '\0') {
@ -397,7 +395,7 @@ dfilter_compile_real(const gchar *text, dfilter_t **dfp,
dfw = dfwork_new(); dfw = dfwork_new();
if (apply_macros) { if (apply_macros) {
dfw->expanded_text = dfilter_macro_apply(text, &dfw->error_message); dfw->expanded_text = dfilter_macro_apply(text, &dfw->error.msg);
if (dfw->expanded_text == NULL) { if (dfw->expanded_text == NULL) {
goto FAILURE; goto FAILURE;
} }
@ -409,7 +407,7 @@ dfilter_compile_real(const gchar *text, dfilter_t **dfp,
} }
if (df_lex_init(&scanner) != 0) { if (df_lex_init(&scanner) != 0) {
dfw->error_message = ws_strdup_printf("Can't initialize scanner: %s", g_strerror(errno)); dfw_error_set_msg(errpp, "Can't initialize scanner: %s", g_strerror(errno));
goto FAILURE; goto FAILURE;
} }
@ -444,7 +442,7 @@ dfilter_compile_real(const gchar *text, dfilter_t **dfp,
/* The parser has freed the lval for us. */ /* The parser has freed the lval for us. */
df_lval = NULL; df_lval = NULL;
if (dfw->syntax_error) { if (dfw->parse_failure) {
failure = TRUE; failure = TRUE;
break; break;
} }
@ -467,7 +465,7 @@ dfilter_compile_real(const gchar *text, dfilter_t **dfp,
Dfilter(ParserObj, 0, NULL, dfw); Dfilter(ParserObj, 0, NULL, dfw);
/* One last check for syntax error (after EOF) */ /* One last check for syntax error (after EOF) */
if (dfw->syntax_error) if (dfw->parse_failure)
failure = TRUE; failure = TRUE;
/* Free scanner state */ /* Free scanner state */
@ -547,22 +545,13 @@ dfilter_compile_real(const gchar *text, dfilter_t **dfp,
FAILURE: FAILURE:
ws_assert(dfw); ws_assert(dfw);
if (dfw->error_message == NULL) { if (dfw->error.msg == NULL) {
/* We require an error message. */ /* We require an error message. */
ws_critical("Unknown error compiling filter: %s", text); ws_critical("Unknown error compiling filter: %s", text);
} }
else { else {
ws_debug("Compiling filter failed with error: %s.", dfw->error_message); ws_debug("Compiling filter failed with error: %s.", dfw->error.msg);
if (error_ret != NULL) { dfw_error_take(errpp, &dfw->error);
*error_ret = dfw->error_message;
}
else {
g_free(dfw->error_message);
}
if (loc_ptr != NULL) {
loc_ptr->col_start = dfw->err_loc.col_start;
loc_ptr->col_len = dfw->err_loc.col_len;
}
} }
global_dfw = NULL; global_dfw = NULL;
@ -738,6 +727,63 @@ reference_free(df_reference_t *ref)
g_free(ref); g_free(ref);
} }
void
dfw_error_init(df_error_t *err) {
err->code = 0;
err->msg = NULL;
err->loc.col_start = -1;
err->loc.col_len = 0;
}
void
dfw_error_clear(df_error_t *err) {
g_free(err->msg);
dfw_error_init(err);
}
void
dfw_error_set_msg(df_error_t **errpp, const char *fmt, ...)
{
if (errpp == NULL) {
return;
}
va_list ap;
df_error_t *errp = g_new(df_error_t, 1);
errp->code = DF_ERROR_GENERIC;
va_start(ap, fmt);
errp->msg = ws_strdup_vprintf(fmt, ap);
va_end(ap);
errp->loc.col_start = -1;
errp->loc.col_len = 0;
*errpp = errp;
}
void
dfw_error_take(df_error_t **errpp, df_error_t *src)
{
if (errpp == NULL) {
g_free(src->msg);
dfw_error_init(src);
return;
}
df_error_t *errp = g_new(df_error_t, 1);
errp->code = src->code;
errp->msg = src->msg;
errp->loc = src->loc;
*errpp = errp;
dfw_error_init(src);
}
void
dfilter_error_free(df_error_t *errp)
{
if (errp == NULL)
return;
g_free(errp->msg);
g_free(errp);
}
/* /*
* Editor modelines - https://www.wireshark.org/tools/modelines.html * Editor modelines - https://www.wireshark.org/tools/modelines.html
* *

View File

@ -52,23 +52,32 @@ dfilter_expand(const char *expr, char **err_ret);
* Returns TRUE on success, FALSE on failure. * Returns TRUE on success, FALSE on failure.
*/ */
#define DF_ERROR_GENERIC -1
typedef struct _dfilter_loc { typedef struct _dfilter_loc {
long col_start; long col_start;
size_t col_len; size_t col_len;
} dfilter_loc_t; } dfilter_loc_t;
typedef struct {
int code;
char *msg;
dfilter_loc_t loc;
} df_error_t;
WS_DLL_PUBLIC
void
dfilter_error_free(df_error_t *);
WS_DLL_PUBLIC WS_DLL_PUBLIC
gboolean gboolean
dfilter_compile_real(const gchar *text, dfilter_t **dfp, dfilter_compile_real(const gchar *text, dfilter_t **dfp,
gchar **err_msg, dfilter_loc_t *loc_ptr, df_error_t **errpp,
const char *caller, gboolean save_tree, const char *caller, gboolean save_tree,
gboolean apply_macros); gboolean apply_macros);
#define dfilter_compile(text, dfp, err_msg) \ #define dfilter_compile(text, dfp, errp) \
dfilter_compile_real(text, dfp, err_msg, NULL, __func__, FALSE, TRUE) dfilter_compile_real(text, dfp, errp, __func__, FALSE, TRUE)
#define dfilter_compile2(text, dfp, err_msg, loc_ptr) \
dfilter_compile_real(text, dfp, err_msg, loc_ptr, __func__, FALSE, TRUE)
/* Frees all memory used by dfilter, and frees /* Frees all memory used by dfilter, and frees
* the dfilter itself. */ * the dfilter itself. */

View File

@ -22,7 +22,7 @@
#include <wsutil/ws_assert.h> #include <wsutil/ws_assert.h>
#define FAIL(dfw, node, ...) \ #define FAIL(dfw, node, ...) \
dfilter_fail_throw(dfw, stnode_location(node), __VA_ARGS__) dfilter_fail_throw(dfw, DF_ERROR_GENERIC, stnode_location(node), __VA_ARGS__)
/* Convert an FT_STRING using a callback function */ /* Convert an FT_STRING using a callback function */
static gboolean static gboolean

View File

@ -22,7 +22,7 @@
static stnode_t * static stnode_t *
new_function(dfwork_t *dfw, stnode_t *node); new_function(dfwork_t *dfw, stnode_t *node);
#define FAIL(dfw, node, ...) dfilter_fail(dfw, stnode_location(node), __VA_ARGS__) #define FAIL(dfw, node, ...) dfilter_fail(dfw, DF_ERROR_GENERIC, stnode_location(node), __VA_ARGS__)
DIAG_OFF_LEMON() DIAG_OFF_LEMON()
} /* end of %include */ } /* end of %include */
@ -65,7 +65,7 @@ DIAG_ON_LEMON()
any "error" symbols are shifted, if possible. */ any "error" symbols are shifted, if possible. */
%syntax_error { %syntax_error {
if (!TOKEN) { if (!TOKEN) {
dfilter_fail(dfw, NULL, "Unexpected end of filter expression."); dfilter_fail(dfw, DF_ERROR_GENERIC, NULL, "Unexpected end of filter expression.");
return; return;
} }
FAIL(dfw, TOKEN, "\"%s\" was unexpected in this context.", stnode_token(TOKEN)); FAIL(dfw, TOKEN, "\"%s\" was unexpected in this context.", stnode_token(TOKEN));
@ -76,7 +76,7 @@ the above syntax_error code and after the parser fails to
use error recovery, shifting an "error" symbol and successfully use error recovery, shifting an "error" symbol and successfully
shifting 3 more symbols. */ shifting 3 more symbols. */
%parse_failure { %parse_failure {
dfw->syntax_error = TRUE; dfw->parse_failure = TRUE;
} }
/* ----------------- The grammar -------------- */ /* ----------------- The grammar -------------- */

View File

@ -97,7 +97,7 @@ static gboolean parse_charconst(df_scanner_state_t *state, const char *s, unsign
static void update_location(df_scanner_state_t *state, const char *text); static void update_location(df_scanner_state_t *state, const char *text);
static void update_string_loc(df_scanner_state_t *state, const char *text); static void update_string_loc(df_scanner_state_t *state, const char *text);
#define FAIL(...) dfilter_fail(yyextra->dfw, &yyextra->location, __VA_ARGS__) #define FAIL(...) dfilter_fail(yyextra->dfw, DF_ERROR_GENERIC, &yyextra->location, __VA_ARGS__)
/* /*
* Sleazy hack to suppress compiler warnings in yy_fatal_error(). * Sleazy hack to suppress compiler warnings in yy_fatal_error().
@ -551,7 +551,7 @@ set_lval_field(df_scanner_state_t *state, const char *token_value)
hfinfo = dfilter_resolve_unparsed(state->dfw, token_value); hfinfo = dfilter_resolve_unparsed(state->dfw, token_value);
if (hfinfo == NULL) { if (hfinfo == NULL) {
dfilter_fail(state->dfw, &state->location, "\"%s\" is not a valid protocol or protocol field.", token_value); dfilter_fail(state->dfw, DF_ERROR_GENERIC, &state->location, "\"%s\" is not a valid protocol or protocol field.", token_value);
} }
stnode_init(df_lval, STTYPE_FIELD, hfinfo, g_strdup(token_value), &state->location); stnode_init(df_lval, STTYPE_FIELD, hfinfo, g_strdup(token_value), &state->location);
return TOKEN_FIELD; return TOKEN_FIELD;
@ -587,7 +587,7 @@ append_escaped_char(df_scanner_state_t *state, GString *str, char c)
case '\"': case '\"':
break; break;
default: default:
dfilter_fail(state->dfw, &state->location, dfilter_fail(state->dfw, DF_ERROR_GENERIC, &state->location,
"\\%c is not a valid character escape sequence", c); "\\%c is not a valid character escape sequence", c);
return FALSE; return FALSE;
} }
@ -657,7 +657,7 @@ append_universal_character_name(df_scanner_state_t *state, GString *str, const c
gunichar val; gunichar val;
if (!parse_universal_character_name(state, ucn, NULL, &val)) { if (!parse_universal_character_name(state, ucn, NULL, &val)) {
dfilter_fail(state->dfw, &state->location, "%s is not a valid universal character name", ucn); dfilter_fail(state->dfw, DF_ERROR_GENERIC, &state->location, "%s is not a valid universal character name", ucn);
return FALSE; return FALSE;
} }
@ -675,7 +675,7 @@ parse_charconst(df_scanner_state_t *state, const char *s, unsigned long *valuep)
cp = s + 1; /* skip the leading ' */ cp = s + 1; /* skip the leading ' */
if (*cp == '\'') { if (*cp == '\'') {
dfilter_fail(state->dfw, &state->string_loc, "Empty character constant."); dfilter_fail(state->dfw, DF_ERROR_GENERIC, &state->string_loc, "Empty character constant.");
return FALSE; return FALSE;
} }
@ -691,7 +691,7 @@ parse_charconst(df_scanner_state_t *state, const char *s, unsigned long *valuep)
switch (*cp) { switch (*cp) {
case '\0': case '\0':
dfilter_fail(state->dfw, &state->string_loc, "%s isn't a valid character constant.", s); dfilter_fail(state->dfw, DF_ERROR_GENERIC, &state->string_loc, "%s isn't a valid character constant.", s);
return FALSE; return FALSE;
case 'a': case 'a':
@ -752,7 +752,7 @@ parse_charconst(df_scanner_state_t *state, const char *s, unsigned long *valuep)
else if (*cp >= 'a' && *cp <= 'f') else if (*cp >= 'a' && *cp <= 'f')
value = 10 + (*cp - 'a'); value = 10 + (*cp - 'a');
else { else {
dfilter_fail(state->dfw, &state->string_loc, "%s isn't a valid character constant.", s); dfilter_fail(state->dfw, DF_ERROR_GENERIC, &state->string_loc, "%s isn't a valid character constant.", s);
return FALSE; return FALSE;
} }
cp++; cp++;
@ -765,7 +765,7 @@ parse_charconst(df_scanner_state_t *state, const char *s, unsigned long *valuep)
else if (*cp >= 'a' && *cp <= 'f') else if (*cp >= 'a' && *cp <= 'f')
value |= 10 + (*cp - 'a'); value |= 10 + (*cp - 'a');
else { else {
dfilter_fail(state->dfw, &state->string_loc, "%s isn't a valid character constant.", s); dfilter_fail(state->dfw, DF_ERROR_GENERIC, &state->string_loc, "%s isn't a valid character constant.", s);
return FALSE; return FALSE;
} }
} }
@ -775,7 +775,7 @@ parse_charconst(df_scanner_state_t *state, const char *s, unsigned long *valuep)
case 'u': case 'u':
case 'U': case 'U':
if (!parse_universal_character_name(state, s+1, &endptr, &unival)) { if (!parse_universal_character_name(state, s+1, &endptr, &unival)) {
dfilter_fail(state->dfw, &state->string_loc, "%s is not a valid universal character name", s); dfilter_fail(state->dfw, DF_ERROR_GENERIC, &state->string_loc, "%s is not a valid universal character name", s);
return FALSE; return FALSE;
} }
value = (unsigned long)unival; value = (unsigned long)unival;
@ -787,7 +787,7 @@ parse_charconst(df_scanner_state_t *state, const char *s, unsigned long *valuep)
if (*cp >= '0' && *cp <= '7') if (*cp >= '0' && *cp <= '7')
value = *cp - '0'; value = *cp - '0';
else { else {
dfilter_fail(state->dfw, &state->string_loc, "%s isn't a valid character constant.", s); dfilter_fail(state->dfw, DF_ERROR_GENERIC, &state->string_loc, "%s isn't a valid character constant.", s);
return FALSE; return FALSE;
} }
if (*(cp + 1) != '\'') { if (*(cp + 1) != '\'') {
@ -796,7 +796,7 @@ parse_charconst(df_scanner_state_t *state, const char *s, unsigned long *valuep)
if (*cp >= '0' && *cp <= '7') if (*cp >= '0' && *cp <= '7')
value |= *cp - '0'; value |= *cp - '0';
else { else {
dfilter_fail(state->dfw, &state->string_loc, "%s isn't a valid character constant.", s); dfilter_fail(state->dfw, DF_ERROR_GENERIC, &state->string_loc, "%s isn't a valid character constant.", s);
return FALSE; return FALSE;
} }
if (*(cp + 1) != '\'') { if (*(cp + 1) != '\'') {
@ -805,13 +805,13 @@ parse_charconst(df_scanner_state_t *state, const char *s, unsigned long *valuep)
if (*cp >= '0' && *cp <= '7') if (*cp >= '0' && *cp <= '7')
value |= *cp - '0'; value |= *cp - '0';
else { else {
dfilter_fail(state->dfw, &state->string_loc, "%s isn't a valid character constant.", s); dfilter_fail(state->dfw, DF_ERROR_GENERIC, &state->string_loc, "%s isn't a valid character constant.", s);
return FALSE; return FALSE;
} }
} }
} }
if (value > 0xFF) { if (value > 0xFF) {
dfilter_fail(state->dfw, &state->string_loc, "%s is too large to be a valid character constant.", s); dfilter_fail(state->dfw, DF_ERROR_GENERIC, &state->string_loc, "%s is too large to be a valid character constant.", s);
return FALSE; return FALSE;
} }
cp++; cp++;
@ -819,13 +819,13 @@ parse_charconst(df_scanner_state_t *state, const char *s, unsigned long *valuep)
} else { } else {
value = *cp++; value = *cp++;
if (!g_ascii_isprint(value)) { if (!g_ascii_isprint(value)) {
dfilter_fail(state->dfw, &state->string_loc, "Non-printable value '0x%02lx' in character constant.", value); dfilter_fail(state->dfw, DF_ERROR_GENERIC, &state->string_loc, "Non-printable value '0x%02lx' in character constant.", value);
return FALSE; return FALSE;
} }
} }
if ((*cp != '\'') || (*(cp + 1) != '\0')){ if ((*cp != '\'') || (*(cp + 1) != '\0')){
dfilter_fail(state->dfw, &state->string_loc, "%s is too long to be a valid character constant.", s); dfilter_fail(state->dfw, DF_ERROR_GENERIC, &state->string_loc, "%s is too long to be a valid character constant.", s);
return FALSE; return FALSE;
} }

View File

@ -34,7 +34,7 @@
#define FAIL(dfw, node, ...) \ #define FAIL(dfw, node, ...) \
do { \ do { \
ws_noisy("Semantic check failed here."); \ ws_noisy("Semantic check failed here."); \
dfilter_fail_throw(dfw, stnode_location(node), __VA_ARGS__); \ dfilter_fail_throw(dfw, DF_ERROR_GENERIC, stnode_location(node), __VA_ARGS__); \
} while (0) } while (0)
static void static void
@ -151,6 +151,18 @@ node_is_constant(stnode_t *node)
return FALSE; return FALSE;
} }
/* Don't set the error message if it's already set. */
#define SET_ERROR(dfw, str) \
do { \
if ((str) != NULL && (dfw)->error.msg == NULL) { \
(dfw)->error.msg = str; \
(dfw)->error.code = DF_ERROR_GENERIC; \
} \
else { \
g_free(str); \
} \
} while (0)
/* Gets an fvalue from a string, and sets the error message on failure. */ /* Gets an fvalue from a string, and sets the error message on failure. */
WS_RETNONNULL WS_RETNONNULL
fvalue_t* fvalue_t*
@ -159,10 +171,11 @@ dfilter_fvalue_from_literal(dfwork_t *dfw, ftenum_t ftype, stnode_t *st,
{ {
fvalue_t *fv; fvalue_t *fv;
const char *s = stnode_data(st); const char *s = stnode_data(st);
gchar *error_message = NULL;
fv = fvalue_from_literal(ftype, s, allow_partial_value, &error_message);
SET_ERROR(dfw, error_message);
/* Don't set the error message if it's already set. */
fv = fvalue_from_literal(ftype, s, allow_partial_value,
dfw->error_message == NULL ? &dfw->error_message : NULL);
if (fv == NULL && hfinfo_value_string) { if (fv == NULL && hfinfo_value_string) {
/* check value_string */ /* check value_string */
fv = mk_fvalue_from_val_string(dfw, hfinfo_value_string, s); fv = mk_fvalue_from_val_string(dfw, hfinfo_value_string, s);
@ -170,9 +183,8 @@ dfilter_fvalue_from_literal(dfwork_t *dfw, ftenum_t ftype, stnode_t *st,
* Ignore previous errors if this can be mapped * Ignore previous errors if this can be mapped
* to an item from value_string. * to an item from value_string.
*/ */
if (fv && dfw->error_message) { if (fv) {
g_free(dfw->error_message); dfw_error_clear(&dfw->error);
dfw->error_message = NULL;
} }
} }
if (fv == NULL) { if (fv == NULL) {
@ -191,18 +203,19 @@ dfilter_fvalue_from_string(dfwork_t *dfw, ftenum_t ftype, stnode_t *st,
{ {
fvalue_t *fv; fvalue_t *fv;
const GString *gs = stnode_string(st); const GString *gs = stnode_string(st);
gchar *error_message = NULL;
fv = fvalue_from_string(ftype, gs->str, gs->len, &error_message);
SET_ERROR(dfw, error_message);
fv = fvalue_from_string(ftype, gs->str, gs->len,
dfw->error_message == NULL ? &dfw->error_message : NULL);
if (fv == NULL && hfinfo_value_string) { if (fv == NULL && hfinfo_value_string) {
fv = mk_fvalue_from_val_string(dfw, hfinfo_value_string, gs->str); fv = mk_fvalue_from_val_string(dfw, hfinfo_value_string, gs->str);
/* /*
* Ignore previous errors if this can be mapped * Ignore previous errors if this can be mapped
* to an item from value_string. * to an item from value_string.
*/ */
if (fv && dfw->error_message) { if (fv) {
g_free(dfw->error_message); dfw_error_clear(&dfw->error);
dfw->error_message = NULL;
} }
} }
if (fv == NULL) { if (fv == NULL) {
@ -319,9 +332,8 @@ mk_fvalue_from_val_string(dfwork_t *dfw, header_field_info *hfinfo, const char *
* Prefer this error message to whatever error message * Prefer this error message to whatever error message
* has already been set. * has already been set.
*/ */
g_free(dfw->error_message); dfw_error_clear(&dfw->error);
dfw->error_message = NULL; dfilter_fail(dfw, DF_ERROR_GENERIC, NULL, "\"%s\" cannot be found among the possible values for %s.",
dfilter_fail(dfw, NULL, "\"%s\" cannot be found among the possible values for %s.",
s, hfinfo->abbrev); s, hfinfo->abbrev);
return NULL; return NULL;
} }
@ -329,7 +341,7 @@ mk_fvalue_from_val_string(dfwork_t *dfw, header_field_info *hfinfo, const char *
/* Do val_strings exist? */ /* Do val_strings exist? */
if (!hfinfo->strings) { if (!hfinfo->strings) {
dfilter_fail(dfw, NULL, "%s cannot accept strings as values.", dfilter_fail(dfw, DF_ERROR_GENERIC, NULL, "%s cannot accept strings as values.",
hfinfo->abbrev); hfinfo->abbrev);
return NULL; return NULL;
} }
@ -337,11 +349,10 @@ mk_fvalue_from_val_string(dfwork_t *dfw, header_field_info *hfinfo, const char *
/* Reset the error message, since *something* interesting will happen, /* Reset the error message, since *something* interesting will happen,
* and the error message will be more interesting than any error message * and the error message will be more interesting than any error message
* I happen to have now. */ * I happen to have now. */
g_free(dfw->error_message); dfw_error_clear(&dfw->error);
dfw->error_message = NULL;
if (hfinfo->display & BASE_RANGE_STRING) { if (hfinfo->display & BASE_RANGE_STRING) {
dfilter_fail(dfw, NULL, "\"%s\" cannot accept [range] strings as values.", dfilter_fail(dfw, DF_ERROR_GENERIC, NULL, "\"%s\" cannot accept [range] strings as values.",
hfinfo->abbrev); hfinfo->abbrev);
} }
else if (hfinfo->display & BASE_VAL64_STRING) { else if (hfinfo->display & BASE_VAL64_STRING) {
@ -353,7 +364,7 @@ mk_fvalue_from_val_string(dfwork_t *dfw, header_field_info *hfinfo, const char *
} }
vals++; vals++;
} }
dfilter_fail(dfw, NULL, "\"%s\" cannot be found among the possible values for %s.", dfilter_fail(dfw, DF_ERROR_GENERIC, NULL, "\"%s\" cannot be found among the possible values for %s.",
s, hfinfo->abbrev); s, hfinfo->abbrev);
} }
else if (hfinfo->display == BASE_CUSTOM) { else if (hfinfo->display == BASE_CUSTOM) {
@ -363,7 +374,7 @@ mk_fvalue_from_val_string(dfwork_t *dfw, header_field_info *hfinfo, const char *
* integer, we have the string they're trying to match. * integer, we have the string they're trying to match.
* -><- * -><-
*/ */
dfilter_fail(dfw, NULL, "\"%s\" cannot accept [custom] strings as values.", dfilter_fail(dfw, DF_ERROR_GENERIC, NULL, "\"%s\" cannot accept [custom] strings as values.",
hfinfo->abbrev); hfinfo->abbrev);
} }
else { else {
@ -377,7 +388,7 @@ mk_fvalue_from_val_string(dfwork_t *dfw, header_field_info *hfinfo, const char *
} }
vals++; vals++;
} }
dfilter_fail(dfw, NULL, "\"%s\" cannot be found among the possible values for %s.", dfilter_fail(dfw, DF_ERROR_GENERIC, NULL, "\"%s\" cannot be found among the possible values for %s.",
s, hfinfo->abbrev); s, hfinfo->abbrev);
} }
return NULL; return NULL;
@ -567,9 +578,10 @@ dfilter_fvalue_from_charconst(dfwork_t *dfw, ftenum_t ftype, stnode_t *st)
{ {
fvalue_t *fvalue; fvalue_t *fvalue;
unsigned long *nump = stnode_data(st); unsigned long *nump = stnode_data(st);
char *error_message = NULL;
fvalue = fvalue_from_charconst(ftype, *nump, fvalue = fvalue_from_charconst(ftype, *nump, &error_message);
dfw->error_message == NULL ? &dfw->error_message : NULL); SET_ERROR(dfw, error_message);
if (fvalue == NULL) { if (fvalue == NULL) {
dfw_set_error_location(dfw, stnode_location(st)); dfw_set_error_location(dfw, stnode_location(st));
@ -980,7 +992,7 @@ check_relation_matches(dfwork_t *dfw, stnode_t *st_node,
pcre = ws_regex_compile_ex(patt->str, patt->len, &errmsg, WS_REGEX_CASELESS|WS_REGEX_NEVER_UTF); pcre = ws_regex_compile_ex(patt->str, patt->len, &errmsg, WS_REGEX_CASELESS|WS_REGEX_NEVER_UTF);
if (errmsg) { if (errmsg) {
dfilter_fail(dfw, NULL, "Regex compilation error: %s.", errmsg); dfilter_fail(dfw, DF_ERROR_GENERIC, NULL, "Regex compilation error: %s.", errmsg);
g_free(errmsg); g_free(errmsg);
THROW(TypeError); THROW(TypeError);
} }
@ -1177,7 +1189,7 @@ check_arithmetic_expr(dfwork_t *dfw, stnode_t *st_node, ftenum_t lhs_ftype)
char *err_msg; char *err_msg;
fvalue_t *new_fv = fvalue_unary_minus(stnode_data(st_arg1), &err_msg); fvalue_t *new_fv = fvalue_unary_minus(stnode_data(st_arg1), &err_msg);
if (new_fv == NULL) { if (new_fv == NULL) {
dfilter_fail(dfw, stnode_location(st_arg1), dfilter_fail(dfw, DF_ERROR_GENERIC, stnode_location(st_arg1),
"%s: %s", stnode_todisplay(st_arg1), err_msg); "%s: %s", stnode_todisplay(st_arg1), err_msg);
g_free(err_msg); g_free(err_msg);
THROW(TypeError); THROW(TypeError);

View File

@ -7077,14 +7077,14 @@ static void
ncp2222_compile_dfilters(void) ncp2222_compile_dfilters(void)
{ {
int i; int i;
gchar *err_msg; df_error_t *df_err;
for (i = 0; i < NUM_REQ_CONDS; i++) { for (i = 0; i < NUM_REQ_CONDS; i++) {
if (!dfilter_compile((const gchar*)req_conds[i].dfilter_text, if (!dfilter_compile((const gchar*)req_conds[i].dfilter_text,
&req_conds[i].dfilter, &err_msg)) { &req_conds[i].dfilter, &df_err)) {
g_error("NCP dissector failed to compile dfilter \"%s\": %s\n", g_error("NCP dissector failed to compile dfilter \"%s\": %s\n",
req_conds[i].dfilter_text, err_msg); req_conds[i].dfilter_text, df_err->msg);
g_free(err_msg); dfilter_error_free(df_err);
ws_assert_not_reached(); ws_assert_not_reached();
} }
} }

View File

@ -541,7 +541,7 @@ register_tap_listener(const char *tapname, void *tapdata, const char *fstring,
int tap_id; int tap_id;
dfilter_t *code=NULL; dfilter_t *code=NULL;
GString *error_string; GString *error_string;
gchar *err_msg; df_error_t *df_err;
tap_id=find_tap_id(tapname); tap_id=find_tap_id(tapname);
if(!tap_id){ if(!tap_id){
@ -555,12 +555,12 @@ register_tap_listener(const char *tapname, void *tapdata, const char *fstring,
tl->failed=FALSE; tl->failed=FALSE;
tl->flags=flags; tl->flags=flags;
if(fstring){ if(fstring){
if(!dfilter_compile(fstring, &code, &err_msg)){ if(!dfilter_compile(fstring, &code, &df_err)){
error_string = g_string_new(""); error_string = g_string_new("");
g_string_printf(error_string, g_string_printf(error_string,
"Filter \"%s\" is invalid - %s", "Filter \"%s\" is invalid - %s",
fstring, err_msg); fstring, df_err->msg);
g_free(err_msg); dfilter_error_free(df_err);
free_tap_listener(tl); free_tap_listener(tl);
return error_string; return error_string;
} }
@ -589,7 +589,7 @@ set_tap_dfilter(void *tapdata, const char *fstring)
tap_listener_t *tl=NULL,*tl2; tap_listener_t *tl=NULL,*tl2;
dfilter_t *code=NULL; dfilter_t *code=NULL;
GString *error_string; GString *error_string;
gchar *err_msg; df_error_t *df_err;
if(!tap_listener_queue){ if(!tap_listener_queue){
return NULL; return NULL;
@ -615,13 +615,13 @@ set_tap_dfilter(void *tapdata, const char *fstring)
tl->needs_redraw=TRUE; tl->needs_redraw=TRUE;
g_free(tl->fstring); g_free(tl->fstring);
if(fstring){ if(fstring){
if(!dfilter_compile(fstring, &code, &err_msg)){ if(!dfilter_compile(fstring, &code, &df_err)){
tl->fstring=NULL; tl->fstring=NULL;
error_string = g_string_new(""); error_string = g_string_new("");
g_string_printf(error_string, g_string_printf(error_string,
"Filter \"%s\" is invalid - %s", "Filter \"%s\" is invalid - %s",
fstring, err_msg); fstring, df_err->msg);
g_free(err_msg); dfilter_error_free(df_err);
return error_string; return error_string;
} }
} }
@ -639,7 +639,6 @@ tap_listeners_dfilter_recompile(void)
{ {
tap_listener_t *tl; tap_listener_t *tl;
dfilter_t *code; dfilter_t *code;
gchar *err_msg;
for(tl=tap_listener_queue;tl;tl=tl->next){ for(tl=tap_listener_queue;tl;tl=tl->next){
if(tl->code){ if(tl->code){
@ -649,12 +648,9 @@ tap_listeners_dfilter_recompile(void)
tl->needs_redraw=TRUE; tl->needs_redraw=TRUE;
code=NULL; code=NULL;
if(tl->fstring){ if(tl->fstring){
if(!dfilter_compile(tl->fstring, &code, &err_msg)){ if(!dfilter_compile(tl->fstring, &code, NULL)){
g_free(err_msg);
err_msg = NULL;
/* Not valid, make a dfilter matching no packets */ /* Not valid, make a dfilter matching no packets */
if (!dfilter_compile("frame.number == 0", &code, &err_msg)) dfilter_compile("frame.number == 0", &code, NULL);
g_free(err_msg);
} }
} }
tl->code=code; tl->code=code;

View File

@ -556,7 +556,7 @@ static gboolean fake_tap = FALSE;
void lua_prime_all_fields(proto_tree* tree _U_) { void lua_prime_all_fields(proto_tree* tree _U_) {
GString* fake_tap_filter = g_string_new("frame"); GString* fake_tap_filter = g_string_new("frame");
guint i; guint i;
gchar *err_msg; df_error_t *df_err;
for(i=0; i < wanted_fields->len; i++) { for(i=0; i < wanted_fields->len; i++) {
Field f = (Field)g_ptr_array_index(wanted_fields,i); Field f = (Field)g_ptr_array_index(wanted_fields,i);
@ -585,9 +585,9 @@ void lua_prime_all_fields(proto_tree* tree _U_) {
if (error) { if (error) {
report_failure("while registering lua_fake_tap:\n%s",error->str); report_failure("while registering lua_fake_tap:\n%s",error->str);
g_string_free(error,TRUE); g_string_free(error,TRUE);
} else if (!dfilter_compile(fake_tap_filter->str, &wslua_dfilter, &err_msg)) { } else if (!dfilter_compile(fake_tap_filter->str, &wslua_dfilter, &df_err)) {
report_failure("while compiling dfilter \"%s\" for wslua: %s", fake_tap_filter->str, err_msg); report_failure("while compiling dfilter \"%s\" for wslua: %s", fake_tap_filter->str, df_err->msg);
g_free(err_msg); dfilter_error_free(df_err);
} }
} }
g_string_free(fake_tap_filter, TRUE); g_string_free(fake_tap_filter, TRUE);

8
file.c
View File

@ -1475,7 +1475,7 @@ cf_filter_packets(capture_file *cf, gchar *dftext, gboolean force)
const char *filter_new = dftext ? dftext : ""; const char *filter_new = dftext ? dftext : "";
const char *filter_old = cf->dfilter ? cf->dfilter : ""; const char *filter_old = cf->dfilter ? cf->dfilter : "";
dfilter_t *dfcode; dfilter_t *dfcode;
gchar *err_msg; df_error_t *df_err;
/* if new filter equals old one, do nothing unless told to do so */ /* if new filter equals old one, do nothing unless told to do so */
if (!force && strcmp(filter_new, filter_old) == 0) { if (!force && strcmp(filter_new, filter_old) == 0) {
@ -1494,13 +1494,13 @@ cf_filter_packets(capture_file *cf, gchar *dftext, gboolean force)
* and try to compile it. * and try to compile it.
*/ */
dftext = g_strdup(dftext); dftext = g_strdup(dftext);
if (!dfilter_compile(dftext, &dfcode, &err_msg)) { if (!dfilter_compile(dftext, &dfcode, &df_err)) {
/* The attempt failed; report an error. */ /* The attempt failed; report an error. */
simple_message_box(ESD_TYPE_ERROR, NULL, simple_message_box(ESD_TYPE_ERROR, NULL,
"See the help for a description of the display filter syntax.", "See the help for a description of the display filter syntax.",
"\"%s\" isn't a valid display filter: %s", "\"%s\" isn't a valid display filter: %s",
dftext, err_msg); dftext, df_err->msg);
g_free(err_msg); dfilter_error_free(df_err);
g_free(dftext); g_free(dftext);
return CF_ERROR; return CF_ERROR;
} }

View File

@ -398,6 +398,7 @@ main(int argc, char *argv[])
{ {
char *err_msg; char *err_msg;
int opt, i; int opt, i;
df_error_t *df_err;
#ifndef _WIN32 #ifndef _WIN32
struct rlimit limit; struct rlimit limit;
@ -759,9 +760,9 @@ main(int argc, char *argv[])
if (n_rfilters != 0) { if (n_rfilters != 0) {
for (i = 0; i < n_rfilters; i++) { for (i = 0; i < n_rfilters; i++) {
if (!dfilter_compile(rfilters[i], &rfcodes[n_rfcodes], &err_msg)) { if (!dfilter_compile(rfilters[i], &rfcodes[n_rfcodes], &df_err)) {
cmdarg_err("%s", err_msg); cmdarg_err("%s", df_err->msg);
g_free(err_msg); dfilter_error_free(df_err);
ret = INVALID_DFILTER; ret = INVALID_DFILTER;
goto clean_exit; goto clean_exit;
} }

View File

@ -646,8 +646,7 @@ sharkd_filter(const char *dftext, guint8 **result)
epan_dissect_t edt; epan_dissect_t edt;
if (!dfilter_compile(dftext, &dfcode, &err_info)) { if (!dfilter_compile(dftext, &dfcode, NULL)) {
g_free(err_info);
return -1; return -1;
} }

View File

@ -4069,26 +4069,27 @@ sharkd_session_process_check(char *buf, const jsmntok_t *tokens, int count)
if (tok_filter != NULL) if (tok_filter != NULL)
{ {
char *err_msg = NULL;
dfilter_t *dfp; dfilter_t *dfp;
df_error_t *df_err = NULL;
if (dfilter_compile(tok_filter, &dfp, &err_msg)) if (dfilter_compile(tok_filter, &dfp, &df_err))
{ {
if (dfp && dfilter_deprecated_tokens(dfp)) if (dfp && dfilter_deprecated_tokens(dfp))
sharkd_json_warning(rpcid, err_msg); sharkd_json_warning(rpcid, df_err->msg);
else else
sharkd_json_simple_ok(rpcid); sharkd_json_simple_ok(rpcid);
dfilter_free(dfp); dfilter_free(dfp);
g_free(err_msg); dfilter_error_free(df_err);
return 0; return 0;
} }
else else
{ {
sharkd_json_error( sharkd_json_error(
rpcid, -5001, NULL, rpcid, -5001, NULL,
"Filter invalid - %s", err_msg "Filter invalid - %s", df_err->msg
); );
dfilter_error_free(df_err);
return -5001; return -5001;
} }
} }

View File

@ -282,7 +282,7 @@ main(int argc, char *argv[])
gchar *dfilter = NULL; gchar *dfilter = NULL;
dfilter_t *rfcode = NULL; dfilter_t *rfcode = NULL;
dfilter_t *dfcode = NULL; dfilter_t *dfcode = NULL;
gchar *err_msg; df_error_t *df_err;
e_prefs *prefs_p; e_prefs *prefs_p;
gchar *output_only = NULL; gchar *output_only = NULL;
@ -859,9 +859,9 @@ main(int argc, char *argv[])
build_column_format_array(&cfile.cinfo, prefs_p->num_cols, TRUE); build_column_format_array(&cfile.cinfo, prefs_p->num_cols, TRUE);
if (rfilter != NULL) { if (rfilter != NULL) {
if (!dfilter_compile(rfilter, &rfcode, &err_msg)) { if (!dfilter_compile(rfilter, &rfcode, &df_err)) {
cmdarg_err("%s", err_msg); cmdarg_err("%s", df_err->msg);
g_free(err_msg); dfilter_error_free(df_err);
exit_status = INVALID_FILTER; exit_status = INVALID_FILTER;
goto clean_exit; goto clean_exit;
} }
@ -869,9 +869,9 @@ main(int argc, char *argv[])
cfile.rfcode = rfcode; cfile.rfcode = rfcode;
if (dfilter != NULL) { if (dfilter != NULL) {
if (!dfilter_compile(dfilter, &dfcode, &err_msg)) { if (!dfilter_compile(dfilter, &dfcode, &df_err)) {
cmdarg_err("%s", err_msg); cmdarg_err("%s", df_err->msg);
g_free(err_msg); dfilter_error_free(df_err);
exit_status = INVALID_FILTER; exit_status = INVALID_FILTER;
goto clean_exit; goto clean_exit;
} }

View File

@ -614,8 +614,8 @@ static gboolean
_compile_dfilter(const char *text, dfilter_t **dfp, const char *caller) _compile_dfilter(const char *text, dfilter_t **dfp, const char *caller)
{ {
gboolean ok; gboolean ok;
dfilter_loc_t err_loc;
char *err_msg = NULL; char *err_msg = NULL;
df_error_t *df_err;
char *err_off; char *err_off;
char *expanded; char *expanded;
@ -626,16 +626,17 @@ _compile_dfilter(const char *text, dfilter_t **dfp, const char *caller)
return FALSE; return FALSE;
} }
ok = dfilter_compile_real(expanded, dfp, &err_msg, &err_loc, caller, FALSE, FALSE); ok = dfilter_compile_real(expanded, dfp, &df_err, caller, FALSE, FALSE);
if (!ok ) { if (!ok ) {
cmdarg_err("%s", err_msg); cmdarg_err("%s", df_err->msg);
g_free(err_msg);
if (err_loc.col_start >= 0) { if (df_err->loc.col_start >= 0) {
err_off = ws_strdup_underline(NULL, err_loc.col_start, err_loc.col_len); err_off = ws_strdup_underline(NULL, df_err->loc.col_start, df_err->loc.col_len);
cmdarg_err_cont(" %s", expanded); cmdarg_err_cont(" %s", expanded);
cmdarg_err_cont(" %s", err_off); cmdarg_err_cont(" %s", err_off);
g_free(err_off); g_free(err_off);
} }
dfilter_error_free(df_err);
} }
g_free(expanded); g_free(expanded);

View File

@ -428,6 +428,7 @@ int main(int argc, char *qt_argv[])
#endif #endif
#endif #endif
gchar *err_msg = NULL; gchar *err_msg = NULL;
df_error_t *df_err = NULL;
QString dfilter, read_filter; QString dfilter, read_filter;
#ifdef HAVE_LIBPCAP #ifdef HAVE_LIBPCAP
@ -960,13 +961,13 @@ int main(int argc, char *qt_argv[])
} else if (global_commandline_info.jfilter != NULL) { } else if (global_commandline_info.jfilter != NULL) {
dfilter_t *jump_to_filter = NULL; dfilter_t *jump_to_filter = NULL;
/* try to compile given filter */ /* try to compile given filter */
if (!dfilter_compile(global_commandline_info.jfilter, &jump_to_filter, &err_msg)) { if (!dfilter_compile(global_commandline_info.jfilter, &jump_to_filter, &df_err)) {
// Similar code in MainWindow::mergeCaptureFile(). // Similar code in MainWindow::mergeCaptureFile().
QMessageBox::warning(main_w, QObject::tr("Invalid Display Filter"), QMessageBox::warning(main_w, QObject::tr("Invalid Display Filter"),
QObject::tr("The filter expression %1 isn't a valid display filter. (%2).") QObject::tr("The filter expression %1 isn't a valid display filter. (%2).")
.arg(global_commandline_info.jfilter, err_msg), .arg(global_commandline_info.jfilter, df_err->msg),
QMessageBox::Ok); QMessageBox::Ok);
g_free(err_msg); dfilter_error_free(df_err);
} else { } else {
/* Filter ok, jump to the first packet matching the filter /* Filter ok, jump to the first packet matching the filter
conditions. Default search direction is forward, but if conditions. Default search direction is forward, but if

View File

@ -1164,16 +1164,16 @@ void LograyMainWindow::mergeCaptureFile()
char *tmpname; char *tmpname;
if (merge_dlg.merge(file_name, read_filter)) { if (merge_dlg.merge(file_name, read_filter)) {
gchar *err_msg; df_error_t *df_err = NULL;
if (!dfilter_compile(qUtf8Printable(read_filter), &rfcode, &err_msg)) { if (!dfilter_compile(qUtf8Printable(read_filter), &rfcode, &df_err)) {
/* Not valid. Tell the user, and go back and run the file /* Not valid. Tell the user, and go back and run the file
selection box again once they dismiss the alert. */ selection box again once they dismiss the alert. */
// Similar to commandline_info.jfilter section in main(). // Similar to commandline_info.jfilter section in main().
QMessageBox::warning(this, tr("Invalid Read Filter"), QMessageBox::warning(this, tr("Invalid Read Filter"),
QString(tr("The filter expression %1 isn't a valid read filter. (%2).").arg(read_filter, err_msg)), QString(tr("The filter expression %1 isn't a valid read filter. (%2).").arg(read_filter, df_err->msg)),
QMessageBox::Ok); QMessageBox::Ok);
g_free(err_msg); dfilter_error_free(df_err);
continue; continue;
} }
} else { } else {

View File

@ -161,7 +161,7 @@ bool LograyMainWindow::openCaptureFile(QString cf_path, QString read_filter, uns
{ {
QString file_name = ""; QString file_name = "";
dfilter_t *rfcode = NULL; dfilter_t *rfcode = NULL;
gchar *err_msg; df_error_t *df_err = NULL;
int err; int err;
gboolean name_param; gboolean name_param;
gboolean ret = true; gboolean ret = true;
@ -194,7 +194,7 @@ bool LograyMainWindow::openCaptureFile(QString cf_path, QString read_filter, uns
goto finish; goto finish;
} }
if (dfilter_compile(qUtf8Printable(read_filter), &rfcode, &err_msg)) { if (dfilter_compile(qUtf8Printable(read_filter), &rfcode, &df_err)) {
cf_set_rfcode(CaptureFile::globalCapFile(), rfcode); cf_set_rfcode(CaptureFile::globalCapFile(), rfcode);
} else { } else {
/* Not valid. Tell the user, and go back and run the file /* Not valid. Tell the user, and go back and run the file
@ -204,8 +204,9 @@ bool LograyMainWindow::openCaptureFile(QString cf_path, QString read_filter, uns
QString("The filter expression ") + QString("The filter expression ") +
read_filter + read_filter +
QString(" isn't a valid display filter. (") + QString(" isn't a valid display filter. (") +
err_msg + QString(")."), df_err->msg + QString(")."),
QMessageBox::Ok); QMessageBox::Ok);
dfilter_error_free(df_err);
if (!name_param) { if (!name_param) {
// go back to the selection dialogue only if the file // go back to the selection dialogue only if the file

View File

@ -174,17 +174,17 @@ void ColoringRulesDialog::rowCountChanged()
bool ColoringRulesDialog::isValidFilter(QString filter, QString * error) bool ColoringRulesDialog::isValidFilter(QString filter, QString * error)
{ {
dfilter_t *dfp = NULL; dfilter_t *dfp = NULL;
gchar *err_msg; df_error_t *df_err = NULL;
if (dfilter_compile(filter.toUtf8().constData(), &dfp, &err_msg)) { if (dfilter_compile(filter.toUtf8().constData(), &dfp, &df_err)) {
dfilter_free(dfp); dfilter_free(dfp);
return true; return true;
} }
if (err_msg) if (df_err)
{ {
error->append(err_msg); error->append(df_err->msg);
g_free(err_msg); dfilter_error_free(df_err);
} }
return false; return false;

View File

@ -294,12 +294,12 @@ Iax2AnalysisDialog::Iax2AnalysisDialog(QWidget &parent, CaptureFile &cf) :
const gchar filter_text[] = "iax2 && (ip || ipv6)"; const gchar filter_text[] = "iax2 && (ip || ipv6)";
#endif #endif
dfilter_t *sfcode; dfilter_t *sfcode;
gchar *err_msg; df_error_t *df_err;
/* Try to compile the filter. */ /* Try to compile the filter. */
if (!dfilter_compile(filter_text, &sfcode, &err_msg)) { if (!dfilter_compile(filter_text, &sfcode, &df_err)) {
err_str_ = QString(err_msg); err_str_ = QString(df_err->msg);
g_free(err_msg); dfilter_error_free(df_err);
updateWidgets(); updateWidgets();
return; return;
} }

View File

@ -1660,12 +1660,12 @@ void IOGraph::setFilter(const QString &filter)
if (!full_filter.isEmpty()) { if (!full_filter.isEmpty()) {
dfilter_t *dfilter; dfilter_t *dfilter;
bool status; bool status;
gchar *err_msg; df_error_t *df_err = NULL;
status = dfilter_compile(full_filter.toUtf8().constData(), &dfilter, &err_msg); status = dfilter_compile(full_filter.toUtf8().constData(), &dfilter, &df_err);
dfilter_free(dfilter); dfilter_free(dfilter);
if (!status) { if (!status) {
config_err_ = QString::fromUtf8(err_msg); config_err_ = QString::fromUtf8(df_err->msg);
g_free(err_msg); dfilter_error_free(df_err);
filter_ = full_filter; filter_ = full_filter;
return; return;
} }

View File

@ -451,6 +451,7 @@ int main(int argc, char *qt_argv[])
#endif #endif
#endif #endif
gchar *err_msg = NULL; gchar *err_msg = NULL;
df_error_t *df_err = NULL;
QString dfilter, read_filter; QString dfilter, read_filter;
#ifdef HAVE_LIBPCAP #ifdef HAVE_LIBPCAP
@ -982,13 +983,13 @@ int main(int argc, char *qt_argv[])
} else if (global_commandline_info.jfilter != NULL) { } else if (global_commandline_info.jfilter != NULL) {
dfilter_t *jump_to_filter = NULL; dfilter_t *jump_to_filter = NULL;
/* try to compile given filter */ /* try to compile given filter */
if (!dfilter_compile(global_commandline_info.jfilter, &jump_to_filter, &err_msg)) { if (!dfilter_compile(global_commandline_info.jfilter, &jump_to_filter, &df_err)) {
// Similar code in MainWindow::mergeCaptureFile(). // Similar code in MainWindow::mergeCaptureFile().
QMessageBox::warning(main_w, QObject::tr("Invalid Display Filter"), QMessageBox::warning(main_w, QObject::tr("Invalid Display Filter"),
QObject::tr("The filter expression %1 isn't a valid display filter. (%2).") QObject::tr("The filter expression %1 isn't a valid display filter. (%2).")
.arg(global_commandline_info.jfilter, err_msg), .arg(global_commandline_info.jfilter, df_err->msg),
QMessageBox::Ok); QMessageBox::Ok);
g_free(err_msg); dfilter_error_free(df_err);
} else { } else {
/* Filter ok, jump to the first packet matching the filter /* Filter ok, jump to the first packet matching the filter
conditions. Default search direction is forward, but if conditions. Default search direction is forward, but if

View File

@ -201,9 +201,8 @@ bool SyntaxLineEdit::checkDisplayFilter(QString filter)
} }
dfilter_t *dfp = NULL; dfilter_t *dfp = NULL;
gchar *err_msg; df_error_t *df_err = NULL;
dfilter_loc_t loc; if (dfilter_compile(filter.toUtf8().constData(), &dfp, &df_err)) {
if (dfilter_compile2(filter.toUtf8().constData(), &dfp, &err_msg, &loc)) {
GPtrArray *depr = NULL; GPtrArray *depr = NULL;
if (dfp) { if (dfp) {
depr = dfilter_deprecated_tokens(dfp); depr = dfilter_deprecated_tokens(dfp);
@ -231,9 +230,9 @@ bool SyntaxLineEdit::checkDisplayFilter(QString filter)
} }
} else { } else {
setSyntaxState(SyntaxLineEdit::Invalid); setSyntaxState(SyntaxLineEdit::Invalid);
syntax_error_message_ = QString::fromUtf8(err_msg); syntax_error_message_ = QString::fromUtf8(df_err->msg);
syntax_error_message_full_ = createSyntaxErrorMessageFull(filter, syntax_error_message_, loc.col_start, loc.col_len); syntax_error_message_full_ = createSyntaxErrorMessageFull(filter, syntax_error_message_, df_err->loc.col_start, df_err->loc.col_len);
g_free(err_msg); dfilter_error_free(df_err);
} }
dfilter_free(dfp); dfilter_free(dfp);

View File

@ -1227,16 +1227,16 @@ void WiresharkMainWindow::mergeCaptureFile()
char *tmpname; char *tmpname;
if (merge_dlg.merge(file_name, read_filter)) { if (merge_dlg.merge(file_name, read_filter)) {
gchar *err_msg; df_error_t *df_err = NULL;
if (!dfilter_compile(qUtf8Printable(read_filter), &rfcode, &err_msg)) { if (!dfilter_compile(qUtf8Printable(read_filter), &rfcode, &df_err)) {
/* Not valid. Tell the user, and go back and run the file /* Not valid. Tell the user, and go back and run the file
selection box again once they dismiss the alert. */ selection box again once they dismiss the alert. */
// Similar to commandline_info.jfilter section in main(). // Similar to commandline_info.jfilter section in main().
QMessageBox::warning(this, tr("Invalid Read Filter"), QMessageBox::warning(this, tr("Invalid Read Filter"),
QString(tr("The filter expression %1 isn't a valid read filter. (%2).").arg(read_filter, err_msg)), QString(tr("The filter expression %1 isn't a valid read filter. (%2).").arg(read_filter, df_err->msg)),
QMessageBox::Ok); QMessageBox::Ok);
g_free(err_msg); dfilter_error_free(df_err);
continue; continue;
} }
} else { } else {
@ -3009,7 +3009,7 @@ QString WiresharkMainWindow::findRtpStreams(QVector<rtpstream_id_t *> *stream_id
bool fwd_id_used, rev_id_used; bool fwd_id_used, rev_id_used;
const gchar filter_text[] = "rtp && rtp.version == 2 && rtp.ssrc && (ip || ipv6)"; const gchar filter_text[] = "rtp && rtp.version == 2 && rtp.ssrc && (ip || ipv6)";
dfilter_t *sfcode; dfilter_t *sfcode;
gchar *err_msg; df_error_t *df_err = NULL;
/* Try to get the hfid for "rtp.ssrc". */ /* Try to get the hfid for "rtp.ssrc". */
int hfid_rtp_ssrc = proto_registrar_get_id_byname("rtp.ssrc"); int hfid_rtp_ssrc = proto_registrar_get_id_byname("rtp.ssrc");
@ -3018,9 +3018,9 @@ QString WiresharkMainWindow::findRtpStreams(QVector<rtpstream_id_t *> *stream_id
} }
/* Try to compile the filter. */ /* Try to compile the filter. */
if (!dfilter_compile(filter_text, &sfcode, &err_msg)) { if (!dfilter_compile(filter_text, &sfcode, &df_err)) {
QString err = QString(err_msg); QString err = QString(df_err->msg);
g_free(err_msg); dfilter_error_free(df_err);
return err; return err;
} }

View File

@ -188,7 +188,7 @@ bool WiresharkMainWindow::openCaptureFile(QString cf_path, QString read_filter,
{ {
QString file_name = ""; QString file_name = "";
dfilter_t *rfcode = NULL; dfilter_t *rfcode = NULL;
gchar *err_msg; df_error_t *df_err = NULL;
int err; int err;
gboolean name_param; gboolean name_param;
gboolean ret = true; gboolean ret = true;
@ -221,7 +221,7 @@ bool WiresharkMainWindow::openCaptureFile(QString cf_path, QString read_filter,
goto finish; goto finish;
} }
if (dfilter_compile(qUtf8Printable(read_filter), &rfcode, &err_msg)) { if (dfilter_compile(qUtf8Printable(read_filter), &rfcode, &df_err)) {
cf_set_rfcode(CaptureFile::globalCapFile(), rfcode); cf_set_rfcode(CaptureFile::globalCapFile(), rfcode);
} else { } else {
/* Not valid. Tell the user, and go back and run the file /* Not valid. Tell the user, and go back and run the file
@ -231,9 +231,9 @@ bool WiresharkMainWindow::openCaptureFile(QString cf_path, QString read_filter,
QString("The filter expression ") + QString("The filter expression ") +
read_filter + read_filter +
QString(" isn't a valid display filter. (") + QString(" isn't a valid display filter. (") +
err_msg + QString(")."), df_err->msg + QString(")."),
QMessageBox::Ok); QMessageBox::Ok);
dfilter_error_free(df_err);
if (!name_param) { if (!name_param) {
// go back to the selection dialogue only if the file // go back to the selection dialogue only if the file
// was selected from this dialogue // was selected from this dialogue

View File

@ -110,7 +110,7 @@ rlc_lte_tap_info *select_rlc_lte_session(capture_file *cf,
} }
/* No real filter yet */ /* No real filter yet */
if (!dfilter_compile("rlc-lte", &sfcode, err_msg)) { if (!dfilter_compile("rlc-lte", &sfcode, NULL)) {
return NULL; return NULL;
} }

View File

@ -256,7 +256,7 @@ select_tcpip_session(capture_file *cf)
epan_dissect_t edt; epan_dissect_t edt;
dfilter_t *sfcode; dfilter_t *sfcode;
guint32 th_stream; guint32 th_stream;
gchar *err_msg; df_error_t *df_err;
GString *error_string; GString *error_string;
th_t th = {0, {NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL}}; th_t th = {0, {NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL}};
@ -265,9 +265,9 @@ select_tcpip_session(capture_file *cf)
} }
/* no real filter yet */ /* no real filter yet */
if (!dfilter_compile("tcp", &sfcode, &err_msg)) { if (!dfilter_compile("tcp", &sfcode, &df_err)) {
simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "%s", err_msg); simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "%s", df_err->msg);
g_free(err_msg); dfilter_error_free(df_err);
return G_MAXUINT32; return G_MAXUINT32;
} }