The dfilter yacc grammar now keeps track of every GNode that it allocates.
authorgram <gram@f5534014-38df-0310-8fa8-9805f1628bb7>
Thu, 26 Aug 1999 06:20:50 +0000 (06:20 +0000)
committergram <gram@f5534014-38df-0310-8fa8-9805f1628bb7>
Thu, 26 Aug 1999 06:20:50 +0000 (06:20 +0000)
After a bad parse, instead of leaking this memory, the memory used for
those GNodes is now freed.

Added some memory-freeing "cleanup" routines for the dfilter and proto_tree
modules, which are called right before ethereal exits. Maybe once we get
a complete set of cleanup routines, we'll be able to better check if
memory is leaking.

git-svn-id: http://anonsvn.wireshark.org/wireshark/trunk@582 f5534014-38df-0310-8fa8-9805f1628bb7

dfilter-grammar.y
dfilter-int.h
dfilter.c
dfilter.h
ethereal.c
proto.c
proto.h

index c8ab1c54b8d3e2ff45bd76f7b844cd3eb6e8edd3..d692267fcc396ba8614e398a9f795372dcf255a5 100644 (file)
@@ -3,7 +3,7 @@
 /* dfilter-grammar.y
  * Parser for display filters
  *
- * $Id: dfilter-grammar.y,v 1.14 1999/08/20 21:19:27 gram Exp $
+ * $Id: dfilter-grammar.y,v 1.15 1999/08/26 06:20:48 gram Exp $
  *
  * Ethereal - Network traffic analyzer
  * By Gerald Combs <gerald@zing.org>
@@ -98,6 +98,13 @@ static int ether_str_to_guint8_array(const char *s, guint8 *mac);
  */
 dfilter *global_df = NULL;;
 
+/* list of GNodes allocated during parsing. If the parsing fails, we'll
+ * use this list to free all the GNodes. If the parsing succeeds, we'll
+ * just clear this list since dfilter_clear_filter() will take care of
+ * freeing the GNodes when they're no longer needed.
+ */
+GSList *gnode_slist = NULL;
+
 %}
 
 %union {
@@ -363,6 +370,7 @@ dfilter_mknode_join(GNode *n1, enum node_type ntype, int operand, GNode *n2)
        g_node_append(gnode_root, n1);
        g_node_append(gnode_root, n2);
 
+       gnode_slist = g_slist_append(gnode_slist, gnode_root);
        return gnode_root;
 }
 
@@ -382,6 +390,7 @@ dfilter_mknode_unary(int operand, GNode *n2)
        gnode_root = g_node_new(node_root);
        g_node_append(gnode_root, n2);
 
+       gnode_slist = g_slist_append(gnode_slist, gnode_root);
        return gnode_root;
 }
 
@@ -400,6 +409,7 @@ dfilter_mknode_numeric_variable(gint id)
        node->value.variable = id;
        gnode = g_node_new(node);
 
+       gnode_slist = g_slist_append(gnode_slist, gnode);
        return gnode;
 }
 
@@ -417,6 +427,7 @@ dfilter_mknode_ether_variable(gint id)
        node->value.variable = id;
        gnode = g_node_new(node);
 
+       gnode_slist = g_slist_append(gnode_slist, gnode);
        return gnode;
 }
 
@@ -434,6 +445,7 @@ dfilter_mknode_ipxnet_variable(gint id)
        node->value.variable = id;
        gnode = g_node_new(node);
 
+       gnode_slist = g_slist_append(gnode_slist, gnode);
        return gnode;
 }
 
@@ -451,6 +463,7 @@ dfilter_mknode_ipv4_variable(gint id)
        node->value.variable = id;
        gnode = g_node_new(node);
 
+       gnode_slist = g_slist_append(gnode_slist, gnode);
        return gnode;
 }
 
@@ -470,6 +483,7 @@ dfilter_mknode_bytes_variable(gint id, gint offset, guint length)
        node->length = length;
        gnode = g_node_new(node);
 
+       gnode_slist = g_slist_append(gnode_slist, gnode);
        return gnode;
 }
 
@@ -487,6 +501,7 @@ dfilter_mknode_boolean_variable(gint id)
        node->value.variable = id;
        gnode = g_node_new(node);
 
