If "!=" or "ne" are used in a display filter, warn the user that the results

may be unexpected.

svn path=/trunk/; revision=24232
This commit is contained in:
Gerald Combs 2008-01-31 19:50:38 +00:00
parent f3747bf637
commit 9703c2bb75
10 changed files with 173 additions and 39 deletions

View File

@ -39,6 +39,7 @@ struct _dfilter_t {
gboolean *attempted_load;
int *interesting_fields;
int num_interesting_fields;
GPtrArray *deprecated;
};
typedef struct {

View File

@ -88,10 +88,10 @@ dfilter_init(void)
/* Trace parser */
DfilterTrace(stdout, "lemon> ");
#endif
/* Initialize the syntax-tree sub-sub-system */
sttype_init();
dfilter_macro_init();
}
@ -115,6 +115,7 @@ dfilter_new(void)
df = g_new(dfilter_t, 1);
df->insns = NULL;
df->deprecated = NULL;
return df;
}
@ -141,7 +142,7 @@ dfilter_free(dfilter_t *df)
if (!df)
return;
if (df->insns) {
free_insns(df->insns);
}
@ -152,7 +153,7 @@ dfilter_free(dfilter_t *df)
if (df->interesting_fields) {
g_free(df->interesting_fields);
}
/* clear registers */
for (i = 0; i < df->max_registers; i++) {
if (df->registers[i]) {
@ -208,7 +209,7 @@ dfwork_free(dfwork_t *dfw)
if (dfw->consts) {
free_insns(dfw->consts);
}
g_free(dfw);
}
@ -219,13 +220,16 @@ dfilter_compile(const gchar *text, dfilter_t **dfp)
dfilter_t *dfilter;
dfwork_t *dfw;
gboolean failure = FALSE;
char *depr_test;
guint i;
GPtrArray *deprecated = g_ptr_array_new();
dfilter_error_msg = NULL;
if ( !( text = dfilter_macro_apply(text, 0, &dfilter_error_msg) ) ) {
return FALSE;
}
dfw = dfwork_new();
df_scanner_text(text);
@ -245,6 +249,22 @@ dfilter_compile(const gchar *text, dfilter_t **dfp)
break;
}
/* See if the node is deprecated */
depr_test = stnode_deprecated(df_lval);
if (depr_test) {
for (i = 0; i < deprecated->len; i++) {
if (strcasecmp(depr_test, g_ptr_array_index(deprecated, i)) == 0) {
/* It's already in our list */
depr_test = NULL;
}
}
}
if (depr_test) {
g_ptr_array_add(deprecated, depr_test);
}
/* Give the token to the parser */
Dfilter(ParserObj, token, df_lval, dfw);
/* We've used the stnode_t, so we don't want to free it */
@ -254,6 +274,7 @@ dfilter_compile(const gchar *text, dfilter_t **dfp)
failure = TRUE;
break;
}
} /* while (1) */
/* If we created an stnode_t but didn't use it, free it; the
@ -285,6 +306,7 @@ dfilter_compile(const gchar *text, dfilter_t **dfp)
* it and set *dfp to NULL */
if (dfw->st_root == NULL) {
*dfp = NULL;
g_ptr_array_free(deprecated, TRUE);
}
else {
@ -314,6 +336,9 @@ dfilter_compile(const gchar *text, dfilter_t **dfp)
/* Initialize constants */
dfvm_init_const(dfilter);
/* Add any deprecated items */
dfilter->deprecated = deprecated;
/* And give it to the user. */
*dfp = dfilter;
}
@ -325,6 +350,7 @@ FAILURE:
if (dfw) {
dfwork_free(dfw);
}
g_ptr_array_free(deprecated, TRUE);
dfilter_fail("Unable to parse filter string \"%s\".", text);
*dfp = NULL;
return FALSE;
@ -355,9 +381,28 @@ dfilter_prime_proto_tree(const dfilter_t *df, proto_tree *tree)
}
}
GPtrArray *
dfilter_deprecated_tokens(dfilter_t *df) {
if (df->deprecated && df->deprecated->len > 0) {
return df->deprecated;
}
return NULL;
}
void
dfilter_dump(dfilter_t *df)
{
guint i;
gchar *sep = "";
dfvm_dump(stdout, df->insns);
if (df->deprecated && df->deprecated->len) {
printf("\nDeprecated tokens: ");
for (i = 0; i < df->deprecated->len; i++) {
printf("%s\"%s\"", sep, (char *) g_ptr_array_index(df->deprecated, i));
sep = ", ";
}
printf("\n");
}
}

