radius: fix memleaks of value_string
authorPeter Wu <peter@lekensteyn.nl>
Tue, 28 Feb 2017 16:05:10 +0000 (17:05 +0100)
committerMichael Mann <mmann78@netscape.net>
Tue, 28 Feb 2017 19:04:42 +0000 (19:04 +0000)
The value_string was taken from the GArray and added to
radius_attr_info_t, but these were not properly freed.

Change-Id: I8de2b84760887c41229a57881ff46cedcef1d22f
Reviewed-on: https://code.wireshark.org/review/20311
Reviewed-by: Michael Mann <mmann78@netscape.net>
epan/dissectors/packet-radius.c
epan/radius_dict.l

index c57aeae894f181b04e189ba58d56853990d11dc6..d396d5c38cd06ae8d643897029d35e431085d26b 100644 (file)
@@ -2141,10 +2141,18 @@ void
 free_radius_attr_info(gpointer data)
 {
        radius_attr_info_t* attr = (radius_attr_info_t*)data;
+       value_string *vs = (value_string *)attr->vs;
 
        g_free(attr->name);
-       if (attr->tlvs_by_id)
+       if (attr->tlvs_by_id) {
                g_hash_table_destroy(attr->tlvs_by_id);
+       }
+       if (vs) {
+               for (; vs->strptr; vs++) {
+                       g_free((gpointer)vs->strptr);
+               }
+               g_free((gpointer)attr->vs);
+       }
 
        g_free(attr);
 }
index fd4771e0b6bb3bbe415815e72e94e28638b174be..2b8b9bfd31f1e3c3cf3a7be3189278e79c167940 100644 (file)
@@ -603,8 +603,9 @@ void add_value(Radius_scanner_state_t* state, const gchar* attrib_name, const gc
        GArray* a = (GArray*)g_hash_table_lookup(state->value_strings,attrib_name);
 
        if (! a) {
-               a = g_array_new(TRUE,TRUE,sizeof(value_string));
-               g_hash_table_insert(state->value_strings,g_strdup(attrib_name),a);
+               /* Ensure that the array is zero terminated. */
+               a = g_array_new(TRUE, TRUE, sizeof(value_string));
+               g_hash_table_insert(state->value_strings, g_strdup(attrib_name), a);
        }
 
        v.value = value;
@@ -625,8 +626,8 @@ static void setup_tlvs(gpointer k _U_, gpointer v, gpointer p) {
 
        if (g_hash_table_lookup_extended(state->value_strings, s->name, &key, &vs.p)) {
                s->vs = (value_string*)(void *)vs.a->data;
+               g_hash_table_steal(state->value_strings, key);
                g_array_free(vs.a, FALSE);
-               g_hash_table_remove(state->value_strings, key);
                g_free(key);
        }
 }
@@ -641,10 +642,10 @@ static void setup_attrs(gpointer k _U_, gpointer v, gpointer p) {
                gpointer p;
        } vs;
 
-       if (g_hash_table_lookup_extended(state->value_strings,a->name,&key,&vs.p) ) {
+       if (g_hash_table_lookup_extended(state->value_strings, a->name, &key, &vs.p) ) {
                a->vs = (value_string*)(void *)vs.a->data;
-               g_array_free(vs.a,FALSE);
-               g_hash_table_remove(state->value_strings,key);
+               g_hash_table_steal(state->value_strings, key);
+               g_array_free(vs.a, FALSE);
                g_free(key);
        }
 
@@ -659,17 +660,14 @@ static void setup_vendors(gpointer k _U_, gpointer v, gpointer p) {
        g_hash_table_foreach(vnd->attrs_by_id,setup_attrs,p);
 }
 
-static gboolean destroy_value_strings(gpointer k, gpointer v, gpointer p _U_) {
+static void destroy_value_strings(gpointer v) {
        value_string* vs = (value_string*)(void *)(((GArray*)v)->data);
 
-       g_free(k);
-
        for (;vs->strptr;vs++) {
                g_free((void*)vs->strptr);
        }
 
        g_array_free((GArray*)v,TRUE);
-       return TRUE;
 }
 
 gboolean radius_load_dictionary (radius_dictionary_t* d, gchar* dir, const gchar* filename, gchar** err_str) {
@@ -719,7 +717,7 @@ gboolean radius_load_dictionary (radius_dictionary_t* d, gchar* dir, const gchar
                return FALSE;
        }
 
-       state.value_strings = g_hash_table_new(g_str_hash,g_str_equal);
+       state.value_strings = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, destroy_value_strings);
 
        if (Radius_lex_init(&scanner) != 0) {
                g_string_append_printf(state.error, "Can't initialize scanner: %s",
@@ -750,7 +748,7 @@ gboolean radius_load_dictionary (radius_dictionary_t* d, gchar* dir, const gchar
 
        g_hash_table_foreach(state.dict->attrs_by_id,setup_attrs,&state);
        g_hash_table_foreach(state.dict->vendors_by_id,setup_vendors,&state);
-       g_hash_table_foreach_remove(state.value_strings,destroy_value_strings,NULL);
+       g_hash_table_destroy(state.value_strings);
 
        if (state.error->len > 0) {
                *err_str = g_string_free(state.error,FALSE);