Thread: [BUGS] BUG #14809: Heap Corruption with deeply nested triggers.

[BUGS] BUG #14809: Heap Corruption with deeply nested triggers.

From
matthew.r.maurer@gmail.com
Date:
The following bug has been logged on the website:

Bug reference:      14809
Logged by:          Matthew Maurer
Email address:      matthew.r.maurer@gmail.com
PostgreSQL version: 9.6.5
Operating system:   Ubuntu Xenial
Description:

Log looks like: https://bpaste.net/show/4c1d3940ca27

https://data.maurer.codes/clique.sql contains a reproduction case.

On my machine, this consistently causes the glibc heap assertion in about 9
seconds on a fresh database. If you get "ERROR:  stack depth limit exceeded"
you may need to increase your max_stack_depth to observe the error (mine was
2MB, but is a release build, debug builds might need more to hit this).


--
Sent via pgsql-bugs mailing list (pgsql-bugs@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-bugs

Re: [BUGS] BUG #14809: Heap Corruption with deeply nested triggers.

From
Tom Lane
Date:
matthew.r.maurer@gmail.com writes:
> Log looks like: https://bpaste.net/show/4c1d3940ca27
> https://data.maurer.codes/clique.sql contains a reproduction case.

For the archives' sake, it'd have been better to include the test case.
The test isn't very large so I'll attach it below.

> On my machine, this consistently causes the glibc heap assertion in about 9
> seconds on a fresh database. If you get "ERROR:  stack depth limit exceeded"
> you may need to increase your max_stack_depth to observe the error (mine was
> 2MB, but is a release build, debug builds might need more to hit this).

I tried a few different max_stack_depth settings on both 9.6 and HEAD,
but was unable to reproduce a crash.  I see either a clean "stack depth
limit exceeded" failure, or successful completion of the query (at
stack depths above circa 3MB for me).  Tested on RHEL6 x86_64; maybe
some other platform would show the problem.

            regards, tom lane

-- General initialization
CREATE SCHEMA facts;
-- Define predicates
CREATE TABLE facts.edge (id serial PRIMARY KEY, arg0 bigint, arg1 bigint);
CREATE TABLE facts.reachable (id serial PRIMARY KEY, arg0 bigint, arg1 bigint);
CREATE TABLE facts.same_clique (id serial PRIMARY KEY, arg0 bigint, arg1 bigint);
-- Restrict predicates to contain unique facts
CREATE UNIQUE INDEX pred_edge_unique ON facts.edge (arg0,arg1);
CREATE UNIQUE INDEX pred_reachable_unique ON facts.reachable (arg0,arg1);
CREATE UNIQUE INDEX pred_same_clique_unique ON facts.same_clique (arg0,arg1);
-- Add triggers to automate rules

CREATE FUNCTION holmes_rule_reach_edge_0() RETURNS trigger AS $reach_edge$
    BEGIN
    INSERT INTO facts.reachable (arg0, arg1) (SELECT NEW.arg0, NEW.arg1  ) ON CONFLICT DO NOTHING;
    RETURN NULL;
    END;
    $reach_edge$ LANGUAGE plpgsql;
    CREATE TRIGGER holmes_rule_reach_edge_0 AFTER INSERT ON facts.edge FOR EACH ROW EXECUTE PROCEDURE
holmes_rule_reach_edge_0();
;

CREATE FUNCTION holmes_rule_reach_trans_0() RETURNS trigger AS $reach_trans$
    BEGIN
    INSERT INTO facts.reachable (arg0, arg1) (SELECT NEW.arg0, t0.arg1 FROM facts.reachable as t0 WHERE NEW.arg1 =
t0.arg0)ON CONFLICT DO NOTHING; 
    RETURN NULL;
    END;
    $reach_trans$ LANGUAGE plpgsql;
    CREATE TRIGGER holmes_rule_reach_trans_0 AFTER INSERT ON facts.edge FOR EACH ROW EXECUTE PROCEDURE
