diff options
author | Richard Mudgett <rmudgett@digium.com> | 2012-08-10 02:07:55 +0000 |
---|---|---|
committer | Richard Mudgett <rmudgett@digium.com> | 2012-08-10 02:07:55 +0000 |
commit | ca481359b9146145f07cca09e1fed7204404bb2b (patch) | |
tree | ed13ad4e1e0bc116fa364db0fe5f2308708f19aa /main/features.c | |
parent | 770988512576247fd3c66055c602f643ae45c831 (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.c | 24 |
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)) { |