aboutsummaryrefslogtreecommitdiffstats
path: root/main
diff options
context:
space:
mode:
authordvossel <dvossel@f38db490-d61c-443f-a65b-d21fe96a405b>2009-11-06 22:38:05 +0000
committerdvossel <dvossel@f38db490-d61c-443f-a65b-d21fe96a405b>2009-11-06 22:38:05 +0000
commit0ff5b77847c9bccecd8221784ae1edde73775621 (patch)
tree42cfc6a16b6d25ba379d2d0a4c0dc6086ea86199 /main
parent26d2b763945787b7d04485d50f65730202ea2f51 (diff)
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: http://svn.digium.com/svn/asterisk/branches/1.6.0@228696 f38db490-d61c-443f-a65b-d21fe96a405b
Diffstat (limited to 'main')
-rw-r--r--main/channel.c12
1 files changed, 10 insertions, 2 deletions
diff --git a/main/channel.c b/main/channel.c
index 9575f5763..6cffd331d 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;
}
}