holmes_rule_reach_trans_0();


CREATE FUNCTION holmes_rule_reach_trans_1() RETURNS trigger AS $reach_trans$
    BEGIN
    INSERT INTO facts.reachable (arg0, arg1) (SELECT t0.arg0, NEW.arg1 FROM facts.edge as t0 WHERE t0.arg1 = NEW.arg0)
ONCONFLICT DO NOTHING; 
    RETURN NULL;
    END;
    $reach_trans$ LANGUAGE plpgsql;
    CREATE TRIGGER holmes_rule_reach_trans_1 AFTER INSERT ON facts.reachable FOR EACH ROW EXECUTE PROCEDURE
holmes_rule_reach_trans_1();
;

CREATE FUNCTION holmes_rule_scc_0() RETURNS trigger AS $scc$
    BEGIN
    INSERT INTO facts.same_clique (arg0, arg1) (SELECT NEW.arg0, NEW.arg1 FROM facts.reachable as t0 WHERE NEW.arg1 =
t0.arg0AND NEW.arg0 = t0.arg1) ON CONFLICT DO NOTHING; 
    RETURN NULL;
    END;
    $scc$ LANGUAGE plpgsql;
    CREATE TRIGGER holmes_rule_scc_0 AFTER INSERT ON facts.reachable FOR EACH ROW EXECUTE PROCEDURE
holmes_rule_scc_0();


CREATE FUNCTION holmes_rule_scc_1() RETURNS trigger AS $scc$
    BEGIN
    INSERT INTO facts.same_clique (arg0, arg1) (SELECT t0.arg0, t0.arg1 FROM facts.reachable as t0 WHERE t0.arg1 =
NEW.arg0AND t0.arg0 = NEW.arg1) ON CONFLICT DO NOTHING; 
    RETURN NULL;
    END;
    $scc$ LANGUAGE plpgsql;
    CREATE TRIGGER holmes_rule_scc_1 AFTER INSERT ON facts.reachable FOR EACH ROW EXECUTE PROCEDURE
holmes_rule_scc_1();
;

CREATE FUNCTION insert_for_clique(iters int) RETURNS VOID as $$
DECLARE
counter integer := 0;
BEGIN
    LOOP
        EXIT WHEN counter = iters;
        INSERT INTO facts.edge (arg0, arg1) values (counter, counter + 1);
        counter := counter + 1;
    END LOOP;
    INSERT INTO facts.edge (arg0, arg1) values (counter, 0);
END ; $$ LANGUAGE plpgsql;

SELECT insert_for_clique(1000);

