]> git.ipfire.org Git - thirdparty/asterisk.git/commitdiff
Astobj2: Correctly treat hash_fn returning INT_MIN 32/532/3
authorIvan Poddubny <ivan.poddubny@gmail.com>
Sun, 24 May 2015 18:47:16 +0000 (21:47 +0300)
committerIvan Poddubny <ivan.poddubny@gmail.com>
Mon, 25 May 2015 07:12:59 +0000 (10:12 +0300)
The code in astobj2_hash.c wrongly assumed that abs(int) is always > 0.
However, abs(INT_MIN) = INT_MIN and is still negative, as well as
abs(INT_MIN) % num_buckets, and as a result this led to a crash.

One way to trigger the bug is using host=::80 or 0.0.0.128 in peer
configuration section in chan_sip or chan_iax.

This patch takes the remainder before applying abs, so that bucket
number is always in range.

ASTERISK-25100 #close
Reported by: Mark Petersen

Change-Id: Id6981400ad526f47e10bcf7b847b62bd2785e899

main/astobj2.c

index b49ed60817402e5529ebaa5c8c49e075e96d67a3..c434209d61031a039e8422b934d69c686d1e1fc9 100644 (file)
@@ -900,7 +900,7 @@ static struct bucket_entry *internal_ao2_link(struct ao2_container *c, void *use
                return NULL;
        }
 
-       i = abs(c->hash_fn(user_data, OBJ_POINTER));
+       i = abs(c->hash_fn(user_data, OBJ_POINTER) % c->n_buckets);
 
        if (flags & OBJ_NOLOCK) {
                orig_lock = adjust_lock(c, AO2_LOCK_REQ_WRLOCK, 1);
@@ -909,7 +909,6 @@ static struct bucket_entry *internal_ao2_link(struct ao2_container *c, void *use
                orig_lock = AO2_LOCK_REQ_MUTEX;
        }
 
-       i %= c->n_buckets;
        p->astobj = obj;
        p->version = ast_atomic_fetchadd_int(&c->version, 1);
        AST_LIST_INSERT_TAIL(&c->buckets[i], p, entry);
@@ -1065,7 +1064,7 @@ static void *internal_ao2_callback(struct ao2_container *c, enum search_flags fl
         */
        if ((flags & (OBJ_POINTER | OBJ_KEY))) {
                /* we know hash can handle this case */
-               start = i = c->hash_fn(arg, flags & (OBJ_POINTER | OBJ_KEY)) % c->n_buckets;
+               start = i = abs(c->hash_fn(arg, flags & (OBJ_POINTER | OBJ_KEY)) % c->n_buckets);
        } else {
                /* don't know, let's scan all buckets */
                start = i = -1;         /* XXX this must be fixed later. */