Changeset 242f280


Ignore:
Timestamp:
2016-02-18T11:17:08Z (4 years ago)
Author:
dequis <dx@…>
Branches:
master
Children:
0843bbe
Parents:
9456255
Message:

Fix a double free when calling proxy_disconnect() inside phb->func()

Fixes trac ticket #1248

proxy_connected() calls phb->func(), then tries to do phb_free() directly
afterwards, but that might have been freed by a proxy_disconnect() call
during the execution of that callback.

This one happened to several different people because some AIM server
broke recently.

This commit fixes it by implementing a phb_connected() function that
removes the PHB from the hash table before calling phb->func(), which
ensures that any proxy_disconnect() calls just close the fd and nothing
else.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • lib/proxy.c

    r9456255 r242f280  
    8787}
    8888
     89/* calls phb->func safely by ensuring that the phb struct doesn't exist in the
     90 * case that proxy_disconnect() is called down there */
     91static gboolean phb_connected(struct PHB *phb, gint source)
     92{
     93        /* save func and data here */
     94        b_event_handler func = phb->func;
     95        gpointer data = phb->data;
     96
     97        /* free the struct so that it can't be freed by the callback */
     98        phb_free(phb, TRUE);
     99
     100        /* if any proxy_disconnect() call happens here, it will use the
     101         * fd (still open), look it up in the hash table, get NULL, and
     102         * proceed to close the fd and do nothing else */
     103        func(data, source, B_EV_IO_READ);
     104
     105        return FALSE;
     106}
     107
    89108static gboolean proxy_connected(gpointer data, gint source, b_input_condition cond)
    90109{
     
    125144                phb->proxy_func(phb->proxy_data, source, B_EV_IO_READ);
    126145        } else {
    127                 phb->func(phb->data, source, B_EV_IO_READ);
    128                 phb_free(phb, TRUE);
     146                phb_connected(phb, source);
    129147        }
    130148
     
    222240        if ((memcmp(HTTP_GOODSTRING, inputline, strlen(HTTP_GOODSTRING)) == 0) ||
    223241            (memcmp(HTTP_GOODSTRING2, inputline, strlen(HTTP_GOODSTRING2)) == 0)) {
    224                 phb->func(phb->data, source, B_EV_IO_READ);
    225                 return phb_free(phb, TRUE);
     242                return phb_connected(phb, source);
    226243        }
    227244
     
    295312        memset(packet, 0, sizeof(packet));
    296313        if (read(source, packet, 9) >= 4 && packet[1] == 90) {
    297                 phb->func(phb->data, source, B_EV_IO_READ);
    298                 return phb_free(phb, TRUE);
     314                return phb_connected(phb, source);
    299315        }
    300316
     
    384400        }
    385401
    386         phb->func(phb->data, source, B_EV_IO_READ);
    387         return phb_free(phb, TRUE);
     402        return phb_connected(phb, source);
    388403}
    389404
Note: See TracChangeset for help on using the changeset viewer.