]> git.ipfire.org Git - thirdparty/asterisk.git/commitdiff
Merged revisions 228693 via svnmerge from
authorDavid Vossel <dvossel@digium.com>
Fri, 6 Nov 2009 22:38:05 +0000 (22:38 +0000)
committerDavid Vossel <dvossel@digium.com>
Fri, 6 Nov 2009 22:38:05 +0000 (22:38 +0000)
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

main/channel.c

index 9575f576322514b3b758f0fb431f448fff40820e..6cffd331de18eff5432dc791b00a1607928a91c5 100644 (file)
@@ -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;
                                        }
                                }