From 2fa42feb7921d9486d56a38608d2b27b8f4e607c Mon Sep 17 00:00:00 2001 From: Tomas Vondra Date: Sat, 14 Mar 2026 15:24:37 +0100 Subject: [PATCH] Tighten asserts on ParallelWorkerNumber The comment about ParallelWorkerNumbr in parallel.c says: In parallel workers, it will be set to a value >= 0 and < the number of workers before any user code is invoked; each parallel worker will get a different parallel worker number. However asserts in various places collecting instrumentation allowed (ParallelWorkerNumber == num_workers). That would be a bug, as the value is used as index into an array with num_workers entries. Fixed by adjusting the asserts accordingly. Backpatch to all supported versions. Discussion: https://postgr.es/m/5db067a1-2cdf-4afb-a577-a04f30b69167@vondra.me Reviewed-by: Bertrand Drouvot Backpatch-through: 14 --- src/backend/executor/nodeAgg.c | 2 +- src/backend/executor/nodeIncrementalSort.c | 2 +- src/backend/executor/nodeMemoize.c | 2 +- src/backend/executor/nodeSort.c | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/backend/executor/nodeAgg.c b/src/backend/executor/nodeAgg.c index 53ead77ece8..bb6f55b2c75 100644 --- a/src/backend/executor/nodeAgg.c +++ b/src/backend/executor/nodeAgg.c @@ -4317,7 +4317,7 @@ ExecEndAgg(AggState *node) { AggregateInstrumentation *si; - Assert(ParallelWorkerNumber <= node->shared_info->num_workers); + Assert(ParallelWorkerNumber < node->shared_info->num_workers); si = &node->shared_info->sinstrument[ParallelWorkerNumber]; si->hash_batches_used = node->hash_batches_used; si->hash_disk_used = node->hash_disk_used; diff --git a/src/backend/executor/nodeIncrementalSort.c b/src/backend/executor/nodeIncrementalSort.c index 2ce5ed5ec8c..235fb90564a 100644 --- a/src/backend/executor/nodeIncrementalSort.c +++ b/src/backend/executor/nodeIncrementalSort.c @@ -102,7 +102,7 @@ if ((node)->shared_info && (node)->am_worker) \ { \ Assert(IsParallelWorker()); \ - Assert(ParallelWorkerNumber <= (node)->shared_info->num_workers); \ + Assert(ParallelWorkerNumber < (node)->shared_info->num_workers); \ instrumentSortedGroup(&(node)->shared_info->sinfo[ParallelWorkerNumber].groupName##GroupInfo, \ (node)->groupName##_state); \ } \ diff --git a/src/backend/executor/nodeMemoize.c b/src/backend/executor/nodeMemoize.c index 45157ffb9c7..79ed1cf7f0c 100644 --- a/src/backend/executor/nodeMemoize.c +++ b/src/backend/executor/nodeMemoize.c @@ -1122,7 +1122,7 @@ ExecEndMemoize(MemoizeState *node) if (node->stats.mem_peak == 0) node->stats.mem_peak = node->mem_used; - Assert(ParallelWorkerNumber <= node->shared_info->num_workers); + Assert(ParallelWorkerNumber < node->shared_info->num_workers); si = &node->shared_info->sinstrument[ParallelWorkerNumber]; memcpy(si, &node->stats, sizeof(MemoizeInstrumentation)); } diff --git a/src/backend/executor/nodeSort.c b/src/backend/executor/nodeSort.c index 3fc925d7b48..c1b8cc913d5 100644 --- a/src/backend/executor/nodeSort.c +++ b/src/backend/executor/nodeSort.c @@ -175,7 +175,7 @@ ExecSort(PlanState *pstate) TuplesortInstrumentation *si; Assert(IsParallelWorker()); - Assert(ParallelWorkerNumber <= node->shared_info->num_workers); + Assert(ParallelWorkerNumber < node->shared_info->num_workers); si = &node->shared_info->sinstrument[ParallelWorkerNumber]; tuplesort_get_stats(tuplesortstate, si); }