• Tom Lane's avatar
    Fix possible dangling pointer dereference in trigger.c. · 27c6619e
    Tom Lane authored
    AfterTriggerEndQuery correctly notes that the query_stack could get
    repalloc'd during a trigger firing, but it nonetheless passes the address
    of a query_stack entry to afterTriggerInvokeEvents, so that if such a
    repalloc occurs, afterTriggerInvokeEvents is already working with an
    obsolete dangling pointer while it scans the rest of the events.  Oops.
    The only code at risk is its "delete_ok" cleanup code, so we can
    prevent unsafe behavior by passing delete_ok = false instead of true.
    
    However, that could have a significant performance penalty, because the
    point of passing delete_ok = true is to not have to re-scan possibly
    a large number of dead trigger events on the next time through the loop.
    There's more than one way to skin that cat, though.  What we can do is
    delete all the "chunks" in the event list except the last one, since
    we know all events in them must be dead.  Deleting the chunks is work
    we'd have had to do later in AfterTriggerEndQuery anyway, and it ends
    up saving rescanning of just about the same events we'd have gotten
    rid of with delete_ok = true.
    
    In v10 and HEAD, we also have to be careful to mop up any per-table
    after_trig_events pointers that would become dangling.  This is slightly
    annoying, but I don't think that normal use-cases will traverse this code
    path often enough for it to be a performance problem.
    
    It's pretty hard to hit this in practice because of the unlikelihood
    of the query_stack getting resized at just the wrong time.  Nonetheless,
    it's definitely a live bug of ancient standing, so back-patch to all
    supported branches.
    
    Discussion: https://postgr.es/m/2891.1505419542@sss.pgh.pa.us
    27c6619e
trigger.c 177 KB