From: Richard Mudgett Date: Mon, 28 Jul 2014 18:50:14 +0000 (+0000) Subject: datastores: Audit ast_channel_datastore_remove usage. X-Git-Tag: 12.5.0-rc1~31 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=094e227f786b1d4030b009489bded84c3a57669c;p=thirdparty%2Fasterisk.git datastores: Audit ast_channel_datastore_remove usage. Audit of v1.8 usage of ast_channel_datastore_remove() for datastore memory leaks. * Fixed leaks in app_speech_utils and func_frame_trace. * Fixed app_speech_utils not locking the channel when accessing the channel datastore list. Review: https://reviewboard.asterisk.org/r/3859/ Audit of v11 usage of ast_channel_datastore_remove() for datastore memory leaks. * Fixed leak in func_jitterbuffer. (Was not in v12) Review: https://reviewboard.asterisk.org/r/3860/ Audit of v12 usage of ast_channel_datastore_remove() for datastore memory leaks. * Fixed leaks in abstract_jb. * Fixed leak in ast_channel_unsuppress(). Used by ARI mute control and res_mutestream. * Fixed ref leak in ast_channel_suppress(). Used by ARI mute control and res_mutestream. Review: https://reviewboard.asterisk.org/r/3861/ ........ Merged revisions 419684 from http://svn.asterisk.org/svn/asterisk/branches/1.8 ........ Merged revisions 419685 from http://svn.asterisk.org/svn/asterisk/branches/11 git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/12@419686 65c4cc65-6c06-0410-ace0-fbb531ad65f3 --- diff --git a/apps/app_speech_utils.c b/apps/app_speech_utils.c index e9ca63ea91..0d36365966 100644 --- a/apps/app_speech_utils.c +++ b/apps/app_speech_utils.c @@ -290,7 +290,9 @@ static struct ast_speech *find_speech(struct ast_channel *chan) return NULL; } + ast_channel_lock(chan); datastore = ast_channel_datastore_find(chan, &speech_datastore, NULL); + ast_channel_unlock(chan); if (datastore == NULL) { return NULL; } @@ -299,6 +301,35 @@ static struct ast_speech *find_speech(struct ast_channel *chan) return speech; } +/*! + * \internal + * \brief Destroy the speech datastore on the given channel. + * + * \param chan Channel to destroy speech datastore. + * + * \retval 0 on success. + * \retval -1 not found. + */ +static int speech_datastore_destroy(struct ast_channel *chan) +{ + struct ast_datastore *datastore; + int res; + + ast_channel_lock(chan); + datastore = ast_channel_datastore_find(chan, &speech_datastore, NULL); + if (datastore) { + ast_channel_datastore_remove(chan, datastore); + } + ast_channel_unlock(chan); + if (datastore) { + ast_datastore_free(datastore); + res = 0; + } else { + res = -1; + } + return res; +} + /* Helper function to find a specific speech recognition result by number and nbest alternative */ static struct ast_speech_result *find_result(struct ast_speech_result *results, char *result_num) { @@ -532,7 +563,9 @@ static int speech_create(struct ast_channel *chan, const char *data) } pbx_builtin_setvar_helper(chan, "ERROR", NULL); datastore->data = speech; + ast_channel_lock(chan); ast_channel_datastore_add(chan, datastore); + ast_channel_unlock(chan); return 0; } @@ -675,7 +708,6 @@ static int speech_background(struct ast_channel *chan, const char *data) struct ast_format oldreadformat; char dtmf[AST_MAX_EXTENSION] = ""; struct timeval start = { 0, 0 }, current; - struct ast_datastore *datastore = NULL; char *parse, *filename_tmp = NULL, *filename = NULL, tmp[2] = "", dtmf_terminator = '#'; const char *tmp2 = NULL; struct ast_flags options = { 0 }; @@ -905,11 +937,7 @@ static int speech_background(struct ast_channel *chan, const char *data) /* See if it was because they hung up */ if (done == 3) { - /* Destroy speech structure */ - ast_speech_destroy(speech); - datastore = ast_channel_datastore_find(chan, &speech_datastore, NULL); - if (datastore != NULL) - ast_channel_datastore_remove(chan, datastore); + speech_datastore_destroy(chan); } else { /* Channel is okay so restore read format */ ast_set_read_format(chan, &oldreadformat); @@ -922,22 +950,10 @@ static int speech_background(struct ast_channel *chan, const char *data) /*! \brief SpeechDestroy() Dialplan Application */ static int speech_destroy(struct ast_channel *chan, const char *data) { - int res = 0; - struct ast_speech *speech = find_speech(chan); - struct ast_datastore *datastore = NULL; - - if (speech == NULL) + if (!chan) { return -1; - - /* Destroy speech structure */ - ast_speech_destroy(speech); - - datastore = ast_channel_datastore_find(chan, &speech_datastore, NULL); - if (datastore != NULL) { - ast_channel_datastore_remove(chan, datastore); } - - return res; + return speech_datastore_destroy(chan); } static int unload_module(void) diff --git a/funcs/func_frame_trace.c b/funcs/func_frame_trace.c index ecebde4df0..36a98d649d 100644 --- a/funcs/func_frame_trace.c +++ b/funcs/func_frame_trace.c @@ -185,6 +185,7 @@ static int frame_trace_helper(struct ast_channel *chan, const char *cmd, char *d id = datastore->data; ast_framehook_detach(chan, *id); ast_channel_datastore_remove(chan, datastore); + ast_datastore_free(datastore); } if (!(datastore = ast_datastore_alloc(&frame_trace_datastore, NULL))) { diff --git a/main/abstract_jb.c b/main/abstract_jb.c index 7841b6a4e7..318498401a 100644 --- a/main/abstract_jb.c +++ b/main/abstract_jb.c @@ -1052,6 +1052,7 @@ void ast_jb_create_framehook(struct ast_channel *chan, struct ast_jb_conf *jb_co id = datastore->data; ast_framehook_detach(chan, *id); ast_channel_datastore_remove(chan, datastore); + ast_datastore_free(datastore); } ast_channel_unlock(chan); return; @@ -1084,6 +1085,7 @@ void ast_jb_create_framehook(struct ast_channel *chan, struct ast_jb_conf *jb_co id = datastore->data; ast_framehook_detach(chan, *id); ast_channel_datastore_remove(chan, datastore); + ast_datastore_free(datastore); } if (!(datastore = ast_datastore_alloc(&jb_datastore, NULL))) { @@ -1109,6 +1111,4 @@ void ast_jb_create_framehook(struct ast_channel *chan, struct ast_jb_conf *jb_co framedata = NULL; } ast_channel_unlock(chan); - - return; } diff --git a/main/channel.c b/main/channel.c index e05a5a1088..40a25313e6 100644 --- a/main/channel.c +++ b/main/channel.c @@ -10381,10 +10381,7 @@ int ast_channel_suppress(struct ast_channel *chan, unsigned int direction, enum if ((datastore = ast_channel_datastore_find(chan, datastore_info, NULL))) { suppress = datastore->data; - ao2_ref(suppress, +1); - suppress->direction |= direction; - return 0; } @@ -10416,13 +10413,12 @@ int ast_channel_suppress(struct ast_channel *chan, unsigned int direction, enum return -1; } + /* and another ref for the datastore */ + ao2_ref(suppress, +1); datastore->data = suppress; ast_channel_datastore_add(chan, datastore); - /* and another ref for the datastore */ - ao2_ref(suppress, +1); - return 0; } @@ -10450,6 +10446,7 @@ int ast_channel_unsuppress(struct ast_channel *chan, unsigned int direction, enu /* Nothing left to suppress. Bye! */ ast_framehook_detach(chan, suppress->framehook_id); ast_channel_datastore_remove(chan, datastore); + ast_datastore_free(datastore); } return 0;