Audit of ao2_iterator_init() usage for v1.8.
authorRichard Mudgett <rmudgett@digium.com>
Fri, 27 Jan 2012 18:47:16 +0000 (18:47 +0000)
committerRichard Mudgett <rmudgett@digium.com>
Fri, 27 Jan 2012 18:47:16 +0000 (18:47 +0000)
Fixes numerous reference leaks and missing ao2_iterator_destroy() calls as
a result.

Review: https://reviewboard.asterisk.org/r/1697/
........

Merged revisions 352955 from http://svn.asterisk.org/svn/asterisk/branches/1.8
........

Merged revisions 352956 from http://svn.asterisk.org/svn/asterisk/branches/10

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

apps/app_chanspy.c
apps/app_queue.c
channels/chan_iax2.c
channels/chan_sip.c
include/asterisk/indications.h
main/indications.c
main/pbx.c
main/taskprocessor.c
res/res_odbc.c
res/res_srtp.c
res/snmp/agent.c

index 54e4736..4c709cf 100644 (file)
@@ -828,11 +828,13 @@ static int common_exec(struct ast_channel *chan, struct ast_flags *flags,
                }
 
                if (!iter) {
-                       return -1;
+                       res = -1;
+                       goto exit;
                }
 
                res = ast_waitfordigit(chan, waitms);
                if (res < 0) {
+                       iter = ast_channel_iterator_destroy(iter);
                        ast_clear_flag(chan, AST_FLAG_SPYING);
                        break;
                }
@@ -840,10 +842,12 @@ static int common_exec(struct ast_channel *chan, struct ast_flags *flags,
                        char tmp[2];
                        tmp[0] = res;
                        tmp[1] = '\0';
-                       if (!ast_goto_if_exists(chan, exitcontext, tmp, 1))
+                       if (!ast_goto_if_exists(chan, exitcontext, tmp, 1)) {
+                               iter = ast_channel_iterator_destroy(iter);
                                goto exit;
-                       else
+                       } else {
                                ast_debug(2, "Exit by single digit did not work in chanspy. Extension %s does not exist in context %s\n", tmp, exitcontext);
+                       }
                }
 
                /* reset for the next loop around, unless overridden later */
@@ -982,10 +986,12 @@ static int common_exec(struct ast_channel *chan, struct ast_flags *flags,
 
                        if (res == -1) {
                                ast_autochan_destroy(autochan);
+                               iter = ast_channel_iterator_destroy(iter);
                                goto exit;
                        } else if (res == -2) {
                                res = 0;
                                ast_autochan_destroy(autochan);
+                               iter = ast_channel_iterator_destroy(iter);
                                goto exit;
                        } else if (res > 1 && spec) {
                                struct ast_channel *next;
@@ -1005,6 +1011,7 @@ static int common_exec(struct ast_channel *chan, struct ast_flags *flags,
                                        }
                                }
                        } else if (res == 0 && ast_test_flag(flags, OPTION_EXITONHANGUP)) {
+                               iter = ast_channel_iterator_destroy(iter);
                                goto exit;
                        }
                }
index 0f192ac..84f0757 100644 (file)
@@ -1426,9 +1426,9 @@ static int get_member_status(struct call_queue *q, int max_penalty, int min_pena
                                ast_debug(4, "%s is unavailable because it has only been %d seconds since his last call (wrapup time is %d)\n", member->membername, (int) (time(NULL) - member->lastcall), q->wrapuptime);
                                break;
                        } else {
-                               ao2_unlock(q);
                                ao2_ref(member, -1);
                                ao2_iterator_destroy(&mem_iter);
+                               ao2_unlock(q);
                                ast_debug(4, "%s is available.\n", member->membername);
                                return 0;
                        }
