Ignore:
Timestamp:
Apr 2, 2018 2:53:48 AM (7 years ago)
Author:
riza
Message:

Fixed #2041: Prevent double free on Failed STUN resolution.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • pjproject/trunk/pjsip/src/pjsua-lib/pjsua_core.c

    r5755 r5762  
    12521252    pj_time_val timeout = {0, 0}; 
    12531253 
     1254    if (sess->destroy_flag) 
     1255        return; 
     1256 
    12541257    sess->destroy_flag = PJ_TRUE; 
    1255  
    1256     /* If the STUN resolution session is blocking, only the waiting thread 
    1257      * is allowed to destroy the session, otherwise it may cause deadlock. 
    1258      */ 
    1259     if (sess->blocking) { 
    1260         if (sess->waiter != pj_thread_this()) 
    1261             return; 
    1262  
    1263         /* Before destroying, make sure ref count is zero. */ 
    1264         while (sess->ref_cnt > 0) 
    1265             pj_thread_sleep(10); 
    1266  
    1267     } else if (sess->ref_cnt > 0) 
    1268         return; 
    1269  
    12701258    if (sess->stun_sock) { 
    12711259        pj_stun_sock_destroy(sess->stun_sock); 
     
    12911279static void stun_resolve_dec_ref(pjsua_stun_resolve *sess) 
    12921280{ 
    1293     --sess->ref_cnt; 
    1294     if (sess->ref_cnt <= 0 && sess->destroy_flag) 
    1295         destroy_stun_resolve(sess); 
     1281    int ref_cnt = --sess->ref_cnt; 
     1282    /* If the STUN resolution session is blocking, only the waiting thread 
     1283     * is allowed to destroy the session, otherwise it may cause deadlock. 
     1284     */ 
     1285    if ((ref_cnt > 0) || 
     1286        (sess->blocking && (sess->waiter != pj_thread_this())))  
     1287    { 
     1288        return; 
     1289    } 
     1290 
     1291    destroy_stun_resolve(sess); 
    12961292} 
    12971293 
     
    13331329on_return: 
    13341330    if (!sess->blocking) { 
    1335         destroy_stun_resolve(sess); 
     1331        stun_resolve_dec_ref(sess); 
    13361332    } 
    13371333} 
     
    15641560    sess->status = PJ_EPENDING; 
    15651561    sess->af = pj_AF_INET(); 
     1562    stun_resolve_add_ref(sess); 
    15661563    sess->srv = (pj_str_t*) pj_pool_calloc(pool, count, sizeof(pj_str_t)); 
    15671564    for (i=0; i<count; ++i) { 
     
    15841581    max_wait_ms = count * pjsua_var.stun_cfg.rto_msec * (1 << 7); 
    15851582    pj_get_timestamp(&start); 
    1586  
    1587     while (sess->status == PJ_EPENDING) { 
     1583     
     1584    while ((sess->status == PJ_EPENDING) && (!sess->destroy_flag)) { 
    15881585        /* If there is no worker thread or 
    15891586         * the function is called from the only worker thread, 
     
    16051602 
    16061603    status = sess->status; 
    1607     destroy_stun_resolve(sess); 
     1604    stun_resolve_dec_ref(sess); 
    16081605 
    16091606    return status; 
     
    16251622 
    16261623        if (sess->token == token) { 
     1624            sess->has_result = PJ_TRUE; 
     1625            sess->status = PJ_ECANCELLED; 
    16271626            if (notify_cb) { 
    16281627                pj_stun_resolve_result result; 
     
    16331632 
    16341633                sess->cb(&result); 
    1635             } 
    1636  
    1637             destroy_stun_resolve(sess); 
     1634            }        
    16381635            ++cancelled_count; 
    16391636        } 
Note: See TracChangeset for help on using the changeset viewer.