1
0
mirror of https://github.com/signalwire/freeswitch.git synced 2025-04-07 21:32:56 +00:00

Merge pull request in FS/freeswitch from sofia-leak to master

* commit '20a893fd0683de64353ee2c111aa9c61a867886d':
  FS-12038: [mod_sofia, core] Fix potential leak and race in chat_hash, add switch_core_hash_insert_auto_free().
This commit is contained in:
Andrey Volk 2019-09-06 11:28:31 -05:00
commit fc925a273b
5 changed files with 26 additions and 13 deletions

@ -1424,6 +1424,16 @@ SWITCH_DECLARE(switch_status_t) switch_core_hash_init_case(_Out_ switch_hash_t *
*/
SWITCH_DECLARE(switch_status_t) switch_core_hash_destroy(_Inout_ switch_hash_t **hash);
/*!
\brief Insert data into a hash and set flags so the value is automatically freed on delete
\param hash the hash to add data to
\param key the name of the key to add the data to
\param data the data to add
\return SWITCH_STATUS_SUCCESS if the data is added
\note the string key must be a constant or a dynamic string
*/
SWITCH_DECLARE(switch_status_t) switch_core_hash_insert_auto_free(switch_hash_t *hash, const char *key, const void *data);
/*!
\brief Insert data into a hash
\param hash the hash to add data to

@ -360,7 +360,6 @@ switch_status_t sofia_on_destroy(switch_core_session_t *session)
{
private_object_t *tech_pvt = (private_object_t *) switch_core_session_get_private(session);
switch_channel_t *channel = switch_core_session_get_channel(session);
char *uuid;
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "%s SOFIA DESTROY\n", switch_channel_get_name(channel));
@ -376,13 +375,7 @@ switch_status_t sofia_on_destroy(switch_core_session_t *session)
}
if (!zstr(tech_pvt->call_id)) {
switch_mutex_lock(tech_pvt->profile->flag_mutex);
if ((uuid = switch_core_hash_find(tech_pvt->profile->chat_hash, tech_pvt->call_id))) {
free(uuid);
uuid = NULL;
switch_core_hash_delete(tech_pvt->profile->chat_hash, tech_pvt->call_id);
}
switch_mutex_unlock(tech_pvt->profile->flag_mutex);
switch_core_hash_delete_locked(tech_pvt->profile->chat_hash, tech_pvt->call_id, tech_pvt->profile->flag_mutex);
}
@ -461,7 +454,7 @@ switch_status_t sofia_on_hangup(switch_core_session_t *session)
switch_channel_get_name(channel), switch_channel_cause2str(cause));
if (tech_pvt->hash_key && !sofia_test_pflag(tech_pvt->profile, PFLAG_DESTROY)) {
switch_core_hash_delete(tech_pvt->profile->chat_hash, tech_pvt->hash_key);
switch_core_hash_delete_locked(tech_pvt->profile->chat_hash, tech_pvt->hash_key, tech_pvt->profile->flag_mutex);
}
if (session && tech_pvt->profile->pres_type) {

@ -2435,7 +2435,7 @@ void sofia_event_callback(nua_event_t event,
tech_pvt->nh = NULL;
sofia_set_flag(tech_pvt, TFLAG_BYE);
switch_mutex_lock(profile->flag_mutex);
switch_core_hash_insert(profile->chat_hash, tech_pvt->call_id, strdup(switch_core_session_get_uuid(session)));
switch_core_hash_insert_auto_free(profile->chat_hash, tech_pvt->call_id, strdup(switch_core_session_get_uuid(session)));
switch_mutex_unlock(profile->flag_mutex);
nua_handle_destroy(nh);
} else {
@ -2524,10 +2524,11 @@ void sofia_event_callback(nua_event_t event,
if (sip->sip_call_id && sip->sip_call_id->i_id) {
char *uuid;
char *uuid = NULL, *tmp;
switch_mutex_lock(profile->flag_mutex);
if ((uuid = (char *) switch_core_hash_find(profile->chat_hash, sip->sip_call_id->i_id))) {
if ((tmp = (char *) switch_core_hash_find(profile->chat_hash, sip->sip_call_id->i_id))) {
uuid = strdup(tmp);
switch_core_hash_delete(profile->chat_hash, sip->sip_call_id->i_id);
}
switch_mutex_unlock(profile->flag_mutex);

@ -5000,7 +5000,7 @@ void sofia_presence_handle_sip_i_message(int status,
abort();
}
if (sofia_test_pflag(profile, PFLAG_IN_DIALOG_CHAT) && (tech_pvt = (private_object_t *) switch_core_hash_find(profile->chat_hash, hash_key))) {
if (sofia_test_pflag(profile, PFLAG_IN_DIALOG_CHAT) && (tech_pvt = (private_object_t *) switch_core_hash_find_locked(profile->chat_hash, hash_key, profile->flag_mutex))) {
switch_core_session_queue_event(tech_pvt->session, &event);
} else {
switch_core_chat_send(proto, event);

@ -55,6 +55,15 @@ SWITCH_DECLARE(switch_status_t) switch_core_hash_destroy(switch_hash_t **hash)
return SWITCH_STATUS_SUCCESS;
}
SWITCH_DECLARE(switch_status_t) switch_core_hash_insert_auto_free(switch_hash_t *hash, const char *key, const void *data)
{
int r = 0;
r = switch_hashtable_insert_destructor(hash, strdup(key), (void *)data, HASHTABLE_FLAG_FREE_KEY | HASHTABLE_FLAG_FREE_VALUE | HASHTABLE_DUP_CHECK, NULL);
return r ? SWITCH_STATUS_SUCCESS : SWITCH_STATUS_FALSE;
}
SWITCH_DECLARE(switch_status_t) switch_core_hash_insert_destructor(switch_hash_t *hash, const char *key, const void *data, hashtable_destructor_t destructor)
{
int r = 0;