+       gnode_slist = g_slist_append(gnode_slist, gnode);
        return gnode;
 }
 
@@ -504,6 +519,7 @@ dfilter_mknode_numeric_value(guint32 val)
        node->value.numeric = val;
        gnode = g_node_new(node);
 
+       gnode_slist = g_slist_append(gnode_slist, gnode);
        return gnode;
 }
 
@@ -531,6 +547,7 @@ dfilter_mknode_ether_value(gchar *byte_string)
        }
 
        gnode = g_node_new(node);
+       gnode_slist = g_slist_append(gnode_slist, gnode);
        return gnode;
 }
 
@@ -548,6 +565,7 @@ dfilter_mknode_ipxnet_value(guint32 ipx_net_val)
        node->value.numeric = ipx_net_val;
        gnode = g_node_new(node);
 
+       gnode_slist = g_slist_append(gnode_slist, gnode);
        return gnode;
 }
 
@@ -566,6 +584,7 @@ dfilter_mknode_ipv4_value(char *host)
        node->value.numeric = htonl(node->value.numeric);
        gnode = g_node_new(node);
 
+       gnode_slist = g_slist_append(gnode_slist, gnode);
        return gnode;
 }
 
@@ -585,6 +604,7 @@ dfilter_mknode_bytes_value(GByteArray *barray)
        node->length = barray->len;
        gnode = g_node_new(node);
 
+       gnode_slist = g_slist_append(gnode_slist, gnode);
        return gnode;
 }
 
@@ -602,6 +622,7 @@ dfilter_mknode_boolean_value(gint truth_value)
        node->value.boolean = truth_value == TOK_TRUE ? TRUE : FALSE;
        gnode = g_node_new(node);
 
+       gnode_slist = g_slist_append(gnode_slist, gnode);
        return gnode;
 }
 
@@ -631,6 +652,7 @@ dfilter_mknode_existence(gint id)
        node->value.variable = id;
        gnode = g_node_new(node);
 
+       gnode_slist = g_slist_append(gnode_slist, gnode);
        return gnode;
 }
 
index 689ff4ebcf5cfd5d08980653784c92801827faab..deb785b5146483ab2f1326c6bcc27bfee0b74845 100644 (file)
@@ -2,7 +2,7 @@
  * Definitions for routines common to multiple modules in the display
  * filter code, but not used outside that code.
  *
- * $Id: dfilter-int.h,v 1.2 1999/08/13 23:47:40 gram Exp $
+ * $Id: dfilter-int.h,v 1.3 1999/08/26 06:20:48 gram Exp $
  *
  * Ethereal - Network traffic analyzer
  * By Gerald Combs <gerald@zing.org>
@@ -34,6 +34,7 @@ void dfilter_scanner_cleanup(void);
 
 /* in dfilter-grammar.y */
 extern dfilter *global_df;
+extern GSList *gnode_slist;
 
 /* Here we provide interfaces to make our scanner act and look like lex */
 int yylex(void);
index fe3727b3301bba4297a1f6b515b6fb1f04f5d3ae..a271a5c1b172da986e7d725c7a09361fb22311be 100644 (file)
--- a/dfilter.c
+++ b/dfilter.c
@@ -1,7 +1,7 @@
 /* dfilter.c
  * Routines for display filters
  *
- * $Id: dfilter.c,v 1.15 1999/08/25 22:54:17 gram Exp $
+ * $Id: dfilter.c,v 1.16 1999/08/26 06:20:48 gram Exp $
  *
  * Ethereal - Network traffic analyzer
  * By Gerald Combs <gerald@zing.org>
@@ -94,6 +94,8 @@ static GArray* get_values_from_ptree(dfilter_node *dnode, proto_tree *ptree, con
 static GArray* get_values_from_dfilter(dfilter_node *dnode, GNode *gnode);
 static gboolean check_existence_in_ptree(dfilter_node *dnode, proto_tree *ptree);
 static void clear_byte_array(gpointer data, gpointer user_data);
+static void unlink_gnode_children(gpointer gnode_ptr, gpointer user_data);
+static void destroy_gnode(gpointer gnode_ptr, gpointer user_data);
 
 /* this is not so pretty. I need my own g_array "function" (macro) to
  * retreive the pointer to the data stored in an array cell. I need this
@@ -120,7 +122,13 @@ dfilter_init(void)
                }
        }
 }
-/* XXX - I should eventually g_tree_destroy(dfilter_tokens), when ethereal shuts down */
+
+void
+dfilter_cleanup(void)
+{
+       if (dfilter_tokens)
+               g_tree_destroy(dfilter_tokens);
+}
 
 /* Compiles the textual representation of the display filter into a tree
  * of operations to perform. Can be called multiple times, compiling a new
@@ -146,7 +154,10 @@ dfilter_compile(dfilter *df, gchar *dfilter_text)
        /* tell the scanner to use this string as input */
        dfilter_scanner_text(df->dftext);
 