@@ -4560,24 +4560,24 @@ static int try_calling(struct queue_ent *qe, const char *options, char *announce
                AST_LIST_HEAD(, ast_dialed_interface) *dialed_interfaces;
                if (!tmp) {
                        ao2_ref(cur, -1);
-                       ao2_unlock(qe->parent);
                        ao2_iterator_destroy(&memi);
+                       ao2_unlock(qe->parent);
                        goto out;
                }
                if (!datastore) {
                        if (!(datastore = ast_datastore_alloc(&dialed_interface_info, NULL))) {
+                               callattempt_free(tmp);
                                ao2_ref(cur, -1);
-                               ao2_unlock(qe->parent);
                                ao2_iterator_destroy(&memi);
-                               callattempt_free(tmp);
+                               ao2_unlock(qe->parent);
                                goto out;
                        }
                        datastore->inheritance = DATASTORE_INHERIT_FOREVER;
                        if (!(dialed_interfaces = ast_calloc(1, sizeof(*dialed_interfaces)))) {
+                               callattempt_free(tmp);
                                ao2_ref(cur, -1);
-                               ao2_unlock(&qe->parent);
                                ao2_iterator_destroy(&memi);
-                               callattempt_free(tmp);
+                               ao2_unlock(&qe->parent);
                                goto out;
                        }
                        datastore->data = dialed_interfaces;
@@ -4601,6 +4601,7 @@ static int try_calling(struct queue_ent *qe, const char *options, char *announce
 
                if (di) {
                        callattempt_free(tmp);
+                       ao2_ref(cur, -1);
                        continue;
                }
 
@@ -4610,10 +4611,10 @@ static int try_calling(struct queue_ent *qe, const char *options, char *announce
                 * it won't call one that has already been called. */
                if (strncasecmp(cur->interface, "Local/", 6)) {
                        if (!(di = ast_calloc(1, sizeof(*di) + strlen(cur->interface)))) {
+                               callattempt_free(tmp);
                                ao2_ref(cur, -1);
-                               ao2_unlock(qe->parent);
                                ao2_iterator_destroy(&memi);
-                               callattempt_free(tmp);
+                               ao2_unlock(qe->parent);
                                goto out;
                        }
                        strcpy(di->interface, cur->interface);
@@ -6623,9 +6624,10 @@ static int queue_function_queuememberlist(struct ast_channel *chan, const char *
 
        if ((q = ao2_t_find(queues, &tmpq, OBJ_POINTER, "Find for QUEUE_MEMBER_LIST()"))) {
                int buflen = 0, count = 0;
-               struct ao2_iterator mem_iter = ao2_iterator_init(q->members, 0);
+               struct ao2_iterator mem_iter;
 
                ao2_lock(q);
+               mem_iter = ao2_iterator_init(q->members, 0);
                while ((m = ao2_iterator_next(&mem_iter))) {
                        /* strcat() is always faster than printf() */
                        if (count++) {
@@ -7148,7 +7150,9 @@ static int reload_queues(int reload, struct ast_flags *mask, const char *queuena
 static int clear_stats(const char *queuename)
 {
        struct call_queue *q;
-       struct ao2_iterator queue_iter = ao2_iterator_init(queues, 0);
+       struct ao2_iterator queue_iter;
+
+       queue_iter = ao2_iterator_init(queues, 0);
        while ((q = ao2_t_iterator_next(&queue_iter, "Iterate through queues"))) {
                ao2_lock(q);
                if (ast_strlen_zero(queuename) || !strcasecmp(q->name, queuename))
@@ -7237,8 +7241,8 @@ static char *__queues_show(struct mansession *s, int fd, int argc, const char *
                }
        }
 
-       queue_iter = ao2_iterator_init(queues, AO2_ITERATOR_DONTLOCK);
        ao2_lock(queues);
+       queue_iter = ao2_iterator_init(queues, AO2_ITERATOR_DONTLOCK);
        while ((q = ao2_t_iterator_next(&queue_iter, "Iterate through queues"))) {
                float sl;
                struct call_queue *realtime_queue = NULL;
@@ -7967,11 +7971,11 @@ static char *complete_queue_remove_member(const char *line, const char *word, in
                while ((m = ao2_iterator_next(&mem_iter))) {
                        if (!strncasecmp(word, m->membername, wordlen) && ++which > state) {
                                char *tmp;
-                               ao2_unlock(q);
                                tmp = ast_strdup(m->interface);
                                ao2_ref(m, -1);
-                               queue_t_unref(q, "Done with iterator, returning interface name");
                                ao2_iterator_destroy(&mem_iter);
+                               ao2_unlock(q);
+                               queue_t_unref(q, "Done with iterator, returning interface name");
                                ao2_iterator_destroy(&queue_iter);
                                return tmp;
                        }
@@ -8524,6 +8528,7 @@ static void queues_data_provider_get_helper(const struct ast_data_search *search
 
                ao2_ref(member, -1);
        }
+       ao2_iterator_destroy(&im);
 
        /* include the callers inside the result. */
        if (queue->head) {
index 2255801..9d442d5 100644 (file)
@@ -2636,6 +2636,7 @@ static char *handle_cli_iax2_show_callno_limits(struct ast_cli_entry *e, int cmd
                        sin.sin_addr.s_addr = peercnt->addr;
                        if (a->argc == 5 && (!strcasecmp(a->argv[4], ast_inet_ntoa(sin.sin_addr)))) {
                                        ast_cli(a->fd, "%-15s %-12d %-12d\n", ast_inet_ntoa(sin.sin_addr), peercnt->cur, peercnt->limit);
+                                       ao2_ref(peercnt, -1);
                                        found = 1;
                                        break;
                        } else {
@@ -6680,8 +6681,7 @@ static char *handle_cli_iax2_show_users(struct ast_cli_entry *e, int cmd, struct
 
        ast_cli(a->fd, FORMAT, "Username", "Secret", "Authen", "Def.Context", "A/C","Codec Pref");
        i = ao2_iterator_init(users, 0);
-       for (user = ao2_iterator_next(&i); user; 
-               user_unref(user), user = ao2_iterator_next(&i)) {
+       for (; (user = ao2_iterator_next(&i)); user_unref(user)) {
                if (havepattern && regexec(&regexbuf, user->name, 0, NULL, 0))
                        continue;
 
@@ -6769,8 +6769,7 @@ static int __iax2_show_peers(int fd, int *total, struct mansession *s, const int
                ast_cli(fd, FORMAT2, "Name/Username", "Host", "   ", "Mask", "Port", "   ", "Status", "Description");
 
        i = ao2_iterator_init(peers, 0);
-       for (peer = ao2_iterator_next(&i); peer;
-               peer_unref(peer), peer = ao2_iterator_next(&i)) {
+       for (; (peer = ao2_iterator_next(&i)); peer_unref(peer)) {
                char nm[20];
                char status[20];
                int retstatus;
@@ -7093,7 +7092,7 @@ static int manager_iax2_show_peer_list(struct mansession *s, const struct messag
 
 
        i = ao2_iterator_init(peers, 0);
-       for (peer = ao2_iterator_next(&i); peer; peer_unref(peer), peer = ao2_iterator_next(&i)) {
+       for (; (peer = ao2_iterator_next(&i)); peer_unref(peer)) {
                encmethods_to_str(peer->encmethods, encmethods);
                astman_append(s, "Event: PeerEntry\r\n%sChanneltype: IAX\r\n", idtext);
                if (!ast_strlen_zero(peer->username)) {
@@ -7676,8 +7675,8 @@ static int check_access(int callno, struct sockaddr_in *sin, struct iax_ies *ies
                return res;
        }
        /* Search the userlist for a compatible entry, and fill in the rest */
-       i = ao2_iterator_init(users, 0);
        ast_sockaddr_from_sin(&addr, sin);
+       i = ao2_iterator_init(users, 0);
        while ((user = ao2_iterator_next(&i))) {
                if ((ast_strlen_zero(iaxs[callno]->username) ||                         /* No username specified */
                        !strcmp(iaxs[callno]->username, user->name))    /* Or this username specified */
@@ -14681,10 +14680,9 @@ static int users_data_provider_get(const struct ast_data_search *search,
        char *pstr = "";
 
        i = ao2_iterator_init(users, 0);
-       while ((user = ao2_iterator_next(&i))) {
+       for (; (user = ao2_iterator_next(&i)); user_unref(user)) {
                data_user = ast_data_add_node(data_root, "user");
                if (!data_user) {
-                       user_unref(user);
                        continue;
                }
 
@@ -14733,8 +14731,6 @@ static int users_data_provider_get(const struct ast_data_search *search,
                }
                ast_data_add_str(data_user, "codec-preferences", pstr);
 
-               user_unref(user);
-
                if (!ast_data_search_match(search, data_user)) {
                        ast_data_remove_node(data_root, data_user);
                }
index a5634fe..73a4b74 100644 (file)
@@ -17639,8 +17639,8 @@ static char *sip_prune_realtime(struct ast_cli_entry *e, int cmd, struct ast_cli
                        while ((pi = ao2_t_iterator_next(&i, "iterate thru peers table"))) {
                                ao2_lock(pi);
                                if (name && regexec(&regexbuf, pi->name, 0, NULL, 0)) {
-                                       sip_unref_peer(pi, "toss iterator peer ptr before continue");
                                        ao2_unlock(pi);
+                                       sip_unref_peer(pi, "toss iterator peer ptr before continue");
                                        continue;
                                };
                                if (ast_test_flag(&pi->flags[1], SIP_PAGE2_RTCACHEFRIENDS)) {
@@ -31103,6 +31103,8 @@ static int peers_data_provider_get(const struct ast_data_search *search,
                /* transfer mode */
                enum_node = ast_data_add_node(data_peer, "allowtransfer");
                if (!enum_node) {
+                       ao2_unlock(peer);
+                       ao2_ref(peer, -1);
                        continue;
                }
                ast_data_add_str(enum_node, "text", transfermode2str(peer->allowtransfer));
@@ -31142,6 +31144,8 @@ static int peers_data_provider_get(const struct ast_data_search *search,
                /* amaflags */
                enum_node = ast_data_add_node(data_peer, "amaflags");
                if (!enum_node) {
+                       ao2_unlock(peer);
+                       ao2_ref(peer, -1);
                        continue;
                }
                ast_data_add_int(enum_node, "value", peer->amaflags);
@@ -31150,6 +31154,8 @@ static int peers_data_provider_get(const struct ast_data_search *search,
                /* sip options */
                data_sip_options = ast_data_add_node(data_peer, "sipoptions");
                if (!data_sip_options) {
+                       ao2_unlock(peer);
+                       ao2_ref(peer, -1);
                        continue;
                }
                for (x = 0 ; x < ARRAY_LEN(sip_options); x++) {
@@ -31159,6 +31165,8 @@ static int peers_data_provider_get(const struct ast_data_search *search,
                /* callingpres */
                enum_node = ast_data_add_node(data_peer, "callingpres");
                if (!enum_node) {
+                       ao2_unlock(peer);
+                       ao2_ref(peer, -1);
                        continue;
                }
                ast_data_add_int(enum_node, "value", peer->callingpres);
index 13422d9..b02be1f 100644 (file)
@@ -176,7 +176,8 @@ int ast_tone_zone_count(void);
 /*!
  * \brief Get an iterator for the available tone zones
  *
- * Use ao2_iterator_next() to iterate the tone zones.
+ * \note Use ao2_iterator_next() to iterate the tone zones.
+ * \note Use ao2_iterator_destroy() to clean up.
  *
  * \return an initialized iterator
  */
index ef98407..b07de4b 100644 (file)
@@ -658,6 +658,7 @@ static char *complete_country(struct ast_cli_args *a)
                        break;
                }
        }
+       ao2_iterator_destroy(&i);
 
        return res;
 }
@@ -835,6 +836,7 @@ static char *handle_cli_indication_show(struct ast_cli_entry *e, int cmd, struct
                        ast_tone_zone_unlock(tz);
                        tz = ast_tone_zone_unref(tz);
                }
+               ao2_iterator_destroy(&iter);
                return CLI_SUCCESS;
        }
 
index 204eb88..e565c48 100644 (file)
@@ -7605,6 +7605,7 @@ void ast_merge_contexts_and_delete(struct ast_context **extcontexts, struct ast_
                        AST_LIST_INSERT_HEAD(&hints_stored, saved_hint, list);
                }
        }
+       ao2_iterator_destroy(&i);
 
        /* save the old table and list */
        oldtable = contexts_table;
index e0d7e5b..782a344 100644 (file)
@@ -173,6 +173,7 @@ static char *tps_taskprocessor_tab_complete(struct ast_taskprocessor *p, struct
                }
                ao2_ref(p, -1);
        }
+       ao2_iterator_destroy(&i);
        return name;
 }
 
@@ -266,6 +267,7 @@ static char *cli_tps_report(struct ast_cli_entry *e, int cmd, struct ast_cli_arg
                ast_cli(a->fd, "\n%24s   %17ld %12ld %12ld", name, processed, qsize, maxqsize);
                ao2_ref(p, -1);
        }
+       ao2_iterator_destroy(&i);
        tcount = ao2_container_count(tps_singletons); 
        ast_cli(a->fd, "\n\t+---------------------+-----------------+------------+-------------+\n\t%d taskprocessors\n\n", tcount);
        return CLI_SUCCESS;     
index 1770bb3..463bf9f 100644 (file)
@@ -911,7 +911,7 @@ static int load_odbc_config(void)
 
 static char *handle_cli_odbc_show(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 {
-       struct ao2_iterator aoi = ao2_iterator_init(class_container, 0);
+       struct ao2_iterator aoi;
        struct odbc_class *class;
        struct odbc_obj *current;
        int length = 0;
@@ -930,6 +930,7 @@ static char *handle_cli_odbc_show(struct ast_cli_entry *e, int cmd, struct ast_c
                if (a->pos != 2)
                        return NULL;
                length = strlen(a->word);
+               aoi = ao2_iterator_init(class_container, 0);
                while ((class = ao2_iterator_next(&aoi))) {
                        if (!strncasecmp(a->word, class->name, length) && ++which > a->n) {
                                ret = ast_strdup(class->name);
@@ -1722,12 +1723,14 @@ static int data_odbc_provider_handler(const struct ast_data_search *search,
 
                        ao2_ref(current, -1);
                }
+               ao2_iterator_destroy(&aoi2);
                ao2_ref(class, -1);
 
                if (!ast_data_search_match(search, data_odbc_class)) {
                        ast_data_remove_node(root, data_odbc_class);
                }
        }
+       ao2_iterator_destroy(&aoi);
        return 0;
 }
 
index a232314..a22a020 100644 (file)
@@ -322,7 +322,7 @@ static int ast_srtp_unprotect(struct ast_srtp *srtp, void *buf, int *len, int rt
        int retry = 0;
        struct ast_rtp_instance_stats stats = {0,};
 
-       tryagain:
+tryagain:
 
        for (i = 0; i < 2; i++) {
                res = rtcp ? srtp_unprotect_rtcp(srtp->session, buf, len) : srtp_unprotect(srtp->session, buf, len);
@@ -348,38 +348,42 @@ static int ast_srtp_unprotect(struct ast_srtp *srtp, void *buf, int *len, int rt
                if (srtp->session) {
                        struct ast_srtp_policy *policy;
                        struct ao2_iterator it;
-                       int policies_count = 0;
-                       
+                       int policies_count;
+
                        // dealloc first
                        ast_log(LOG_WARNING, "SRTP destroy before re-create\n");
                        srtp_dealloc(srtp->session);
-                       
+
                        // get the count
                        policies_count = ao2_container_count(srtp->policies);
-                       
+
                        // get the first to build up
                        it = ao2_iterator_init(srtp->policies, 0);
                        policy = ao2_iterator_next(&it);
 
                        ast_log(LOG_WARNING, "SRTP try to re-create\n");
-                       if (srtp_create(&srtp->session, &policy->sp) == err_status_ok) {
-                               ast_log(LOG_WARNING, "SRTP re-created with first policy\n");
-                               
-                               // unref first element
-                               ao2_t_ref(policy, -1, "Unreffing first policy for re-creating srtp session");
-                               
-                               // if we have more than one policy, add them afterwards 
-                               if (policies_count > 1) {
-                                       ast_log(LOG_WARNING, "Add all the other %d policies\n", policies_count-1);
-                                       while ((policy = ao2_iterator_next(&it))) {
-                                               srtp_add_stream(srtp->session, &policy->sp);
-                                               ao2_t_ref(policy, -1, "Unreffing n-th policy for re-creating srtp session");
+                       if (policy) {
+                               if (srtp_create(&srtp->session, &policy->sp) == err_status_ok) {
+                                       ast_log(LOG_WARNING, "SRTP re-created with first policy\n");
+
+                                       // unref first element
+                                       ao2_t_ref(policy, -1, "Unreffing first policy for re-creating srtp session");
+
+                                       // if we have more than one policy, add them afterwards
+                                       if (policies_count > 1) {
+                                               ast_log(LOG_WARNING, "Add all the other %d policies\n",
+                                                       policies_count - 1);
+                                               while ((policy = ao2_iterator_next(&it))) {
+                                                       srtp_add_stream(srtp->session, &policy->sp);
+                                                       ao2_t_ref(policy, -1, "Unreffing n-th policy for re-creating srtp session");
+                                               }
                                        }
+
+                                       retry++;
+                                       ao2_iterator_destroy(&it);
+                                       goto tryagain;
                                }
-                               
-                               retry++;
-                               ao2_iterator_destroy(&it);
-                               goto tryagain;
+                               ao2_t_ref(policy, -1, "Unreffing first policy after srtp_create failed");
                        }
                        ao2_iterator_destroy(&it);
                }
index 153106e..71f0213 100644 (file)
@@ -703,6 +703,7 @@ static u_char *ast_var_indications(struct variable *vp, oid *name, size_t *lengt
                        tz = ast_tone_zone_unref(tz);
                        long_ret++;
                }
+               ao2_iterator_destroy(&i);
 
                return (u_char *) &long_ret;
        }
@@ -743,6 +744,7 @@ static u_char *ast_var_indications_table(struct variable *vp, oid *name, size_t
                tz = ast_tone_zone_unref(tz);
                i--;
        }
+       ao2_iterator_destroy(&iter);
 
        if (tz == NULL) {
                return NULL;
@@ -750,24 +752,27 @@ static u_char *ast_var_indications_table(struct variable *vp, oid *name, size_t
 
        switch (vp->magic) {
        case ASTINDINDEX:
+               ast_tone_zone_unref(tz);
                long_ret = name[*length - 1];
                return (u_char *)&long_ret;
        case ASTINDCOUNTRY:
                ast_copy_string(ret_buf, tz->country, sizeof(ret_buf));
-               tz = ast_tone_zone_unref(tz);
+               ast_tone_zone_unref(tz);
                *var_len = strlen(ret_buf);
                return (u_char *) ret_buf;
        case ASTINDALIAS:
                /* No longer exists */
+               ast_tone_zone_unref(tz);
                return NULL;
        case ASTINDDESCRIPTION:
                ast_tone_zone_lock(tz);
                ast_copy_string(ret_buf, tz->description, sizeof(ret_buf));
                ast_tone_zone_unlock(tz);
-               tz = ast_tone_zone_unref(tz);
+               ast_tone_zone_unref(tz);
                *var_len = strlen(ret_buf);
                return (u_char *) ret_buf;
        default:
+               ast_tone_zone_unref(tz);
                break;
        }
        return NULL;