summaryrefslogtreecommitdiff
path: root/main/features.c
diff options
context:
space:
mode:
authorRichard Mudgett <rmudgett@digium.com>2012-08-10 02:07:55 +0000
committerRichard Mudgett <rmudgett@digium.com>2012-08-10 02:07:55 +0000
commitca481359b9146145f07cca09e1fed7204404bb2b (patch)
treeed13ad4e1e0bc116fa364db0fe5f2308708f19aa /main/features.c
parent770988512576247fd3c66055c602f643ae45c831 (diff)
Fix pickup extension channel reference error.
You cannot unref a pointer and then expect to ref it again later. * Fix potential NULL pointer deref if the call pickup search fails. git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@371052 65c4cc65-6c06-0410-ace0-fbb531ad65f3
Diffstat (limited to 'main/features.c')
-rw-r--r--main/features.c24
1 files changed, 18 insertions, 6 deletions
diff --git a/main/features.c b/main/features.c
index 0794a2f94..48b733922 100644
--- a/main/features.c
+++ b/main/features.c
@@ -7718,27 +7718,38 @@ int ast_pickup_call(struct ast_channel *chan)
* Transfer all pickup-able channels to another container-iterator.
* Iterate it to find the oldest channel.
*/
- targets_it = (struct ao2_iterator *)ast_channel_callback(find_channel_by_group, NULL, chan, OBJ_MULTIPLE);
+ targets_it = (struct ao2_iterator *) ast_channel_callback(find_channel_by_group,
+ NULL, chan, OBJ_MULTIPLE);
+ if (!targets_it) {
+ /* Search really failed. */
+ goto no_pickup_calls;
+ }
target = NULL;
while ((candidate = ao2_iterator_next(targets_it))) {
- if (!target || ast_tvcmp(ast_channel_creationtime(candidate), ast_channel_creationtime(target)) < 0) {
+ if (!target) {
+ target = candidate;
+ continue;
+ }
+ if (ast_tvcmp(ast_channel_creationtime(candidate), ast_channel_creationtime(target)) < 0) {
+ ast_channel_unref(target);
target = candidate;
+ continue;
}
ast_channel_unref(candidate);
}
+ ao2_iterator_destroy(targets_it);
if (target) {
/* The found channel must be locked and ref'd. */
- ast_channel_lock(ast_channel_ref(target));
+ ast_channel_lock(target);
/* Recheck pickup ability */
if (!ast_can_pickup(target)) {
+ /* Someone else picked it up or the call went away. */
ast_channel_unlock(target);
- target = ast_channel_unref(target);/* Bad luck */
+ target = ast_channel_unref(target);
}
}
- ao2_iterator_destroy(targets_it);
-
if (target) {
ast_log(LOG_NOTICE, "pickup %s attempt by %s\n", ast_channel_name(target), ast_channel_name(chan));
@@ -7754,6 +7765,7 @@ int ast_pickup_call(struct ast_channel *chan)
target = ast_channel_unref(target);
}
+no_pickup_calls:
if (res < 0) {
ast_debug(1, "No call pickup possible... for %s\n", ast_channel_name(chan));
if (!ast_strlen_zero(pickupfailsound)) {