aboutsummaryrefslogtreecommitdiff
path: root/src/backend/commands/trigger.c
diff options
context:
space:
mode:
authorTom Lane <tgl@sss.pgh.pa.us>2010-08-19 15:46:30 +0000
committerTom Lane <tgl@sss.pgh.pa.us>2010-08-19 15:46:30 +0000
commitfd91b7d39aae5a02cfedf89da5f4589cfef2082e (patch)
tree88dd40c28b96e5a773335107e0ceb4fec021205f /src/backend/commands/trigger.c
parent8a288694f52d3f8a717ca7f1aa19a56b11e19232 (diff)
downloadpostgresql-fd91b7d39aae5a02cfedf89da5f4589cfef2082e.tar.gz
postgresql-fd91b7d39aae5a02cfedf89da5f4589cfef2082e.zip
Fix possible corruption of AfterTriggerEventLists in subtransaction rollback.
afterTriggerInvokeEvents failed to adjust events->tailfree when truncating the last chunk of an event list. This could result in the data being "de-truncated" by afterTriggerRestoreEventList during a subsequent subtransaction abort. Even that wouldn't kill us, because the re-added data would just be events marked DONE --- unless the data had been partially overwritten by new events. Then we might crash, or in any case misbehave (perhaps fire triggers twice, or fire triggers with the wrong event data). Per bug #5622 from Thue Janus Kristensen. Back-patch to 8.4 where the current trigger list representation was introduced.
Diffstat (limited to 'src/backend/commands/trigger.c')
-rw-r--r--src/backend/commands/trigger.c12
1 files changed, 11 insertions, 1 deletions
diff --git a/src/backend/commands/trigger.c b/src/backend/commands/trigger.c
index 09199ed27be..15871bbab54 100644
--- a/src/backend/commands/trigger.c
+++ b/src/backend/commands/trigger.c
@@ -7,7 +7,7 @@
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/commands/trigger.c,v 1.248.2.2 2010/01/24 21:49:31 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/commands/trigger.c,v 1.248.2.3 2010/08/19 15:46:30 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -2534,6 +2534,7 @@ afterTriggerAddEvent(AfterTriggerEventList *events,
else
events->tail->next = chunk;
events->tail = chunk;
+ /* events->tailfree is now out of sync, but we'll fix it below */
}
/*
@@ -2935,6 +2936,15 @@ afterTriggerInvokeEvents(AfterTriggerEventList *events,
{
chunk->freeptr = CHUNK_DATA_START(chunk);
chunk->endfree = chunk->endptr;
+
+ /*
+ * If it's last chunk, must sync event list's tailfree too. Note
+ * that delete_ok must NOT be passed as true if there could be
+ * stacked AfterTriggerEventList values pointing at this event
+ * list, since we'd fail to fix their copies of tailfree.
+ */
+ if (chunk == events->tail)
+ events->tailfree = chunk->freeptr;
}
}