View File

@ -65,7 +65,7 @@ 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
* otherwise it points to a displayable error message. With MSVC and a
* libwireshark.dll, we need a special declaration.
*/
@ -84,6 +84,9 @@ dfilter_apply(dfilter_t *df, proto_tree *tree);
void
dfilter_prime_proto_tree(const dfilter_t *df, proto_tree *tree);
GPtrArray *
dfilter_deprecated_tokens(dfilter_t *df);
/* Print bytecode of dfilter to stdout */
void
dfilter_dump(dfilter_t *df);

View File

@ -98,7 +98,7 @@ dfw_append_read_tree(dfwork_t *dfw, header_field_info *hfinfo)
insn->arg1 = val1;
insn->arg2 = val2;
dfw_append_insn(dfw, insn);
if (added_new_hfinfo) {
while (hfinfo) {
/* Record the FIELD_ID in hash of interesting fields. */
@ -186,7 +186,7 @@ dfw_append_function(dfwork_t *dfw, stnode_t *node, dfvm_value_t **p_jmp)
/* Create the new DFVM instruction */
insn = dfvm_insn_new(CALL_FUNCTION);
val1 = dfvm_value_new(FUNCTION_DEF);
val1->value.funcdef = sttype_function_funcdef(node);
insn->arg1 = val1;
@ -241,7 +241,7 @@ dfw_append_function(dfwork_t *dfw, stnode_t *node, dfvm_value_t **p_jmp)
dfw_append_insn(dfw, insn);
g_free(jmps);
return val2->value.numeric;
}
@ -450,7 +450,7 @@ dfw_gencode(dfwork_t *dfw)
int id, id1, length;
dfvm_insn_t *insn, *insn1, *prev;
dfvm_value_t *arg1;
dfw->insns = g_ptr_array_new();
dfw->consts = g_ptr_array_new();
dfw->loaded_fields = g_hash_table_new(g_direct_hash, g_direct_equal);
@ -467,17 +467,17 @@ dfw_gencode(dfwork_t *dfw)
if (insn->op == IF_TRUE_GOTO || insn->op == IF_FALSE_GOTO) {
dfvm_opcode_t revert = (insn->op == IF_FALSE_GOTO)?IF_TRUE_GOTO:IF_FALSE_GOTO;
id1 = arg1->value.numeric;
do {
do {
insn1 = g_ptr_array_index(dfw->insns, id1);
if (insn1->op == revert) {
/* this one is always false and the branch is not taken*/
id1 = id1 +1;
continue;
}
else if (insn1->op == READ_TREE && prev && prev->op == READ_TREE &&
else if (insn1->op == READ_TREE && prev && prev->op == READ_TREE &&
prev->arg2->value.numeric == insn1->arg2->value.numeric) {
/* hack if it's the same register it's the same field
* and it returns the same value
/* hack if it's the same register it's the same field
* and it returns the same value
*/
id1 = id1 +1;
continue;
@ -508,26 +508,26 @@ dfw_gencode(dfwork_t *dfw)
length = dfw->consts->len;
for (id = 0; id < length; id++) {
insn = g_ptr_array_index(dfw->consts, id);
if (insn->arg2 && insn->arg2->type == REGISTER && (int)insn->arg2->value.numeric < 0 )
if (insn->arg2 && insn->arg2->type == REGISTER && (int)insn->arg2->value.numeric < 0 )
insn->arg2->value.numeric = dfw->first_constant - insn->arg2->value.numeric -1;
}
length = dfw->insns->len;
for (id = 0; id < length; id++) {
insn = g_ptr_array_index(dfw->insns, id);
if (insn->arg1 && insn->arg1->type == REGISTER && (int)insn->arg1->value.numeric < 0 )
if (insn->arg1 && insn->arg1->type == REGISTER && (int)insn->arg1->value.numeric < 0 )
insn->arg1->value.numeric = dfw->first_constant - insn->arg1->value.numeric -1;
if (insn->arg2 && insn->arg2->type == REGISTER && (int)insn->arg2->value.numeric < 0 )
if (insn->arg2 && insn->arg2->type == REGISTER && (int)insn->arg2->value.numeric < 0 )
insn->arg2->value.numeric = dfw->first_constant - insn->arg2->value.numeric -1;
if (insn->arg3 && insn->arg3->type == REGISTER && (int)insn->arg3->value.numeric < 0 )
if (insn->arg3 && insn->arg3->type == REGISTER && (int)insn->arg3->value.numeric < 0 )
insn->arg3->value.numeric = dfw->first_constant - insn->arg3->value.numeric -1;
if (insn->arg4 && insn->arg4->type == REGISTER && (int)insn->arg4->value.numeric < 0 )
if (insn->arg4 && insn->arg4->type == REGISTER && (int)insn->arg4->value.numeric < 0 )
insn->arg4->value.numeric = dfw->first_constant - insn->arg4->value.numeric -1;
}
}

View File

@ -26,17 +26,17 @@
* Wireshark - Network traffic analyzer
* By Gerald Combs <gerald@wireshark.org>
* Copyright 2001 Gerald Combs
*
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
@ -83,6 +83,7 @@ static int set_lval_int(int token, char *s);
static int simple(int token);
static gboolean str_to_gint32(char *s, gint32* pint);
GString* quoted_string = NULL;
static void mark_lval_deprecated(const char *s);
%}
@ -102,8 +103,14 @@ GString* quoted_string = NULL;
"==" return simple(TOKEN_TEST_EQ);
"eq" return simple(TOKEN_TEST_EQ);
"!=" return simple(TOKEN_TEST_NE);
"ne" return simple(TOKEN_TEST_NE);
"!=" {
mark_lval_deprecated("!=");
return simple(TOKEN_TEST_NE);
}
"ne" {
mark_lval_deprecated("ne");
return simple(TOKEN_TEST_NE);
}
">" return simple(TOKEN_TEST_GT);
"gt" return simple(TOKEN_TEST_GT);
">=" return simple(TOKEN_TEST_GE);
@ -351,7 +358,7 @@ set_lval_int(int token, char *s)
if (!str_to_gint32(s, &val)) {
return SCAN_FAILED;
}
}
switch (token) {
case TOKEN_INTEGER:
@ -417,4 +424,10 @@ str_to_gint32(char *s, gint32* pint)
return TRUE;
}
static void
mark_lval_deprecated(const char *s)
{
df_lval->deprecated_token = s;
}
#include <lemonflex-tail.inc>

View File

@ -92,6 +92,7 @@ stnode_new(sttype_id_t type_id, gpointer data)
node = g_new(stnode_t, 1);
node->magic = STNODE_MAGIC;
node->deprecated_token = NULL;
if (type_id == STTYPE_UNINITIALIZED) {
node->type = NULL;
@ -188,3 +189,12 @@ stnode_value(stnode_t *node)
assert_magic(node, STNODE_MAGIC);
return node->value;
}
char *
stnode_deprecated(stnode_t *node)
{
if (!node) {
return NULL;
}
return node->deprecated_token;
}

View File

@ -60,6 +60,7 @@ typedef struct {
* set aside to time to do so. */
gpointer data;
gint32 value;
char *deprecated_token;
} stnode_t;
/* These are the sttype_t registration function prototypes. */
@ -103,6 +104,9 @@ stnode_data(stnode_t *node);
gint32
stnode_value(stnode_t *node);
char *
stnode_deprecated(stnode_t *node);
#define assert_magic(obj, mnum) \
g_assert((obj)); \
if ((obj)->magic != (mnum)) { \

View File

@ -1440,7 +1440,7 @@ filter_add_expr_bt_cb(GtkWidget *w _U_, gpointer main_w_arg)
* through file->open, make the latest dialog modal also so that it
* takes over "control" from the other modal dialogs. Also set
* the transient property of the new dialog so the user doesn't try
* to interact with the previous window when they can't.
* to interact with the previous window when they can't.
* XXX: containing widget might be the Filter Toolbar */
if ( GTK_IS_WINDOW(main_w) && gtk_window_get_modal(GTK_WINDOW(main_w))) {
@ -1482,6 +1482,13 @@ colorize_filter_te_as_invalid(GtkWidget *w)
color_filter_te(w, 0xFFFF, 0xAFFF, 0xAFFF);
}
void
colorize_filter_te_as_deprecated(GtkWidget *w)
{
/* light yellow */
color_filter_te(w, 0xFFFF, 0xFFFF, 0xAFFF);
}
void
colorize_filter_te_as_valid(GtkWidget *w)
{
@ -1494,19 +1501,39 @@ filter_te_syntax_check_cb(GtkWidget *w)
{
const gchar *strval;
dfilter_t *dfp;
GPtrArray *depr = NULL;
gchar *msg;
statusbar_pop_filter_msg();
strval = gtk_entry_get_text(GTK_ENTRY(w));
/* colorize filter string entry */
if (strval && dfilter_compile(strval, &dfp)) {
if (dfp != NULL)
dfilter_free(dfp);
if (strlen(strval) == 0)
if (dfp != NULL) {
depr = dfilter_deprecated_tokens(dfp);
dfilter_free(dfp);
}
if (strlen(strval) == 0) {
colorize_filter_te_as_empty(w);
else
} 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);
/*
* We're being lazy and only printing the first "problem" token.
* Would it be better to print all of them?
*/
msg = g_strdup_printf("\"%s\" may have unexpected results.",
(char *) g_ptr_array_index(depr, 0));
statusbar_push_filter_msg(msg);
g_free(msg);
} else {
colorize_filter_te_as_valid(w);
} else
}
} else {
colorize_filter_te_as_invalid(w);
statusbar_push_filter_msg("Invalid filter");
}
}

View File

@ -225,7 +225,7 @@ static GtkWidget *info_bar;
static GtkWidget *packets_bar = NULL;
static GtkWidget *profile_bar = NULL;
static GtkWidget *welcome_pane;
static guint main_ctx, file_ctx, help_ctx;
static guint main_ctx, file_ctx, help_ctx, filter_ctx;
static guint packets_ctx;
static guint profile_ctx;
static gchar *packets_str = NULL;
@ -1008,6 +1008,24 @@ statusbar_pop_field_msg(void)
gtk_statusbar_pop(GTK_STATUSBAR(info_bar), help_ctx);
}
/*
* Push a message referring to the current filter onto the statusbar.
*/
void
statusbar_push_filter_msg(const gchar *msg)
{
gtk_statusbar_push(GTK_STATUSBAR(info_bar), filter_ctx, msg);
}
/*
* Pop a message referring to the current filter off the statusbar.
*/
void
statusbar_pop_filter_msg(void)
{
gtk_statusbar_pop(GTK_STATUSBAR(info_bar), filter_ctx);
}
/*
* update the packets statusbar to the current values
*/
@ -3358,6 +3376,7 @@ static GtkWidget *info_bar_new(void)
main_ctx = gtk_statusbar_get_context_id(GTK_STATUSBAR(info_bar), "main");
file_ctx = gtk_statusbar_get_context_id(GTK_STATUSBAR(info_bar), "file");
help_ctx = gtk_statusbar_get_context_id(GTK_STATUSBAR(info_bar), "help");
filter_ctx = gtk_statusbar_get_context_id(GTK_STATUSBAR(info_bar), "filter");
#if GTK_MAJOR_VERSION >= 2
gtk_statusbar_set_has_resize_grip(GTK_STATUSBAR(info_bar), FALSE);
#endif

View File

@ -129,14 +129,14 @@ typedef enum {
/** "bitwise or" this with MATCH_SELECTED_E value for copy to clipboard instead of prepare only */
#define MATCH_SELECTED_COPY_ONLY 0x200
/** User highlited item in details window and then right clicked and selected the copy option
/** User highlited item in details window and then right clicked and selected the copy option
*
* @param widget parent widget
* @param data parent widget
*/
extern void copy_selected_plist_cb(GtkWidget *w _U_, gpointer data);
/** User requested one of "Apply as Filter" or "Prepare a Filter" functions
/** User requested one of "Apply as Filter" or "Prepare a Filter" functions
* by menu or context menu of protocol tree.
*
* @param widget parent widget
@ -289,7 +289,7 @@ extern gboolean dfilter_combo_add_recent(gchar *dftext);
/** Empty out the combobox entry field */
extern void dfilter_combo_add_empty(void);
/** Write all non empty display filters (until maximum count)
/** Write all non empty display filters (until maximum count)
* of the combo box GList to the user's recent file.
*
* @param rf the recent file
@ -308,7 +308,7 @@ extern void main_widgets_rearrange(void);
/** Show or hide the main window widgets, user changed it's preferences. */
extern void main_widgets_show_or_hide(void);
/** Apply a new filter string.
/** Apply a new filter string.
* Call cf_filter_packets() and add this filter string to the recent filter list.
*
* @param cf the capture file
@ -349,4 +349,16 @@ extern void change_configuration_profile(const gchar *profile_name);
extern GtkWidget *pkt_scrollw;
/** Push a message referring to the current filter onto the statusbar.
*
* @param msg The message
*/
void
statusbar_push_filter_msg(const gchar *msg);
/** Pop a message referring to the current filter off the statusbar.
*/
void
statusbar_pop_filter_msg(void);
#endif /* __MAIN_H__ */