summaryrefslogtreecommitdiff
path: root/epan/reassemble.c
diff options
context:
space:
mode:
authorBill Meier <wmeier@newsguy.com>2012-08-09 02:06:53 +0000
committerBill Meier <wmeier@newsguy.com>2012-08-09 02:06:53 +0000
commit3c7d32017fe57395b13fd854993db27c7293449c (patch)
tree2de8d949c9195b57beae34e709db4b88844b076b /epan/reassemble.c
parentbec794d51ea9390c112f1470a88c8a947b8a6cfa (diff)
downloadwireshark-3c7d32017fe57395b13fd854993db27c7293449c.tar.gz
From Jakub Zawadzki: Fix for memory leak in reassemble.c
Bug #4141 https://bugs.wireshark.org/bugzilla/show_bug.cgi?id=4141#c10 svn path=/trunk/; revision=44371
Diffstat (limited to 'epan/reassemble.c')
-rw-r--r--epan/reassemble.c46
1 files changed, 33 insertions, 13 deletions
diff --git a/epan/reassemble.c b/epan/reassemble.c
index a0b9c136b8..2090711546 100644
--- a/epan/reassemble.c
+++ b/epan/reassemble.c
@@ -231,28 +231,32 @@ static fragment_data *new_head(const guint32 flags)
return fd_head;
}
+#define FD_VISITED_FREE 0xffff
+
/*
* For a reassembled-packet hash table entry, free the fragment data
* to which the value refers.
*/
static gboolean
free_all_reassembled_fragments(gpointer key_arg _U_, gpointer value,
- gpointer user_data _U_)
+ gpointer user_data)
{
+ GPtrArray *allocated_fragments = (GPtrArray *) user_data;
fragment_data *fd_head;
for (fd_head = value; fd_head != NULL; fd_head = fd_head->next) {
- if(fd_head->data && !(fd_head->flags&FD_NOT_MALLOCED)) {
- g_free(fd_head->data);
-
- /*
- * A reassembled packet is inserted into the
- * hash table once for every frame that made
- * up the reassembled packet; clear the data
- * pointer so that we only free the data the
- * first time we see it.
- */
- fd_head->data = NULL;
+ /*
+ * A reassembled packet is inserted into the
+ * hash table once for every frame that made
+ * up the reassembled packet; add first seen
+ * fragments to array and later free them in
+ * free_fragments()
+ */
+ if (fd_head->flags != FD_VISITED_FREE) {
+ if (fd_head->flags & FD_NOT_MALLOCED)
+ fd_head->data = NULL;
+ g_ptr_array_add(allocated_fragments, fd_head);
+ fd_head->flags = FD_VISITED_FREE;
}
}
@@ -344,6 +348,15 @@ dcerpc_fragment_table_init(GHashTable **fragment_table)
}
}
+static void
+free_fragments(gpointer data, gpointer user_data _U_)
+{
+ fragment_data *fd_head = (fragment_data *) data;
+
+ g_free(fd_head->data);
+ g_slice_free(fragment_data, fd_head);
+}
+
/*
* Initialize a reassembled-packet table.
*/
@@ -351,14 +364,21 @@ void
reassembled_table_init(GHashTable **reassembled_table)
{
if (*reassembled_table != NULL) {
+ GPtrArray *allocated_fragments;
+
/*
* The reassembled-packet hash table exists.
*
* Remove all entries and free reassembled packet
* data for each entry.
*/
+
+ allocated_fragments = g_ptr_array_new();
g_hash_table_foreach_remove(*reassembled_table,
- free_all_reassembled_fragments, NULL);
+ free_all_reassembled_fragments, allocated_fragments);
+
+ g_ptr_array_foreach(allocated_fragments, free_fragments, NULL);
+ g_ptr_array_free(allocated_fragments, TRUE);
} else {
/* The fragment table does not exist. Create it */
*reassembled_table = g_hash_table_new(reassembled_hash,