Thread

Commits

Same data as JSON: GET /api/v1/messages/:b64id/commits the thread's linked commits as JSON, with link sources. API reference →
  1. Fix use-after-free of qs in AfterTriggerEndQuery.

  1. Server crash: Use-after-free in AfterTriggerEndQuery()

    amul sul <sulamul@gmail.com> — 2026-05-05T06:37:19Z

    Hi,
    
    The crash occurs when the per-query firing loop in
    AfterTriggerEndQuery() exits via the "all fired" path. If
    afterTriggerInvokeEvents() reallocated query_stack while firing, the
    loop's local qs pointer is left dangling, and the subsequent
    FireAfterTriggerBatchCallbacks(qs->batch_callbacks) reads
    batch_callbacks from the freed memory and crashes.
    
    Here is the reproducible test that has an AFTER INSERT trigger on a
    referenced table that recursively inserts rows into itself:
    
    --
    create table trigger_recursive_pk (id int primary key);
    create table trigger_recursive_fk (id int references trigger_recursive_pk(id));
    insert into trigger_recursive_pk select g from generate_series(1, 15) g;
    
    create function trigger_recursive_fn() returns trigger language plpgsql as $$
    begin
        if new.id < 10 then
            insert into trigger_recursive_fk values (new.id + 1);
        end if;
        return new;
    end$$;
    
    create trigger trigger_recursive after insert on trigger_recursive_fk
        for each row execute function trigger_recursive_fn();
    
    insert into trigger_recursive_fk values (1);
    --
    
    The attached patch fixes the reported issue by recomputing qs
    immediately before calling FireAfterTriggerBatchCallbacks().
    
    --
    Regards,
    Amul Sul
    EDB: http://www.enterprisedb.com
    
  2. Re: Server crash: Use-after-free in AfterTriggerEndQuery()

    amit <amitlangote09@gmail.com> — 2026-05-05T07:45:26Z

    On Tue, May 5, 2026 at 15:37 Amul Sul <sulamul@gmail.com> wrote:
    
    > Hi,
    >
    > The crash occurs when the per-query firing loop in
    > AfterTriggerEndQuery() exits via the "all fired" path. If
    > afterTriggerInvokeEvents() reallocated query_stack while firing, the
    > loop's local qs pointer is left dangling, and the subsequent
    > FireAfterTriggerBatchCallbacks(qs->batch_callbacks) reads
    > batch_callbacks from the freed memory and crashes.
    >
    > Here is the reproducible test that has an AFTER INSERT trigger on a
    > referenced table that recursively inserts rows into itself:
    >
    > --
    > create table trigger_recursive_pk (id int primary key);
    > create table trigger_recursive_fk (id int references
    > trigger_recursive_pk(id));
    > insert into trigger_recursive_pk select g from generate_series(1, 15) g;
    >
    > create function trigger_recursive_fn() returns trigger language plpgsql as
    > $$
    > begin
    >     if new.id < 10 then
    >         insert into trigger_recursive_fk values (new.id + 1);
    >     end if;
    >     return new;
    > end$$;
    >
    > create trigger trigger_recursive after insert on trigger_recursive_fk
    >     for each row execute function trigger_recursive_fn();
    >
    > insert into trigger_recursive_fk values (1);
    > --
    >
    > The attached patch fixes the reported issue by recomputing qs
    > immediately before calling FireAfterTriggerBatchCallbacks().
    
    
    Thanks Amul for the report. I'll look at this on Thursday when I'm back at
    work.
    
    - Amit
    
    >
    
  3. Re: Server crash: Use-after-free in AfterTriggerEndQuery()

    Anthonin Bonnefoy <anthonin.bonnefoy@datadoghq.com> — 2026-05-06T08:13:57Z

    Hi,
    
    On Tue, May 5, 2026 at 8:38 AM Amul Sul <sulamul@gmail.com> wrote:
    > Here is the reproducible test that has an AFTER INSERT trigger on a
    > referenced table that recursively inserts rows into itself:
    >
    > --
    > create table trigger_recursive_pk (id int primary key);
    > create table trigger_recursive_fk (id int references trigger_recursive_pk(id));
    > insert into trigger_recursive_pk select g from generate_series(1, 15) g;
    >
    > create function trigger_recursive_fn() returns trigger language plpgsql as $$
    > begin
    >     if new.id < 10 then
    >         insert into trigger_recursive_fk values (new.id + 1);
    >     end if;
    >     return new;
    > end$$;
    >
    > create trigger trigger_recursive after insert on trigger_recursive_fk
    >     for each row execute function trigger_recursive_fn();
    >
    > insert into trigger_recursive_fk values (1);
    > --
    
    I've managed to reproduce the issue on the current HEAD thanks to the
    script. Doing a git bissect, the failure was introduced with
    34a30786293005 when the batch_callbacks list was added.
    
    > The attached patch fixes the reported issue by recomputing qs
    > immediately before calling FireAfterTriggerBatchCallbacks().
    
    The patch fixes the issue and the change looks reasonable.
    
    Regards,
    Anthonin Bonnefoy
    
    
    
    
  4. Re: Server crash: Use-after-free in AfterTriggerEndQuery()

    amit <amitlangote09@gmail.com> — 2026-05-07T09:09:36Z

    Hi Anthonin,
    
    On Wed, May 6, 2026 at 5:14 PM Anthonin Bonnefoy
    <anthonin.bonnefoy@datadoghq.com> wrote:
    > On Tue, May 5, 2026 at 8:38 AM Amul Sul <sulamul@gmail.com> wrote:
    > > Here is the reproducible test that has an AFTER INSERT trigger on a
    > > referenced table that recursively inserts rows into itself:
    > >
    > > --
    > > create table trigger_recursive_pk (id int primary key);
    > > create table trigger_recursive_fk (id int references trigger_recursive_pk(id));
    > > insert into trigger_recursive_pk select g from generate_series(1, 15) g;
    > >
    > > create function trigger_recursive_fn() returns trigger language plpgsql as $$
    > > begin
    > >     if new.id < 10 then
    > >         insert into trigger_recursive_fk values (new.id + 1);
    > >     end if;
    > >     return new;
    > > end$$;
    > >
    > > create trigger trigger_recursive after insert on trigger_recursive_fk
    > >     for each row execute function trigger_recursive_fn();
    > >
    > > insert into trigger_recursive_fk values (1);
    > > --
    >
    > I've managed to reproduce the issue on the current HEAD thanks to the
    > script. Doing a git bissect, the failure was introduced with
    > 34a30786293005 when the batch_callbacks list was added.
    >
    > > The attached patch fixes the reported issue by recomputing qs
    > > immediately before calling FireAfterTriggerBatchCallbacks().
    >
    > The patch fixes the issue and the change looks reasonable.
    
    Thanks for the review.  I agree.
    
    Attached v2.  I simplified the test because the FK isn't really needed
    to reproduce the bug, since the use-after-free is the stale qs load
    itself.  Also reworded the comment above the recompute and tweaked the
    commit message a bit.
    
    Will push tomorrow barring objections.  Thanks again, Amul, for the patch.
    
    -- 
    Thanks, Amit Langote
    
  5. Re: Server crash: Use-after-free in AfterTriggerEndQuery()

    amit <amitlangote09@gmail.com> — 2026-05-08T00:55:19Z

    On Thu, May 7, 2026 at 6:09 PM Amit Langote <amitlangote09@gmail.com> wrote:
    > On Wed, May 6, 2026 at 5:14 PM Anthonin Bonnefoy
    > <anthonin.bonnefoy@datadoghq.com> wrote:
    > > On Tue, May 5, 2026 at 8:38 AM Amul Sul <sulamul@gmail.com> wrote:
    > > > Here is the reproducible test that has an AFTER INSERT trigger on a
    > > > referenced table that recursively inserts rows into itself:
    > > >
    > > > --
    > > > create table trigger_recursive_pk (id int primary key);
    > > > create table trigger_recursive_fk (id int references trigger_recursive_pk(id));
    > > > insert into trigger_recursive_pk select g from generate_series(1, 15) g;
    > > >
    > > > create function trigger_recursive_fn() returns trigger language plpgsql as $$
    > > > begin
    > > >     if new.id < 10 then
    > > >         insert into trigger_recursive_fk values (new.id + 1);
    > > >     end if;
    > > >     return new;
    > > > end$$;
    > > >
    > > > create trigger trigger_recursive after insert on trigger_recursive_fk
    > > >     for each row execute function trigger_recursive_fn();
    > > >
    > > > insert into trigger_recursive_fk values (1);
    > > > --
    > >
    > > I've managed to reproduce the issue on the current HEAD thanks to the
    > > script. Doing a git bissect, the failure was introduced with
    > > 34a30786293005 when the batch_callbacks list was added.
    > >
    > > > The attached patch fixes the reported issue by recomputing qs
    > > > immediately before calling FireAfterTriggerBatchCallbacks().
    > >
    > > The patch fixes the issue and the change looks reasonable.
    >
    > Thanks for the review.  I agree.
    >
    > Attached v2.  I simplified the test because the FK isn't really needed
    > to reproduce the bug, since the use-after-free is the stale qs load
    > itself.  Also reworded the comment above the recompute and tweaked the
    > commit message a bit.
    >
    > Will push tomorrow barring objections.  Thanks again, Amul, for the patch.
    
    Pushed.
    
    -- 
    Thanks, Amit Langote