-- 
Sent via pgsql-bugs mailing list (pgsql-bugs@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-bugs

Re: [BUGS] BUG #14809: Heap Corruption with deeply nested triggers.

From
Matthew Maurer
Date:
In case it helps, I was running Ubuntu Xenial inside docker.

On Sat, Sep 9, 2017 at 1:46 PM, Tom Lane <tgl@sss.pgh.pa.us> wrote:
> matthew.r.maurer@gmail.com writes:
>> Log looks like: https://bpaste.net/show/4c1d3940ca27
>> https://data.maurer.codes/clique.sql contains a reproduction case.
>
> For the archives' sake, it'd have been better to include the test case.
> The test isn't very large so I'll attach it below.
>
>> On my machine, this consistently causes the glibc heap assertion in about 9
>> seconds on a fresh database. If you get "ERROR:  stack depth limit exceeded"
>> you may need to increase your max_stack_depth to observe the error (mine was
>> 2MB, but is a release build, debug builds might need more to hit this).
>
> I tried a few different max_stack_depth settings on both 9.6 and HEAD,
> but was unable to reproduce a crash.  I see either a clean "stack depth
> limit exceeded" failure, or successful completion of the query (at
> stack depths above circa 3MB for me).  Tested on RHEL6 x86_64; maybe
> some other platform would show the problem.
>
>                         regards, tom lane
>
>
> -- General initialization
> CREATE SCHEMA facts;
> -- Define predicates
> CREATE TABLE facts.edge (id serial PRIMARY KEY, arg0 bigint, arg1 bigint);
> CREATE TABLE facts.reachable (id serial PRIMARY KEY, arg0 bigint, arg1 bigint);
> CREATE TABLE facts.same_clique (id serial PRIMARY KEY, arg0 bigint, arg1 bigint);
> -- Restrict predicates to contain unique facts
> CREATE UNIQUE INDEX pred_edge_unique ON facts.edge (arg0,arg1);
> CREATE UNIQUE INDEX pred_reachable_unique ON facts.reachable (arg0,arg1);
> CREATE UNIQUE INDEX pred_same_clique_unique ON facts.same_clique (arg0,arg1);
> -- Add triggers to automate rules
>
> CREATE FUNCTION holmes_rule_reach_edge_0() RETURNS trigger AS $reach_edge$
>     BEGIN
>     INSERT INTO facts.reachable (arg0, arg1) (SELECT NEW.arg0, NEW.arg1  ) ON CONFLICT DO NOTHING;
>     RETURN NULL;
>     END;
>     $reach_edge$ LANGUAGE plpgsql;
>     CREATE TRIGGER holmes_rule_reach_edge_0 AFTER INSERT ON facts.edge FOR EACH ROW EXECUTE PROCEDURE
holmes_rule_reach_edge_0();
> ;
>
> CREATE FUNCTION holmes_rule_reach_trans_0() RETURNS trigger AS $reach_trans$
>     BEGIN
>     INSERT INTO facts.reachable (arg0, arg1) (SELECT NEW.arg0, t0.arg1 FROM facts.reachable as t0 WHERE NEW.arg1 =
t0.arg0)ON CONFLICT DO NOTHING;
 
>     RETURN NULL;
>     END;
>     $reach_trans$ LANGUAGE plpgsql;
>     CREATE TRIGGER holmes_rule_reach_trans_0 AFTER INSERT ON facts.edge FOR EACH ROW EXECUTE PROCEDURE
holmes_rule_reach_trans_0();
>
>
> CREATE FUNCTION holmes_rule_reach_trans_1() RETURNS trigger AS $reach_trans$
>     BEGIN
>     INSERT INTO facts.reachable (arg0, arg1) (SELECT t0.arg0, NEW.arg1 FROM facts.edge as t0 WHERE t0.arg1 =
NEW.arg0)ON CONFLICT DO NOTHING;
 
>     RETURN NULL;
>     END;
>     $reach_trans$ LANGUAGE plpgsql;
>     CREATE TRIGGER holmes_rule_reach_trans_1 AFTER INSERT ON facts.reachable FOR EACH ROW EXECUTE PROCEDURE
holmes_rule_reach_trans_1();
> ;
>
> CREATE FUNCTION holmes_rule_scc_0() RETURNS trigger AS $scc$
>     BEGIN
>     INSERT INTO facts.same_clique (arg0, arg1) (SELECT NEW.arg0, NEW.arg1 FROM facts.reachable as t0 WHERE NEW.arg1 =
t0.arg0AND NEW.arg0 = t0.arg1) ON CONFLICT DO NOTHING;
 
>     RETURN NULL;
>     END;
>     $scc$ LANGUAGE plpgsql;
>     CREATE TRIGGER holmes_rule_scc_0 AFTER INSERT ON facts.reachable FOR EACH ROW EXECUTE PROCEDURE
holmes_rule_scc_0();
>
>
> CREATE FUNCTION holmes_rule_scc_1() RETURNS trigger AS $scc$
>     BEGIN
>     INSERT INTO facts.same_clique (arg0, arg1) (SELECT t0.arg0, t0.arg1 FROM facts.reachable as t0 WHERE t0.arg1 =
NEW.arg0AND t0.arg0 = NEW.arg1) ON CONFLICT DO NOTHING;
 
