]> git.ipfire.org Git - thirdparty/asterisk.git/commitdiff
If the datastore has been moved to another channel due to a masquerade, then
authorMark Michelson <mmichelson@digium.com>
Mon, 14 Apr 2008 16:24:22 +0000 (16:24 +0000)
committerMark Michelson <mmichelson@digium.com>
Mon, 14 Apr 2008 16:24:22 +0000 (16:24 +0000)
freeing the datastore here causes an eventual double free when the new channel
hangs up. We should only free the datastore if we were able to successfully remove
it from the channel we are referencing (i.e. the datastore was not moved).

(closes issue #12359)
Reported by: pguido

git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.4@114112 65c4cc65-6c06-0410-ace0-fbb531ad65f3

apps/app_dial.c
apps/app_queue.c

index 2d5bf093828b079b12b857b94e1e8a3c6f6312dd..e9189b4bf667793e53e60c35fd3ac93b6f0637d1 100644 (file)
@@ -1320,8 +1320,14 @@ static int dial_exec_full(struct ast_channel *chan, void *data, struct ast_flags
        time(&start_time);
        peer = wait_for_answer(chan, outgoing, &to, peerflags, &sentringing, status, sizeof(status), numbusy, numnochan, numcongestion, ast_test_flag(&opts, OPT_PRIORITY_JUMP), &result);
 
-       ast_channel_datastore_remove(chan, datastore);
-       ast_channel_datastore_free(datastore);
+       /* The ast_channel_datastore_remove() function could fail here if the
+        * datastore was moved to another channel during a masquerade. If this is
+        * the case, don't free the datastore here because later, when the channel
+        * to which the datastore was moved hangs up, it will attempt to free this
+        * datastore again, causing a crash
+        */
+       if (!ast_channel_datastore_remove(chan, datastore))
+               ast_channel_datastore_free(datastore);
        if (!peer) {
                if (result) {
                        res = result;
index 36ba8e21319581a66f3ecc3d0b0d9fe93ec7c67e..d35ece846a4fe7333fb15661ef8225a3fe2d0bdc 100644 (file)
@@ -2753,8 +2753,13 @@ static int try_calling(struct queue_ent *qe, const char *options, char *announce
        if (use_weight)
                AST_LIST_UNLOCK(&queues);
        lpeer = wait_for_answer(qe, outgoing, &to, &digit, numbusies, ast_test_flag(&(bridge_config.features_caller), AST_FEATURE_DISCONNECT), forwardsallowed);
-       if (datastore) {
-               ast_channel_datastore_remove(qe->chan, datastore);
+       /* The ast_channel_datastore_remove() function could fail here if the
+        * datastore was moved to another channel during a masquerade. If this is
+        * the case, don't free the datastore here because later, when the channel
+        * to which the datastore was moved hangs up, it will attempt to free this
+        * datastore again, causing a crash
+        */
+       if (datastore && !ast_channel_datastore_remove(qe->chan, datastore)) {
                ast_channel_datastore_free(datastore);
        }
        ast_mutex_lock(&qe->parent->lock);