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
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
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
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
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