From 5767118ec9098bf8eeae9c0f7860ed3a48477c79 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stig=20Bj=C3=B8rlykke?= Date: Wed, 30 May 2018 09:00:16 +0200 Subject: [PATCH] Free dynamic header fields on exit MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Put routine to free all dynamically registered header fields in the UAT reset callback to avoid ASAN report for memory leaks on exit. Handle duplicated entries without leaking memory. Call proto_free_deregistered_fields() in proto_cleanup() and move this after prefs_cleanup() to free the memory used in UATs. Change-Id: I96545177b5b23b9c20ad8e7751a0d5621c9ca10f Reviewed-on: https://code.wireshark.org/review/27907 Petri-Dish: Stig Bjørlykke Tested-by: Petri Dish Buildbot Reviewed-by: Peter Wu --- .../asn1/ldap/packet-ldap-template.c | 76 +++++++----- epan/dissectors/packet-http.c | 83 +++++++------ epan/dissectors/packet-imf.c | 80 ++++++++----- epan/dissectors/packet-ldap.c | 84 +++++++------ epan/dissectors/packet-lwm2mtlv.c | 66 ++++++++--- epan/dissectors/packet-sip.c | 96 ++++++++------- epan/dissectors/packet-udp-nm.c | 110 ++++++++++-------- epan/epan.c | 15 ++- epan/proto.c | 1 + 9 files changed, 377 insertions(+), 234 deletions(-) diff --git a/epan/dissectors/asn1/ldap/packet-ldap-template.c b/epan/dissectors/asn1/ldap/packet-ldap-template.c index be679ece64..9b9b9afdcf 100644 --- a/epan/dissectors/asn1/ldap/packet-ldap-template.c +++ b/epan/dissectors/asn1/ldap/packet-ldap-template.c @@ -451,10 +451,12 @@ typedef struct _attribute_type_t { gchar* attribute_desc; } attribute_type_t; -static attribute_type_t* attribute_types = NULL; -static guint num_attribute_types = 0; +static attribute_type_t* attribute_types; +static guint num_attribute_types; -static GHashTable* attribute_types_hash = NULL; +static GHashTable* attribute_types_hash; +static hf_register_info* dynamic_hf; +static guint dynamic_hf_size; static gboolean attribute_types_update_cb(void *r, char **err) @@ -531,51 +533,67 @@ get_hf_for_header(char* attribute_type) * */ static void -attribute_types_initialize_cb(void) +deregister_attribute_types(void) { - static hf_register_info* hf; - gint* hf_id; - guint i; - gchar* attribute_type; - - if (attribute_types_hash && hf) { - guint hf_size = g_hash_table_size (attribute_types_hash); + if (dynamic_hf) { /* Deregister all fields */ - for (i = 0; i < hf_size; i++) { - proto_deregister_field (proto_ldap, *(hf[i].p_id)); - g_free (hf[i].p_id); + for (guint i = 0; i < dynamic_hf_size; i++) { + proto_deregister_field (proto_ldap, *(dynamic_hf[i].p_id)); + g_free (dynamic_hf[i].p_id); } + + proto_add_deregistered_data (dynamic_hf); + dynamic_hf = NULL; + dynamic_hf_size = 0; + } + + if (attribute_types_hash) { g_hash_table_destroy (attribute_types_hash); - proto_add_deregistered_data (hf); attribute_types_hash = NULL; } +} + +static void +attribute_types_post_update_cb(void) +{ + gint* hf_id; + gchar* attribute_type; + + deregister_attribute_types(); if (num_attribute_types) { attribute_types_hash = g_hash_table_new(g_str_hash, g_str_equal); - hf = g_new0(hf_register_info,num_attribute_types); + dynamic_hf = g_new0(hf_register_info,num_attribute_types); + dynamic_hf_size = num_attribute_types; - for (i = 0; i < num_attribute_types; i++) { + for (guint i = 0; i < dynamic_hf_size; i++) { hf_id = g_new(gint,1); *hf_id = -1; attribute_type = g_strdup(attribute_types[i].attribute_type); - hf[i].p_id = hf_id; - hf[i].hfinfo.name = attribute_type; - hf[i].hfinfo.abbrev = g_strdup_printf("ldap.AttributeValue.%s", attribute_type); - hf[i].hfinfo.type = FT_STRING; - hf[i].hfinfo.display = BASE_NONE; - hf[i].hfinfo.strings = NULL; - hf[i].hfinfo.bitmask = 0; - hf[i].hfinfo.blurb = g_strdup(attribute_types[i].attribute_desc); - HFILL_INIT(hf[i]); + dynamic_hf[i].p_id = hf_id; + dynamic_hf[i].hfinfo.name = attribute_type; + dynamic_hf[i].hfinfo.abbrev = g_strdup_printf("ldap.AttributeValue.%s", attribute_type); + dynamic_hf[i].hfinfo.type = FT_STRING; + dynamic_hf[i].hfinfo.display = BASE_NONE; + dynamic_hf[i].hfinfo.strings = NULL; + dynamic_hf[i].hfinfo.bitmask = 0; + dynamic_hf[i].hfinfo.blurb = g_strdup(attribute_types[i].attribute_desc); + HFILL_INIT(dynamic_hf[i]); g_hash_table_insert(attribute_types_hash, attribute_type, hf_id); } - proto_register_field_array(proto_ldap, hf, num_attribute_types); + proto_register_field_array(proto_ldap, dynamic_hf, dynamic_hf_size); } } +static void +attribute_types_reset_cb(void) +{ + deregister_attribute_types(); +} + /* MS-ADTS specification, section 7.3.1.1, NETLOGON_NT_VERSION Options Bits */ static int dissect_mscldap_ntver_flags(proto_tree *parent_tree, tvbuff_t *tvb, int offset) { @@ -2204,8 +2222,8 @@ void proto_register_ldap(void) { attribute_types_copy_cb, attribute_types_update_cb, attribute_types_free_cb, - attribute_types_initialize_cb, - NULL, + attribute_types_post_update_cb, + attribute_types_reset_cb, custom_attribute_types_uat_fields); prefs_register_uat_preference(ldap_module, "custom_ldap_attribute_types", diff --git a/epan/dissectors/packet-http.c b/epan/dissectors/packet-http.c index 2adf6e788e..a53f9aa66b 100644 --- a/epan/dissectors/packet-http.c +++ b/epan/dissectors/packet-http.c @@ -159,10 +159,12 @@ typedef struct _header_field_t { gchar* header_desc; } header_field_t; -static header_field_t* header_fields = NULL; -static guint num_header_fields = 0; +static header_field_t* header_fields; +static guint num_header_fields; -static GHashTable* header_fields_hash = NULL; +static GHashTable* header_fields_hash; +static hf_register_info* dynamic_hf; +static guint dynamic_hf_size; static gboolean header_fields_update_cb(void *r, char **err) @@ -2725,54 +2727,69 @@ get_hf_for_header(char* header_name) * */ static void -header_fields_initialize_cb(void) +deregister_header_fields(void) +{ + if (dynamic_hf) { + /* Deregister all fields */ + for (guint i = 0; i < dynamic_hf_size; i++) { + proto_deregister_field (proto_http, *(dynamic_hf[i].p_id)); + g_free (dynamic_hf[i].p_id); + } + + proto_add_deregistered_data (dynamic_hf); + dynamic_hf = NULL; + dynamic_hf_size = 0; + } + + if (header_fields_hash) { + g_hash_table_destroy (header_fields_hash); + header_fields_hash = NULL; + } +} + +static void +header_fields_post_update_cb(void) { - static hf_register_info* hf; gint* hf_id; - guint i; gchar* header_name; gchar* header_name_key; - if (header_fields_hash && hf) { - guint hf_size = g_hash_table_size (header_fields_hash); - /* Deregister all fields */ - for (i = 0; i < hf_size; i++) { - proto_deregister_field (proto_http, *(hf[i].p_id)); - g_free (hf[i].p_id); - } - g_hash_table_destroy (header_fields_hash); - proto_add_deregistered_data (hf); - header_fields_hash = NULL; - } + deregister_header_fields(); if (num_header_fields) { - header_fields_hash = g_hash_table_new_full(g_str_hash, g_str_equal, - g_free, NULL); - hf = g_new0(hf_register_info, num_header_fields); + header_fields_hash = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, NULL); + dynamic_hf = g_new0(hf_register_info, num_header_fields); + dynamic_hf_size = num_header_fields; - for (i = 0; i < num_header_fields; i++) { + for (guint i = 0; i < dynamic_hf_size; i++) { hf_id = g_new(gint,1); *hf_id = -1; header_name = g_strdup(header_fields[i].header_name); header_name_key = g_ascii_strdown(header_name, -1); - hf[i].p_id = hf_id; - hf[i].hfinfo.name = header_name; - hf[i].hfinfo.abbrev = g_strdup_printf("http.header.%s", header_name); - hf[i].hfinfo.type = FT_STRING; - hf[i].hfinfo.display = BASE_NONE; - hf[i].hfinfo.strings = NULL; - hf[i].hfinfo.bitmask = 0; - hf[i].hfinfo.blurb = g_strdup(header_fields[i].header_desc); - HFILL_INIT(hf[i]); + dynamic_hf[i].p_id = hf_id; + dynamic_hf[i].hfinfo.name = header_name; + dynamic_hf[i].hfinfo.abbrev = g_strdup_printf("http.header.%s", header_name); + dynamic_hf[i].hfinfo.type = FT_STRING; + dynamic_hf[i].hfinfo.display = BASE_NONE; + dynamic_hf[i].hfinfo.strings = NULL; + dynamic_hf[i].hfinfo.bitmask = 0; + dynamic_hf[i].hfinfo.blurb = g_strdup(header_fields[i].header_desc); + HFILL_INIT(dynamic_hf[i]); g_hash_table_insert(header_fields_hash, header_name_key, hf_id); } - proto_register_field_array(proto_http, hf, num_header_fields); + proto_register_field_array(proto_http, dynamic_hf, dynamic_hf_size); } } +static void +header_fields_reset_cb(void) +{ + deregister_header_fields(); +} + /** * Parses the transfer-coding, returning TRUE if everything was fully understood * or FALSE when unknown names were encountered. @@ -3989,8 +4006,8 @@ proto_register_http(void) header_fields_copy_cb, header_fields_update_cb, header_fields_free_cb, - header_fields_initialize_cb, - NULL, + header_fields_post_update_cb, + header_fields_reset_cb, custom_header_uat_fields ); diff --git a/epan/dissectors/packet-imf.c b/epan/dissectors/packet-imf.c index fff3ea5612..b311019ee5 100644 --- a/epan/dissectors/packet-imf.c +++ b/epan/dissectors/packet-imf.c @@ -310,10 +310,12 @@ typedef struct _header_field_t { guint add_to_col_info; } header_field_t; -static header_field_t *header_fields = NULL; -static guint num_header_fields = 0; +static header_field_t *header_fields; +static guint num_header_fields; -static GHashTable *custom_field_table = NULL; +static GHashTable *custom_field_table; +static hf_register_info *dynamic_hf; +static guint dynamic_hf_size; static gboolean header_fields_update_cb(void *r, char **err) @@ -939,44 +941,54 @@ free_imf_field (gpointer data) } static void -header_fields_initialize_cb (void) +deregister_header_fields(void) { - static hf_register_info *hf; - gint *hf_id; - struct imf_field *imffield; - guint i; - gchar *header_name; - - if (custom_field_table && hf) { - guint hf_size = g_hash_table_size (custom_field_table); + if (dynamic_hf) { /* Deregister all fields */ - for (i = 0; i < hf_size; i++) { - proto_deregister_field (proto_imf, *(hf[i].p_id)); - g_free (hf[i].p_id); + for (guint i = 0; i < dynamic_hf_size; i++) { + proto_deregister_field (proto_imf, *(dynamic_hf[i].p_id)); + g_free (dynamic_hf[i].p_id); } + + proto_add_deregistered_data (dynamic_hf); + dynamic_hf = NULL; + dynamic_hf_size = 0; + } + + if (custom_field_table) { g_hash_table_destroy (custom_field_table); - proto_add_deregistered_data (hf); custom_field_table = NULL; } +} + +static void +header_fields_post_update_cb (void) +{ + gint *hf_id; + struct imf_field *imffield; + gchar *header_name; + + deregister_header_fields(); if (num_header_fields) { custom_field_table = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, free_imf_field); - hf = (hf_register_info *)g_malloc0 (sizeof (hf_register_info) * num_header_fields); + dynamic_hf = (hf_register_info *)g_malloc0 (sizeof (hf_register_info) * num_header_fields); + dynamic_hf_size = num_header_fields; - for (i = 0; i < num_header_fields; i++) { + for (guint i = 0; i < dynamic_hf_size; i++) { hf_id = (gint *)g_malloc (sizeof (gint)); *hf_id = -1; header_name = g_strdup (header_fields[i].header_name); - hf[i].p_id = hf_id; - hf[i].hfinfo.name = header_name; - hf[i].hfinfo.abbrev = g_strdup_printf ("imf.header.%s", header_name); - hf[i].hfinfo.type = FT_STRING; - hf[i].hfinfo.display = BASE_NONE; - hf[i].hfinfo.strings = NULL; - hf[i].hfinfo.bitmask = 0; - hf[i].hfinfo.blurb = g_strdup (header_fields[i].description); - HFILL_INIT(hf[i]); + dynamic_hf[i].p_id = hf_id; + dynamic_hf[i].hfinfo.name = header_name; + dynamic_hf[i].hfinfo.abbrev = g_strdup_printf ("imf.header.%s", header_name); + dynamic_hf[i].hfinfo.type = FT_STRING; + dynamic_hf[i].hfinfo.display = BASE_NONE; + dynamic_hf[i].hfinfo.strings = NULL; + dynamic_hf[i].hfinfo.bitmask = 0; + dynamic_hf[i].hfinfo.blurb = g_strdup (header_fields[i].description); + HFILL_INIT(dynamic_hf[i]); imffield = (struct imf_field *)g_malloc (sizeof (struct imf_field)); imffield->hf_id = hf_id; @@ -998,7 +1010,7 @@ header_fields_initialize_cb (void) imffield->subdissector = dissect_imf_address_list; break; case FORMAT_SIO_LABEL: - hf[i].hfinfo.type = FT_NONE; /* constructed */ + dynamic_hf[i].hfinfo.type = FT_NONE; /* constructed */ imffield->subdissector = dissect_imf_siolabel; break; default: @@ -1010,10 +1022,16 @@ header_fields_initialize_cb (void) g_hash_table_insert (custom_field_table, (gpointer)imffield->name, (gpointer)imffield); } - proto_register_field_array (proto_imf, hf, num_header_fields); + proto_register_field_array (proto_imf, dynamic_hf, dynamic_hf_size); } } +static void +header_fields_reset_cb(void) +{ + deregister_header_fields(); +} + /* Register all the bits needed by the filtering engine */ void @@ -1311,8 +1329,8 @@ proto_register_imf(void) header_fields_copy_cb, header_fields_update_cb, header_fields_free_cb, - header_fields_initialize_cb, - NULL, + header_fields_post_update_cb, + header_fields_reset_cb, attributes_flds); module_t *imf_module; diff --git a/epan/dissectors/packet-ldap.c b/epan/dissectors/packet-ldap.c index 515e19fb4f..921f358435 100644 --- a/epan/dissectors/packet-ldap.c +++ b/epan/dissectors/packet-ldap.c @@ -665,10 +665,12 @@ typedef struct _attribute_type_t { gchar* attribute_desc; } attribute_type_t; -static attribute_type_t* attribute_types = NULL; -static guint num_attribute_types = 0; +static attribute_type_t* attribute_types; +static guint num_attribute_types; -static GHashTable* attribute_types_hash = NULL; +static GHashTable* attribute_types_hash; +static hf_register_info* dynamic_hf; +static guint dynamic_hf_size; static gboolean attribute_types_update_cb(void *r, char **err) @@ -745,51 +747,67 @@ get_hf_for_header(char* attribute_type) * */ static void -attribute_types_initialize_cb(void) +deregister_attribute_types(void) { - static hf_register_info* hf; - gint* hf_id; - guint i; - gchar* attribute_type; - - if (attribute_types_hash && hf) { - guint hf_size = g_hash_table_size (attribute_types_hash); + if (dynamic_hf) { /* Deregister all fields */ - for (i = 0; i < hf_size; i++) { - proto_deregister_field (proto_ldap, *(hf[i].p_id)); - g_free (hf[i].p_id); + for (guint i = 0; i < dynamic_hf_size; i++) { + proto_deregister_field (proto_ldap, *(dynamic_hf[i].p_id)); + g_free (dynamic_hf[i].p_id); } + + proto_add_deregistered_data (dynamic_hf); + dynamic_hf = NULL; + dynamic_hf_size = 0; + } + + if (attribute_types_hash) { g_hash_table_destroy (attribute_types_hash); - proto_add_deregistered_data (hf); attribute_types_hash = NULL; } +} + +static void +attribute_types_post_update_cb(void) +{ + gint* hf_id; + gchar* attribute_type; + + deregister_attribute_types(); if (num_attribute_types) { attribute_types_hash = g_hash_table_new(g_str_hash, g_str_equal); - hf = g_new0(hf_register_info,num_attribute_types); + dynamic_hf = g_new0(hf_register_info,num_attribute_types); + dynamic_hf_size = num_attribute_types; - for (i = 0; i < num_attribute_types; i++) { + for (guint i = 0; i < dynamic_hf_size; i++) { hf_id = g_new(gint,1); *hf_id = -1; attribute_type = g_strdup(attribute_types[i].attribute_type); - hf[i].p_id = hf_id; - hf[i].hfinfo.name = attribute_type; - hf[i].hfinfo.abbrev = g_strdup_printf("ldap.AttributeValue.%s", attribute_type); - hf[i].hfinfo.type = FT_STRING; - hf[i].hfinfo.display = BASE_NONE; - hf[i].hfinfo.strings = NULL; - hf[i].hfinfo.bitmask = 0; - hf[i].hfinfo.blurb = g_strdup(attribute_types[i].attribute_desc); - HFILL_INIT(hf[i]); + dynamic_hf[i].p_id = hf_id; + dynamic_hf[i].hfinfo.name = attribute_type; + dynamic_hf[i].hfinfo.abbrev = g_strdup_printf("ldap.AttributeValue.%s", attribute_type); + dynamic_hf[i].hfinfo.type = FT_STRING; + dynamic_hf[i].hfinfo.display = BASE_NONE; + dynamic_hf[i].hfinfo.strings = NULL; + dynamic_hf[i].hfinfo.bitmask = 0; + dynamic_hf[i].hfinfo.blurb = g_strdup(attribute_types[i].attribute_desc); + HFILL_INIT(dynamic_hf[i]); g_hash_table_insert(attribute_types_hash, attribute_type, hf_id); } - proto_register_field_array(proto_ldap, hf, num_attribute_types); + proto_register_field_array(proto_ldap, dynamic_hf, dynamic_hf_size); } } +static void +attribute_types_reset_cb(void) +{ + deregister_attribute_types(); +} + /* MS-ADTS specification, section 7.3.1.1, NETLOGON_NT_VERSION Options Bits */ static int dissect_mscldap_ntver_flags(proto_tree *parent_tree, tvbuff_t *tvb, int offset) { @@ -3815,7 +3833,7 @@ static int dissect_PasswordPolicyResponseValue_PDU(tvbuff_t *tvb _U_, packet_inf /*--- End of included file: packet-ldap-fn.c ---*/ -#line 901 "./asn1/ldap/packet-ldap-template.c" +#line 919 "./asn1/ldap/packet-ldap-template.c" static int dissect_LDAPMessage_PDU(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, ldap_conv_info_t *ldap_info) { int offset = 0; @@ -5625,7 +5643,7 @@ void proto_register_ldap(void) { NULL, HFILL }}, /*--- End of included file: packet-ldap-hfarr.c ---*/ -#line 2142 "./asn1/ldap/packet-ldap-template.c" +#line 2160 "./asn1/ldap/packet-ldap-template.c" }; /* List of subtrees */ @@ -5699,7 +5717,7 @@ void proto_register_ldap(void) { &ett_ldap_T_warning, /*--- End of included file: packet-ldap-ettarr.c ---*/ -#line 2156 "./asn1/ldap/packet-ldap-template.c" +#line 2174 "./asn1/ldap/packet-ldap-template.c" }; /* UAT for header fields */ static uat_field_t custom_attribute_types_uat_fields[] = { @@ -5751,8 +5769,8 @@ void proto_register_ldap(void) { attribute_types_copy_cb, attribute_types_update_cb, attribute_types_free_cb, - attribute_types_initialize_cb, - NULL, + attribute_types_post_update_cb, + attribute_types_reset_cb, custom_attribute_types_uat_fields); prefs_register_uat_preference(ldap_module, "custom_ldap_attribute_types", @@ -5887,7 +5905,7 @@ proto_reg_handoff_ldap(void) /*--- End of included file: packet-ldap-dis-tab.c ---*/ -#line 2327 "./asn1/ldap/packet-ldap-template.c" +#line 2345 "./asn1/ldap/packet-ldap-template.c" dissector_add_uint_range_with_preference("tcp.port", TCP_PORT_RANGE_LDAP, ldap_handle); } diff --git a/epan/dissectors/packet-lwm2mtlv.c b/epan/dissectors/packet-lwm2mtlv.c index af2ef43f6a..a6fffd2fc0 100644 --- a/epan/dissectors/packet-lwm2mtlv.c +++ b/epan/dissectors/packet-lwm2mtlv.c @@ -235,6 +235,10 @@ static lwm2m_resource_t lwm2m_oma_resources[] = static lwm2m_resource_t *lwm2m_uat_resources; static guint num_lwm2m_uat_resources; +static hf_register_info *dynamic_hf; +static guint dynamic_hf_size; +static hf_register_info *static_hf; + static gboolean lwm2m_resource_update_cb(void *record, char **error) { lwm2m_resource_t *rec = (lwm2m_resource_t *)record; @@ -352,32 +356,41 @@ static void lwm2m_add_resource(lwm2m_resource_t *resource, hf_register_info *hf) HFILL_INIT(*hf); } +static void deregister_resource_fields(void) +{ + if (dynamic_hf) { + /* Deregister all fields */ + for (guint i = 0; i < dynamic_hf_size; i++) { + proto_deregister_field(proto_lwm2mtlv, *(dynamic_hf[i].p_id)); + g_free (dynamic_hf[i].p_id); + } + + proto_add_deregistered_data(dynamic_hf); + dynamic_hf = NULL; + dynamic_hf_size = 0; + } +} + static void lwm2m_resource_post_update_cb(void) { - static hf_register_info *hf; - static guint hf_size; - - if (hf_size > 0) { - /* Deregister all fields */ - for (guint i = 0; i < hf_size; i++) { - proto_deregister_field(proto_lwm2mtlv, *(hf[i].p_id)); - g_free (hf[i].p_id); - } - proto_add_deregistered_data(hf); - hf_size = 0; - } + deregister_resource_fields(); if (num_lwm2m_uat_resources) { - hf = g_new0(hf_register_info, num_lwm2m_uat_resources); + dynamic_hf = g_new0(hf_register_info, num_lwm2m_uat_resources); for (guint i = 0; i < num_lwm2m_uat_resources; i++) { - lwm2m_add_resource(&lwm2m_uat_resources[i], &hf[hf_size++]); + lwm2m_add_resource(&lwm2m_uat_resources[i], &dynamic_hf[dynamic_hf_size++]); } - proto_register_field_array(proto_lwm2mtlv, hf, hf_size); + proto_register_field_array(proto_lwm2mtlv, dynamic_hf, dynamic_hf_size); } } +static void lwm2m_resource_reset_cb(void) +{ + deregister_resource_fields(); +} + static gint64 decodeVariableInt(tvbuff_t *tvb, const gint offset, const guint length) { @@ -709,6 +722,18 @@ dissect_lwm2mtlv(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, void * return tvb_captured_length(tvb); } +static void lwm2m_shutdown_routine(void) +{ + /* Deregister all fields */ + for (guint i = 0; i < array_length(lwm2m_oma_resources); i++) { + proto_deregister_field(proto_lwm2mtlv, *(static_hf[i].p_id)); + g_free (static_hf[i].p_id); + } + + proto_add_deregistered_data(static_hf); + static_hf = NULL; +} + void proto_register_lwm2mtlv(void) { static hf_register_info hf[] = { @@ -818,7 +843,7 @@ void proto_register_lwm2mtlv(void) lwm2m_resource_update_cb, lwm2m_resource_free_cb, lwm2m_resource_post_update_cb, - NULL, + lwm2m_resource_reset_cb, lwm2m_resource_flds); module_t *lwm2mtlv_module; @@ -835,6 +860,9 @@ void proto_register_lwm2mtlv(void) register_dissector("lwm2mtlv", dissect_lwm2mtlv, proto_lwm2mtlv); + /* Register the dissector shutdown function */ + register_shutdown_routine(lwm2m_shutdown_routine); + lwm2mtlv_module = prefs_register_protocol(proto_lwm2mtlv, NULL); prefs_register_uat_preference(lwm2mtlv_module, "resource_table", @@ -842,11 +870,11 @@ void proto_register_lwm2mtlv(void) "User Resource Names", resource_uat); - hf_register_info *hf2 = g_new0(hf_register_info, array_length(lwm2m_oma_resources)); + static_hf = g_new0(hf_register_info, array_length(lwm2m_oma_resources)); for (guint i = 0; i < array_length(lwm2m_oma_resources); i++) { - lwm2m_add_resource(&lwm2m_oma_resources[i], &hf2[i]); + lwm2m_add_resource(&lwm2m_oma_resources[i], &static_hf[i]); } - proto_register_field_array(proto_lwm2mtlv, hf2, array_length(lwm2m_oma_resources)); + proto_register_field_array(proto_lwm2mtlv, static_hf, array_length(lwm2m_oma_resources)); } void diff --git a/epan/dissectors/packet-sip.c b/epan/dissectors/packet-sip.c index 4b90e334ca..3a89875320 100644 --- a/epan/dissectors/packet-sip.c +++ b/epan/dissectors/packet-sip.c @@ -908,9 +908,11 @@ typedef struct _header_field_t { gchar* header_desc; } header_field_t; -static header_field_t* sip_custom_header_fields = NULL; -static guint sip_custom_num_header_fields = 0; -static wmem_map_t *sip_custom_header_fields_hash = NULL; +static header_field_t* sip_custom_header_fields; +static guint sip_custom_num_header_fields; +static GHashTable *sip_custom_header_fields_hash; +static hf_register_info *dynamic_hf; +static guint dynamic_hf_size; static gboolean header_fields_update_cb(void *r, char **err) @@ -964,54 +966,69 @@ header_fields_free_cb(void*r) } static void -header_fields_initialize_cb(void) +deregister_header_fields(void) +{ + if (dynamic_hf) { + /* Deregister all fields */ + for (guint i = 0; i < dynamic_hf_size; i++) { + proto_deregister_field(proto_sip, *(dynamic_hf[i].p_id)); + g_free(dynamic_hf[i].p_id); + } + + proto_add_deregistered_data(dynamic_hf); + dynamic_hf = NULL; + dynamic_hf_size = 0; + } + + if (sip_custom_header_fields_hash) { + g_hash_table_destroy(sip_custom_header_fields_hash); + sip_custom_header_fields_hash = NULL; + } +} + +static void +header_fields_post_update_cb(void) { - static hf_register_info* hf; gint* hf_id; - guint i; gchar* header_name; gchar* header_name_key; - if (hf) { - guint hf_size = wmem_map_size(sip_custom_header_fields_hash); - /* Deregister all fields */ - for (i = 0; i < hf_size; i++) { - proto_deregister_field(proto_sip, *(hf[i].p_id)); - header_name_key = wmem_ascii_strdown(NULL, hf[i].hfinfo.name, -1); - wmem_map_remove(sip_custom_header_fields_hash, header_name_key); - wmem_free(NULL, header_name_key); - wmem_free(wmem_epan_scope(), hf[i].p_id); - } - proto_add_deregistered_data(hf); - hf = NULL; - } + deregister_header_fields(); if (sip_custom_num_header_fields) { - hf = g_new0(hf_register_info, sip_custom_num_header_fields); + sip_custom_header_fields_hash = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, NULL); + dynamic_hf = g_new0(hf_register_info, sip_custom_num_header_fields); + dynamic_hf_size = sip_custom_num_header_fields; - for (i = 0; i < sip_custom_num_header_fields; i++) { - hf_id = wmem_new(wmem_epan_scope(), gint); + for (guint i = 0; i < dynamic_hf_size; i++) { + hf_id = g_new(gint, 1); *hf_id = -1; header_name = g_strdup(sip_custom_header_fields[i].header_name); - header_name_key = wmem_ascii_strdown(wmem_epan_scope(), header_name, -1); + header_name_key = g_ascii_strdown(header_name, -1); - hf[i].p_id = hf_id; - hf[i].hfinfo.name = header_name; - hf[i].hfinfo.abbrev = g_strdup_printf("sip.%s", header_name); - hf[i].hfinfo.type = FT_STRING; - hf[i].hfinfo.display = BASE_NONE; - hf[i].hfinfo.strings = NULL; - hf[i].hfinfo.bitmask = 0; - hf[i].hfinfo.blurb = g_strdup(sip_custom_header_fields[i].header_desc); - HFILL_INIT(hf[i]); + dynamic_hf[i].p_id = hf_id; + dynamic_hf[i].hfinfo.name = header_name; + dynamic_hf[i].hfinfo.abbrev = g_strdup_printf("sip.%s", header_name); + dynamic_hf[i].hfinfo.type = FT_STRING; + dynamic_hf[i].hfinfo.display = BASE_NONE; + dynamic_hf[i].hfinfo.strings = NULL; + dynamic_hf[i].hfinfo.bitmask = 0; + dynamic_hf[i].hfinfo.blurb = g_strdup(sip_custom_header_fields[i].header_desc); + HFILL_INIT(dynamic_hf[i]); - wmem_map_insert(sip_custom_header_fields_hash, header_name_key, hf_id); + g_hash_table_insert(sip_custom_header_fields_hash, header_name_key, hf_id); } - proto_register_field_array(proto_sip, hf, sip_custom_num_header_fields); + proto_register_field_array(proto_sip, dynamic_hf, dynamic_hf_size); } } +static void +header_fields_reset_cb(void) +{ + deregister_header_fields(); +} + UAT_CSTRING_CB_DEF(sip_custom_header_fields, header_name, header_field_t) UAT_CSTRING_CB_DEF(sip_custom_header_fields, header_desc, header_field_t) @@ -3576,7 +3593,10 @@ dissect_sip_common(tvbuff_t *tvb, int offset, int remaining_length, packet_info value_len = (gint) (line_end_offset - value_offset); if (hf_index == -1) { - gint *hf_ptr = (gint*)wmem_map_lookup(sip_custom_header_fields_hash, header_name); + gint *hf_ptr = NULL; + if (sip_custom_header_fields_hash) { + hf_ptr = (gint*)g_hash_table_lookup(sip_custom_header_fields_hash, header_name); + } if (hf_ptr) { sip_proto_tree_add_string(hdr_tree, *hf_ptr, tvb, offset, next_offset - offset, value_offset, value_len); @@ -7374,8 +7394,8 @@ void proto_register_sip(void) header_fields_copy_cb, header_fields_update_cb, header_fields_free_cb, - header_fields_initialize_cb, - NULL, + header_fields_post_update_cb, + header_fields_reset_cb, sip_custom_header_uat_fields ); @@ -7420,8 +7440,6 @@ void proto_register_sip(void) register_stat_tap_table_ui(&sip_stat_table); - sip_custom_header_fields_hash = wmem_map_new(wmem_epan_scope(), wmem_str_hash, g_str_equal); - /* compile patterns */ ws_mempbrk_compile(&pbrk_comma_semi, ",;"); ws_mempbrk_compile(&pbrk_whitespace, " \t\r\n"); diff --git a/epan/dissectors/packet-udp-nm.c b/epan/dissectors/packet-udp-nm.c index c999c19a7d..2cef537b65 100644 --- a/epan/dissectors/packet-udp-nm.c +++ b/epan/dissectors/packet-udp-nm.c @@ -74,10 +74,12 @@ static gboolean g_udp_nm_swap_first_fields = TRUE; /*** stolen from the HTTP disector ;-) ***/ -static user_data_field_t* user_data_fields = NULL; -static guint num_user_data_fields = 0; -static GHashTable* user_data_fields_hash_hf = NULL; -static GHashTable* user_data_fields_hash_ett = NULL; +static user_data_field_t* user_data_fields; +static guint num_user_data_fields; +static GHashTable* user_data_fields_hash_hf; +static hf_register_info* dynamic_hf; +static guint dynamic_hf_size; +static wmem_map_t* user_data_fields_hash_ett; static gboolean user_data_fields_update_cb(void *r, char **err) @@ -210,7 +212,7 @@ get_ett_for_user_data(guint32 offset, guint32 length) guint64 key = calc_ett_key(offset, length); if (user_data_fields_hash_ett) { - ett_id = (gint*)g_hash_table_lookup(user_data_fields_hash_ett, &key); + ett_id = (gint*)wmem_map_lookup(user_data_fields_hash_ett, &key); } else { ett_id = NULL; @@ -222,14 +224,32 @@ get_ett_for_user_data(guint32 offset, guint32 length) /* * */ +static void +deregister_user_data(void) +{ + if (dynamic_hf) { + /* Unregister all fields */ + for (guint i = 0; i < dynamic_hf_size; i++) { + proto_deregister_field(proto_udp_nm, *(dynamic_hf[i].p_id)); + g_free(dynamic_hf[i].p_id); + } + + proto_add_deregistered_data(dynamic_hf); + dynamic_hf = NULL; + dynamic_hf_size = 0; + } + + if (user_data_fields_hash_hf) { + g_hash_table_destroy(user_data_fields_hash_hf); + user_data_fields_hash_hf = NULL; + } +} + static void user_data_post_update_cb(void) { - static hf_register_info* hf; gint* hf_id; - guint i; - //gchar* udf_name; - + gint *ett_id; gchar* tmp = NULL; guint64* key = NULL; @@ -238,53 +258,43 @@ user_data_post_update_cb(void) &ett_dummy, }; - static gint *ett_id; - - if (user_data_fields_hash_hf && hf) { - guint hf_size = g_hash_table_size(user_data_fields_hash_hf); - /* Unregister all fields */ - for (i = 0; i < hf_size; i++) { - proto_deregister_field(proto_udp_nm, *(hf[i].p_id)); - } - g_hash_table_destroy(user_data_fields_hash_hf); - - user_data_fields_hash_hf = NULL; - } + deregister_user_data(); // we cannot unregister ETTs, so we should try to limit the damage of an update if (num_user_data_fields) { - user_data_fields_hash_hf = g_hash_table_new(g_str_hash, g_str_equal); - hf = g_new0(hf_register_info, num_user_data_fields); + user_data_fields_hash_hf = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, NULL); + dynamic_hf = g_new0(hf_register_info, num_user_data_fields); + dynamic_hf_size = num_user_data_fields; if (user_data_fields_hash_ett == NULL) { - user_data_fields_hash_ett = g_hash_table_new(g_int64_hash, g_int64_equal); + user_data_fields_hash_ett = wmem_map_new(wmem_epan_scope(), g_int64_hash, g_int64_equal); } - for (i = 0; i < num_user_data_fields; i++) { + for (guint i = 0; i < dynamic_hf_size; i++) { hf_id = g_new(gint, 1); *hf_id = -1; - hf[i].p_id = hf_id; - hf[i].hfinfo.strings = NULL; - hf[i].hfinfo.bitmask = user_data_fields[i].udf_mask; - hf[i].hfinfo.same_name_next = NULL; - hf[i].hfinfo.same_name_prev_id = -1; + dynamic_hf[i].p_id = hf_id; + dynamic_hf[i].hfinfo.strings = NULL; + dynamic_hf[i].hfinfo.bitmask = user_data_fields[i].udf_mask; + dynamic_hf[i].hfinfo.same_name_next = NULL; + dynamic_hf[i].hfinfo.same_name_prev_id = -1; if (user_data_fields[i].udf_mask == 0 || user_data_fields[i].udf_length <= 0 || user_data_fields[i].udf_length>4) { - hf[i].hfinfo.name = g_strdup(user_data_fields[i].udf_name); - hf[i].hfinfo.abbrev = g_strdup_printf("nm.user_data.%s", user_data_fields[i].udf_name); - hf[i].hfinfo.type = FT_BYTES; - hf[i].hfinfo.display = BASE_NONE; - hf[i].hfinfo.bitmask = 0; - hf[i].hfinfo.blurb = g_strdup(user_data_fields[i].udf_desc); + dynamic_hf[i].hfinfo.name = g_strdup(user_data_fields[i].udf_name); + dynamic_hf[i].hfinfo.abbrev = g_strdup_printf("nm.user_data.%s", user_data_fields[i].udf_name); + dynamic_hf[i].hfinfo.type = FT_BYTES; + dynamic_hf[i].hfinfo.display = BASE_NONE; + dynamic_hf[i].hfinfo.bitmask = 0; + dynamic_hf[i].hfinfo.blurb = g_strdup(user_data_fields[i].udf_desc); } else { - hf[i].hfinfo.name = g_strdup(user_data_fields[i].udf_value_desc); - hf[i].hfinfo.abbrev = g_strdup_printf("nm.user_data.%s.%s", user_data_fields[i].udf_name, user_data_fields[i].udf_value_desc); - hf[i].hfinfo.type = FT_BOOLEAN; - hf[i].hfinfo.display = 8 * (user_data_fields[i].udf_length); - // hf[i].hfinfo.bitmask = 0; - hf[i].hfinfo.blurb = g_strdup(user_data_fields[i].udf_value_desc); + dynamic_hf[i].hfinfo.name = g_strdup(user_data_fields[i].udf_value_desc); + dynamic_hf[i].hfinfo.abbrev = g_strdup_printf("nm.user_data.%s.%s", user_data_fields[i].udf_name, user_data_fields[i].udf_value_desc); + dynamic_hf[i].hfinfo.type = FT_BOOLEAN; + dynamic_hf[i].hfinfo.display = 8 * (user_data_fields[i].udf_length); + // dynamic_hf[i].hfinfo.bitmask = 0; + dynamic_hf[i].hfinfo.blurb = g_strdup(user_data_fields[i].udf_value_desc); } tmp = calc_hf_key(user_data_fields[i]); @@ -295,20 +305,26 @@ user_data_post_update_cb(void) ett_dummy = -1; proto_register_subtree_array(ett, array_length(ett)); - ett_id = g_new(gint, 1); + ett_id = wmem_new(wmem_epan_scope(), gint); *ett_id = ett_dummy; - key = g_new(guint64, 1); + key = wmem_new(wmem_epan_scope(), guint64); *key = calc_ett_key(user_data_fields[i].udf_offset, user_data_fields[i].udf_length); - g_hash_table_insert(user_data_fields_hash_ett, key, ett_id); + wmem_map_insert(user_data_fields_hash_ett, key, ett_id); } } - proto_register_field_array(proto_udp_nm, hf, num_user_data_fields); + proto_register_field_array(proto_udp_nm, dynamic_hf, dynamic_hf_size); } } +static void +user_data_reset_cb(void) +{ + deregister_user_data(); +} + /********************************** ****** The dissector itself ****** @@ -472,7 +488,7 @@ void proto_register_udp_nm(void) user_data_fields_update_cb, /* update callback */ user_data_fields_free_cb, /* free callback */ user_data_post_update_cb, /* post update callback */ - NULL, /* reset callback */ + user_data_reset_cb, /* reset callback */ user_data_uat_fields); /* UAT field definitions */ prefs_register_uat_preference(udp_nm_module, "udp_nm_user_data_fields", "User Data Field Configuration", diff --git a/epan/epan.c b/epan/epan.c index 3dfcde7c42..fe1f660c94 100644 --- a/epan/epan.c +++ b/epan/epan.c @@ -307,13 +307,22 @@ epan_cleanup(void) epan_register_all_handoffs = NULL; dfilter_cleanup(); - proto_cleanup(); - prefs_cleanup(); decode_clear_all(); + + /* + * Note: packet_cleanup() will call registered shutdown routines which + * may be used to deregister dynamically registered protocol fields, + * and prefs_cleanup() will call uat_clear() which also may be used to + * deregister dynamically registered protocol fields. This must be done + * before proto_cleanup() to avoid inconsistency and memory leaks. + */ + packet_cleanup(); + prefs_cleanup(); + proto_cleanup(); + conversation_filters_cleanup(); reassembly_table_cleanup(); tap_cleanup(); - packet_cleanup(); expert_cleanup(); capture_dissector_cleanup(); export_pdu_cleanup(); diff --git a/epan/proto.c b/epan/proto.c index 22b0f4ac88..49960d56e5 100644 --- a/epan/proto.c +++ b/epan/proto.c @@ -608,6 +608,7 @@ proto_cleanup_base(void) void proto_cleanup(void) { + proto_free_deregistered_fields(); proto_cleanup_base(); #ifdef HAVE_PLUGINS