Skip to content

Commit 6af63cf

Browse files
committed
Fix confusion about event trigger vs. plain function in plpgsql.
The function hash table keys made by compute_function_hashkey() failed to distinguish event-trigger call context from regular call context. This meant that once we'd successfully made a hash entry for an event trigger (either by validation, or by normal use as an event trigger), an attempt to call the trigger function as a plain function would find this hash entry and thereby bypass the you-can't-do-that check in do_compile(). Thus we'd attempt to execute the function, leading to strange errors or even crashes, depending on function contents and server version. To fix, add an isEventTrigger field to PLpgSQL_func_hashkey, paralleling the longstanding infrastructure for regular triggers. This fits into what had been pad space, so there's no risk of an ABI break, even assuming that any third-party code is looking at these hash keys. (I considered replacing isTrigger with a PLpgSQL_trigtype enum field, but felt that that carried some API/ABI risk. Maybe we should change it in HEAD though.) Per bug #16266 from Alexander Lakhin. This has been broken since event triggers were invented, so back-patch to all supported branches. Discussion: https://postgr.es/m/16266-fcd7f838e97ba5d4@postgresql.org
1 parent 79f344d commit 6af63cf

File tree

4 files changed

+21
-6
lines changed

4 files changed

+21
-6
lines changed

src/pl/plpgsql/src/pl_comp.c

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2453,12 +2453,19 @@ compute_function_hashkey(FunctionCallInfo fcinfo,
24532453

24542454
/* get call context */
24552455
hashkey->isTrigger = CALLED_AS_TRIGGER(fcinfo);
2456+
hashkey->isEventTrigger = CALLED_AS_EVENT_TRIGGER(fcinfo);
24562457

24572458
/*
2458-
* if trigger, get its OID. In validation mode we do not know what
2459-
* relation or transition table names are intended to be used, so we leave
2460-
* trigOid zero; the hash entry built in this case will never really be
2461-
* used.
2459+
* If DML trigger, include trigger's OID in the hash, so that each trigger
2460+
* usage gets a different hash entry, allowing for e.g. different relation
2461+
* rowtypes or transition table names. In validation mode we do not know
2462+
* what relation or transition table names are intended to be used, so we
2463+
* leave trigOid zero; the hash entry built in this case will never be
2464+
* used for any actual calls.
2465+
*
2466+
* We don't currently need to distinguish different event trigger usages
2467+
* in the same way, since the special parameter variables don't vary in
2468+
* type in that case.
24622469
*/
24632470
if (hashkey->isTrigger && !forValidator)
24642471
{

src/pl/plpgsql/src/plpgsql.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -776,15 +776,16 @@ typedef struct PLpgSQL_func_hashkey
776776
{
777777
Oid funcOid;
778778

779-
bool isTrigger; /* true if called as a trigger */
779+
bool isTrigger; /* true if called as a DML trigger */
780+
bool isEventTrigger; /* true if called as an event trigger */
780781

781782
/* be careful that pad bytes in this struct get zeroed! */
782783

783784
/*
784785
* For a trigger function, the OID of the trigger is part of the hash key
785786
* --- we want to compile the trigger function separately for each trigger
786787
* it is used with, in case the rowtype or transition table names are
787-
* different. Zero if not called as a trigger.
788+
* different. Zero if not called as a DML trigger.
788789
*/
789790
Oid trigOid;
790791

src/test/regress/expected/event_trigger.out

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,10 @@ BEGIN
99
RAISE NOTICE 'test_event_trigger: % %', tg_event, tg_tag;
1010
END
1111
$$ language plpgsql;
12+
-- should fail, can't call it as a plain function
13+
SELECT test_event_trigger();
14+
ERROR: trigger functions can only be called as triggers
15+
CONTEXT: compilation of PL/pgSQL function "test_event_trigger" near line 1
1216
-- should fail, event triggers cannot have declared arguments
1317
create function test_event_trigger_arg(name text)
1418
returns event_trigger as $$ BEGIN RETURN 1; END $$ language plpgsql;

src/test/regress/sql/event_trigger.sql

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,9 @@ BEGIN
1010
END
1111
$$ language plpgsql;
1212

13+
-- should fail, can't call it as a plain function
14+
SELECT test_event_trigger();
15+
1316
-- should fail, event triggers cannot have declared arguments
1417
create function test_event_trigger_arg(name text)
1518
returns event_trigger as $$ BEGIN RETURN 1; END $$ language plpgsql;

0 commit comments

Comments
 (0)