Re: Segmentation fault during update inside ExecBRUpdateTriggers - Mailing list pgsql-bugs

From Tom Lane
Subject Re: Segmentation fault during update inside ExecBRUpdateTriggers
Date
Msg-id 12395.1565911617@sss.pgh.pa.us
Whole thread Raw
In response to Re: Segmentation fault during update inside ExecBRUpdateTriggers  (Tom Lane <tgl@sss.pgh.pa.us>)
Responses Re: Segmentation fault during update inside ExecBRUpdateTriggers  (Thomas Munro <thomas.munro@gmail.com>)
List pgsql-bugs
I wrote:
> [ thinks some more... ]  Actually, I'm beginning to recall that
> we made changes here because v11 plpgsql is capable of actually
> returning "trigtuple" where before it would always have made a copy.
> If that's accurate, then very likely the bug exists further back
> but requires some other PL than plpgsql to manifest.

As I suspected ... the attached test case crashes 9.4 through 11.
We already had some problems in this area, which is why a suitable
trigger is already at hand in regress.c.

            regards, tom lane

diff --git a/src/test/regress/expected/triggers.out b/src/test/regress/expected/triggers.out
index c64151b..1e4053c 100644
--- a/src/test/regress/expected/triggers.out
+++ b/src/test/regress/expected/triggers.out
@@ -144,6 +144,76 @@ select * from trigtest;
 ----+----
 (0 rows)

+-- Also check what happens when such a trigger runs before or after others
+create function f1_times_10() returns trigger as
+$$ begin new.f1 := new.f1 * 10; return new; end $$ language plpgsql;
+create trigger trigger_alpha
+    before insert or update on trigtest
+    for each row execute procedure f1_times_10();
+insert into trigtest values(1, 'foo');
+select * from trigtest;
+ f1 | f2
+----+-----
+ 10 | foo
+(1 row)
+
+update trigtest set f2 = f2 || 'bar';
+select * from trigtest;
+ f1 | f2
+----+-----
+ 10 | foo
+(1 row)
+
+delete from trigtest;
+select * from trigtest;
+ f1 | f2
+----+----
+(0 rows)
+
+create trigger trigger_zed
+    before insert or update on trigtest
+    for each row execute procedure f1_times_10();
+insert into trigtest values(1, 'foo');
+select * from trigtest;
+ f1  | f2
+-----+-----
+ 100 | foo
+(1 row)
+
+update trigtest set f2 = f2 || 'bar';
+select * from trigtest;
+  f1  | f2
+------+-----
+ 1000 | foo
+(1 row)
+
+delete from trigtest;
+select * from trigtest;
+ f1 | f2
+----+----
+(0 rows)
+
+drop trigger trigger_alpha on trigtest;
+insert into trigtest values(1, 'foo');
+select * from trigtest;
+ f1 | f2
+----+-----
+ 10 | foo
+(1 row)
+
+update trigtest set f2 = f2 || 'bar';
+select * from trigtest;
+ f1  | f2
+-----+-----
+ 100 | foo
+(1 row)
+
+delete from trigtest;
+select * from trigtest;
+ f1 | f2
+----+----
+(0 rows)
+
 drop table trigtest;
 create sequence ttdummy_seq increment 10 start 0 minvalue 0;
 create table tttest (
diff --git a/src/test/regress/sql/triggers.sql b/src/test/regress/sql/triggers.sql
index 4534dc9..c21b6c1 100644
--- a/src/test/regress/sql/triggers.sql
+++ b/src/test/regress/sql/triggers.sql
@@ -117,6 +117,41 @@ select * from trigtest;
 delete from trigtest;
 select * from trigtest;

+-- Also check what happens when such a trigger runs before or after others
+create function f1_times_10() returns trigger as
+$$ begin new.f1 := new.f1 * 10; return new; end $$ language plpgsql;
+
+create trigger trigger_alpha
+    before insert or update on trigtest
+    for each row execute procedure f1_times_10();
+
+insert into trigtest values(1, 'foo');
+select * from trigtest;
+update trigtest set f2 = f2 || 'bar';
+select * from trigtest;
+delete from trigtest;
+select * from trigtest;
+
+create trigger trigger_zed
+    before insert or update on trigtest
+    for each row execute procedure f1_times_10();
+
+insert into trigtest values(1, 'foo');
+select * from trigtest;
+update trigtest set f2 = f2 || 'bar';
+select * from trigtest;
+delete from trigtest;
+select * from trigtest;
+
+drop trigger trigger_alpha on trigtest;
+
+insert into trigtest values(1, 'foo');
+select * from trigtest;
+update trigtest set f2 = f2 || 'bar';
+select * from trigtest;
+delete from trigtest;
+select * from trigtest;
+
 drop table trigtest;

 create sequence ttdummy_seq increment 10 start 0 minvalue 0;

pgsql-bugs by date:

Previous
From: Andres Freund
Date:
Subject: Re: Segmentation fault during update inside ExecBRUpdateTriggers
Next
From: Thomas Munro
Date:
Subject: Re: Segmentation fault during update inside ExecBRUpdateTriggers