-       /* Assign global variable so yyparse knows which dfilter we're talking about */
+       /* Assign global variable so dfilter_parse knows which dfilter we're
+        * talking about. Reset the global error message. We don't have to set
+        * gnode_slist since it will always be NULL by the time we get here.
+        */
        global_df = df;
        dfilter_error_msg = NULL;
 
@@ -167,6 +178,12 @@ dfilter_compile(dfilter *df, gchar *dfilter_text)
                }
        }
 
+       /* Clear the list of allocated nodes */
+       if (gnode_slist) {
+               g_slist_free(gnode_slist);
+               gnode_slist = NULL;
+       }
+
        return retval;
 }
 
@@ -233,9 +250,6 @@ dfilter_destroy(dfilter *df)
 }
 
 
-
-
-
 static void
 clear_byte_array(gpointer data, gpointer user_data)
 {
@@ -244,15 +258,51 @@ clear_byte_array(gpointer data, gpointer user_data)
                g_byte_array_free(barray, TRUE);
 }
 
+/* Called when the yacc grammar finds a parsing error */
 void
 dfilter_error(char *s)
 {
-       /* Setting to NULL here is fine, since global_df is a copy of a pointer.
-           dfilter_clear_filter() will free the memory when called from the
-          next dfilter_compile() */
-       global_df->dftree = NULL;
+       /* The only data we have to worry about freeing is the
+        * data used by any GNodes that were allocated during
+        * parsing. The data in those Gnodes will be cleared
+        * later via df->node_memchunk. Use gnode_slist to
+        * clear the GNodes, and set global_df to NULL just
+        * to be tidy.
+        */
+       global_df = NULL;
+
+       /* I don't want to call g_node_destroy on each GNode ptr,
+        * since that function frees any children. That could
+        * mess me up later in the list if I try to free a GNode
+        * that has already been freed. So, I'll unlink the
+        * children firs,t then call g_node_destroy on each GNode ptr.
+        */
+       if (!gnode_slist)
+               return;
+
+       g_slist_foreach(gnode_slist, unlink_gnode_children, NULL);
+       g_slist_foreach(gnode_slist, destroy_gnode, NULL);
+
+       /* notice we don't clear gnode_slist itself. dfilter_compile()
+        * will take care of that.
+        */
+}
+
+static void
+unlink_gnode_children(gpointer gnode_ptr, gpointer user_data)
+{
+       if (gnode_ptr)
+               g_node_unlink((GNode*) gnode_ptr);
 }
 
+static void
+destroy_gnode(gpointer gnode_ptr, gpointer user_data)
+{
+       if (gnode_ptr)
+               g_node_destroy((GNode*) gnode_ptr);
+}
+
+
 /* lookup an abbreviation in our token tree, returing the ID #
  * If the abbreviation doesn't exit, returns 0 */
 int dfilter_lookup_token(char *abbrev)
index b4849cd376906df5a1880d2ef49768a6bd8fb9de..c42676061af55ca796ca016410de259dfbfdb738 100644 (file)
--- a/dfilter.h
+++ b/dfilter.h
@@ -1,7 +1,7 @@
 /* dfilter.h
  * Definitions for display filters
  *
- * $Id: dfilter.h,v 1.9 1999/08/20 20:37:46 gram Exp $
+ * $Id: dfilter.h,v 1.10 1999/08/26 06:20:49 gram Exp $
  *
  * Ethereal - Network traffic analyzer
  * By Gerald Combs <gerald@zing.org>
@@ -49,6 +49,9 @@ typedef struct {
 /* Initialization of the symbol table. Called once during program startup */
 void dfilter_init(void);
 
