Fix a use-after-free error on EV_CLOSURE_EVENT_FINALIZE callbacks

After running the callback, we were checking evcb->evcb_closure to
decide whether to call mm_free(ev).  But the callback itself might
have freed ev, so we need to grab that field first

Found with AddressSanitizer
This commit is contained in:
Nick Mathewson 2014-03-18 11:25:58 -04:00
parent 860c71c892
commit ec99dd82e4

View File

@ -1584,6 +1584,7 @@ event_process_active_single_queue(struct event_base *base,
case EV_CLOSURE_EVENT_FINALIZE: case EV_CLOSURE_EVENT_FINALIZE:
case EV_CLOSURE_EVENT_FINALIZE_FREE: { case EV_CLOSURE_EVENT_FINALIZE_FREE: {
void (*evcb_evfinalize)(struct event *, void *); void (*evcb_evfinalize)(struct event *, void *);
int evcb_closure = evcb->evcb_closure;
EVUTIL_ASSERT(ev != NULL); EVUTIL_ASSERT(ev != NULL);
base->current_event = NULL; base->current_event = NULL;
evcb_evfinalize = ev->ev_evcallback.evcb_cb_union.evcb_evfinalize; evcb_evfinalize = ev->ev_evcallback.evcb_cb_union.evcb_evfinalize;
@ -1591,7 +1592,7 @@ event_process_active_single_queue(struct event_base *base,
EVBASE_RELEASE_LOCK(base, th_base_lock); EVBASE_RELEASE_LOCK(base, th_base_lock);
evcb_evfinalize(ev, ev->ev_arg); evcb_evfinalize(ev, ev->ev_arg);
event_debug_note_teardown_(ev); event_debug_note_teardown_(ev);
if (evcb->evcb_closure == EV_CLOSURE_EVENT_FINALIZE_FREE) if (evcb_closure == EV_CLOSURE_EVENT_FINALIZE_FREE)
mm_free(ev); mm_free(ev);
} }
break; break;