Language: C
Label: safe
CWE: CWE-416 \u2014 Use After Free
Referencing memory after it has been freed can cause a program to crash, use unexpected values, or execute code.

Code:
static pj_status_t transport_destroy(pjmedia_transport *tp)
{
    struct transport_udp *udp = (struct transport_udp*) tp;

    /* Sanity check */
    PJ_ASSERT_RETURN(tp, PJ_EINVAL);

    /* Must not close while application is using this */
    //PJ_ASSERT_RETURN(!udp->attached, PJ_EINVALIDOP);

    /* The following calls to pj_ioqueue_unregister() will block the execution
     * if callback is still being called because allow_concurrent is false.
     * So it is safe to release the pool immediately after.
     */

    if (udp->rtp_key) {
        pj_ioqueue_unregister(udp->rtp_key);
        udp->rtp_key = NULL;
        udp->rtp_sock = PJ_INVALID_SOCKET;
    } else if (udp->rtp_sock != PJ_INVALID_SOCKET) {
        pj_sock_close(udp->rtp_sock);
        udp->rtp_sock = PJ_INVALID_SOCKET;
    }

    if (udp->rtcp_key) {
        pj_ioqueue_unregister(udp->rtcp_key);
        udp->rtcp_key = NULL;
        udp->rtcp_sock = PJ_INVALID_SOCKET;
    } else if (udp->rtcp_sock != PJ_INVALID_SOCKET) {
        pj_sock_close(udp->rtcp_sock);
        udp->rtcp_sock = PJ_INVALID_SOCKET;
    }

    pj_grp_lock_dec_ref(tp->grp_lock);

    PJ_LOG(4,(udp->base.name, "UDP media transport destroyed"));
    pj_pool_release(udp->pool);

    return PJ_SUCCESS;
}