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

(closes issue #16045)
Reported by: bluecrow76
Patches:
      issue16045.diff uploaded by dvossel (license 671)
Tested by: bluecrow76, dvossel, habile


git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.4@228692 65c4cc65-6c06-0410-ace0-fbb531ad65f3
This commit is contained in:
David Vossel
2009-11-06 22:33:27 +00:00
parent 0eb5bea853
commit 8939eece6a

View File

@@ -2949,6 +2949,11 @@ int ast_write(struct ast_channel *chan, struct ast_frame *fr)
if (chan->audiohooks) { if (chan->audiohooks) {
struct ast_frame *prev = NULL, *new_frame, *cur, *dup; 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 /* 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 * an item in a list of frames, create a new list adding each cur frame back to it
@@ -2959,13 +2964,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, /* 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 */ * free the old frames, and set cur to be the new frame */
if (new_frame != cur) { if (new_frame != cur) {
/* doing an ast_frisolate here seems silly, but we are not guaranteed the new_frame /* 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 * 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 */ * times it may override the previous frame we got from it unless we dup it */
if ((dup = ast_frisolate(new_frame))) { if ((dup = ast_frisolate(new_frame))) {
AST_LIST_NEXT(dup, frame_list) = AST_LIST_NEXT(cur, frame_list); AST_LIST_NEXT(dup, frame_list) = AST_LIST_NEXT(cur, frame_list);
ast_frfree(new_frame); if (freeoldlist) {
AST_LIST_NEXT(cur, frame_list) = NULL;
ast_frfree(cur); ast_frfree(cur);
}
cur = dup; cur = dup;
} }
} }