+/* Free the memory used by the symbol table. Called at program shutdown */
+void dfilter_cleanup(void);
+
 /* Allocate and initialize new dfilter struct. Returns pointer to new dfilter */
 dfilter* dfilter_new(void);
 
index 5fbbea695870d7ff779a056e2ee05f09640886c1..cf342c03d71b380bec61822a2c5227742efc1f5a 100644 (file)
@@ -1,6 +1,6 @@
 /* ethereal.c
  *
- * $Id: ethereal.c,v 1.107 1999/08/25 22:19:55 gram Exp $
+ * $Id: ethereal.c,v 1.108 1999/08/26 06:20:49 gram Exp $
  *
  * Ethereal - Network traffic analyzer
  * By Gerald Combs <gerald@zing.org>
@@ -1008,6 +1008,12 @@ ethereal_proto_init(void) {
   dfilter_init();
 }
 
+static void
+ethereal_proto_cleanup(void) {
+       proto_cleanup();
+       dfilter_cleanup();
+}
+
 static void 
 print_usage(void) {
 
@@ -1472,5 +1478,7 @@ main(int argc, char *argv[])
 
   gtk_main();
 
+  ethereal_proto_cleanup();
+
   exit(0);
 }
diff --git a/proto.c b/proto.c
index d185bf3943186365025ffd087083308eec4f6259..319c428d9a06748b2ed8814d56e74146a6e98717 100644 (file)
--- a/proto.c
+++ b/proto.c
@@ -1,7 +1,7 @@
 /* proto.c
  * Routines for protocol tree
  *
- * $Id: proto.c,v 1.16 1999/08/20 06:55:06 guy Exp $
+ * $Id: proto.c,v 1.17 1999/08/26 06:20:50 gram Exp $
  *
  * Ethereal - Network traffic analyzer
  * By Gerald Combs <gerald@zing.org>
@@ -167,7 +167,7 @@ proto_init(void)
        if (gmc_item_labels)
                g_mem_chunk_destroy(gmc_item_labels);
        if (gpa_hfinfo)
-               g_ptr_array_free(gpa_hfinfo, FALSE); /* ever needs to be TRUE?  */
+               g_ptr_array_free(gpa_hfinfo, FALSE);
 
        gmc_hfinfo = g_mem_chunk_new("gmc_hfinfo",
                sizeof(struct header_field_info), 50 * sizeof(struct 
@@ -246,6 +246,19 @@ proto_init(void)
                /* vals[] */    NULL );
 }
 
+void
+proto_cleanup(void)
+{
+       if (gmc_hfinfo)
+               g_mem_chunk_destroy(gmc_hfinfo);
+       if (gmc_field_info)
+               g_mem_chunk_destroy(gmc_field_info);
+       if (gmc_item_labels)
+               g_mem_chunk_destroy(gmc_item_labels);
+       if (gpa_hfinfo)
+               g_ptr_array_free(gpa_hfinfo, FALSE);
+}
+
 /* frees the resources that the dissection a proto_tree uses */
 void
 proto_tree_free(proto_tree *tree)
diff --git a/proto.h b/proto.h
index ef317aa17f63c4d6d4267f882415f2ddedd4c0d7..6383cae9143e0d4d03c9859d3651d2862d97b82b 100644 (file)
--- a/proto.h
+++ b/proto.h
@@ -1,7 +1,7 @@
 /* proto.h
  * Definitions for protocol display
  *
- * $Id: proto.h,v 1.6 1999/08/14 01:26:39 gram Exp $
+ * $Id: proto.h,v 1.7 1999/08/26 06:20:50 gram Exp $
  *
  * Ethereal - Network traffic analyzer
  * By Gerald Combs <gerald@zing.org>
@@ -118,7 +118,12 @@ typedef struct proto_tree_search_info {
        const guint8    *packet_data;
 } proto_tree_search_info;
 
+/* Sets up memory used by proto routines. Called at program startup */
 void proto_init(void);
+
+/* Frees memory used by proto routines. Called at program shutdown */
+void proto_cleanup(void);
+
 void proto_item_set_len(proto_item *ti, gint length);
 proto_tree* proto_tree_create_root(void);
 void proto_tree_free(proto_tree *tree);