>     RETURN NULL;
>     END;
>     $scc$ LANGUAGE plpgsql;
>     CREATE TRIGGER holmes_rule_scc_1 AFTER INSERT ON facts.reachable FOR EACH ROW EXECUTE PROCEDURE
holmes_rule_scc_1();
> ;
>
> CREATE FUNCTION insert_for_clique(iters int) RETURNS VOID as $$
> DECLARE
> counter integer := 0;
> BEGIN
>         LOOP
>                 EXIT WHEN counter = iters;
>                 INSERT INTO facts.edge (arg0, arg1) values (counter, counter + 1);
>                 counter := counter + 1;
>         END LOOP;
>         INSERT INTO facts.edge (arg0, arg1) values (counter, 0);
> END ; $$ LANGUAGE plpgsql;
>
> SELECT insert_for_clique(1000);
>


-- 
Sent via pgsql-bugs mailing list (pgsql-bugs@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-bugs

Re: [BUGS] BUG #14809: Heap Corruption with deeply nested triggers.

From
Tom Lane
Date:
Matthew Maurer <matthew.r.maurer@gmail.com> writes:
> In case it helps, I was running Ubuntu Xenial inside docker.

I spent some more time today trying to reproduce this, without success.
At this point it seems probably platform- or build-specific.  Related
to that, the memory map you showed contains an awful lot of libraries
that I would not have expected to find loaded in a Postgres executable.
(I mean, libsqlite3?  Seriously?  And we don't officially support gnutls
nor libicu (in 9.6), for instance.)  So my suspicion at this point is
that Ubuntu has hacked up their version of PG and broken it somehow.
You said you were running a "release build", but whose exactly?
If it's Ubuntu's, you might try the PG community build for Ubuntu
https://www.postgresql.org/download/linux/ubuntu/
or roll your own from source, and then see if you can still reproduce
the problem.
        regards, tom lane


-- 
Sent via pgsql-bugs mailing list (pgsql-bugs@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-bugs

Re: [BUGS] BUG #14809: Heap Corruption with deeply nested triggers.

From
Matthew Maurer
Date:
Thanks for spending time trying to reproduce it. I am using the build
from the apt repository

deb http://apt.postgresql.org/pub/repos/apt/ xenial-pgdg main

postgresql-9.6 9.6.5-1.pgdg16.04+1

I chased down the depencency chain to find out why libsqlite3 is
present. It is linked against libldap, which is in turn linked against
libgssapi, which is in turn linked against libheimntlm, which is in
turn linked to libkrb5, which is then linked to libsqlite3.

I can chase down the other dependencies if you'd like, but I expect
that those are in the process for similar reasons.

On Sun, Sep 10, 2017 at 4:40 PM, Tom Lane <tgl@sss.pgh.pa.us> wrote:
> Matthew Maurer <matthew.r.maurer@gmail.com> writes:
>> In case it helps, I was running Ubuntu Xenial inside docker.
>
> I spent some more time today trying to reproduce this, without success.
> At this point it seems probably platform- or build-specific.  Related
> to that, the memory map you showed contains an awful lot of libraries
> that I would not have expected to find loaded in a Postgres executable.
> (I mean, libsqlite3?  Seriously?  And we don't officially support gnutls
> nor libicu (in 9.6), for instance.)  So my suspicion at this point is
> that Ubuntu has hacked up their version of PG and broken it somehow.
> You said you were running a "release build", but whose exactly?
> If it's Ubuntu's, you might try the PG community build for Ubuntu
> https://www.postgresql.org/download/linux/ubuntu/
> or roll your own from source, and then see if you can still reproduce
> the problem.
>
>                         regards, tom lane


-- 
Sent via pgsql-bugs mailing list (pgsql-bugs@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-bugs