From: David Vossel Date: Fri, 6 Nov 2009 22:38:05 +0000 (+0000) Subject: Merged revisions 228693 via svnmerge from X-Git-Tag: 1.6.0.18-rc2~5 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=f7d0b0d139dd8f4278c808cd0b9fcfadc92f6ed4;p=thirdparty%2Fasterisk.git Merged revisions 228693 via svnmerge from https://origsvn.digium.com/svn/asterisk/trunk ................ r228693 | dvossel | 2009-11-06 16:35:44 -0600 (Fri, 06 Nov 2009) | 16 lines Merged revisions 228692 via svnmerge from https://origsvn.digium.com/svn/asterisk/branches/1.4 ........ r228692 | dvossel | 2009-11-06 16:33:27 -0600 (Fri, 06 Nov 2009) | 9 lines fixes audiohook write crash occuring in chan_spy whisper mode. After writing to the audiohook list in ast_write(), frames were being freed incorrectly. Under certain conditions this resulted in a double free crash. (closes issue #16133) Reported by: wetwired ........ ................ git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.6.0@228696 65c4cc65-6c06-0410-ace0-fbb531ad65f3 --- diff --git a/main/channel.c b/main/channel.c index 9575f57632..6cffd331de 100644 --- a/main/channel.c +++ b/main/channel.c @@ -3470,6 +3470,11 @@ int ast_write(struct ast_channel *chan, struct ast_frame *fr) if (chan->audiohooks) { struct ast_frame *prev = NULL, *new_frame, *cur, *dup; + int freeoldlist = 0; + + if (f != fr) { + freeoldlist = 1; + } /* Since ast_audiohook_write may return a new frame, and the cur frame is * an item in a list of frames, create a new list adding each cur frame back to it @@ -3480,13 +3485,16 @@ int ast_write(struct ast_channel *chan, struct ast_frame *fr) /* if this frame is different than cur, preserve the end of the list, * free the old frames, and set cur to be the new frame */ if (new_frame != cur) { + /* doing an ast_frisolate here seems silly, but we are not guaranteed the new_frame * isn't part of local storage, meaning if ast_audiohook_write is called multiple * times it may override the previous frame we got from it unless we dup it */ if ((dup = ast_frisolate(new_frame))) { AST_LIST_NEXT(dup, frame_list) = AST_LIST_NEXT(cur, frame_list); - ast_frfree(new_frame); - ast_frfree(cur); + if (freeoldlist) { + AST_LIST_NEXT(cur, frame_list) = NULL; + ast_frfree(cur); + } cur = dup; } }