8000 Fix dereference of dangling pointer in GiST index buffering build. · postgres/postgres@b5c6776 · GitHub
[go: up one dir, main page]

Skip to content

Commit b5c6776

Browse files
committed
Fix dereference of dangling pointer in GiST index buffering build.
gistBuildCallback tried to fetch the size of an index tuple that might have already been freed by gistProcessEmptyingQueue. While this seems to usually be harmless in production builds, in principle it could result in a SIGSEGV, or more likely a bogus value for indtuplesSize leading to poor page-split decisions later in the build. The memory management here is confusing and could stand to be refactored, but for the moment it seems to be enough to fetch the tuple size sooner. AFAICT the indtuples[Size] totals aren't used in between these places; even if they were, the updated values shouldn't be any worse to use. So just move the incrementing of the totals up. It's not very clear why our valgrind-using buildfarm animals haven't noticed this problem, because the relevant code path does seem to be exercised according to the code coverage report. I think the reason that we didn't fix this bug after the first report is that I'd wanted to try to understand that better. However, now that it's been re-discovered let's just be pragmatic and fix it already. Original report by Alexander Lakhin (bug #16329), later rediscovered by Egor Chindyaskin (bug #17874). Patch by Alexander Lakhin (commentary by Pavel Borisov and me). Back-patch to all supported branches. Discussion: https://postgr.es/m/16329-7a6aa9b6fa1118a1@postgresql.org Discussion: https://postgr.es/m/17874-63ca6c7ce42d2103@postgresql.org
1 parent 4257d34 commit b5c6776

File tree

1 file changed

+13
-4
lines changed

1 file changed

+13
-4
lines changed

src/backend/access/gist/gistbuild.c

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -474,6 +474,19 @@ gistBuildCallback(Relation index,
474474
itup = gistFormTuple(buildstate->giststate, index, values, isnull, true);
475475
itup->t_tid = htup->t_self;
476476

477+
/* Update tuple count and total size. */
478+
buildstate->indtuples += 1;
479+
buildstate->indtuplesSize += IndexTupleSize(itup);
480+
481+
/*
482+
* XXX In buffering builds, the tempCxt is also reset down inside
483+
* gistProcessEmptyingQueue(). This is not great because it risks
484+
* confusion and possible use of dangling pointers (for example, itup
485+
* might be already freed when control returns here). It's generally
486+
* better that a memory context be "owned" by only one function. However,
487+
* currently this isn't causing issues so it doesn't seem worth the amount
488+
* of refactoring that would be needed to avoid it.
489+
*/
477490
if (buildstate->bufferingMode == GIST_BUFFERING_ACTIVE)
478491
{
479492
/* We have buffers, so use them. */
@@ -489,10 +502,6 @@ gistBuildCallback(Relation index,
489502
buildstate->giststate, buildstate->heaprel);
490503
}
491504

492-
/* Update tuple count and total size. */
493-
buildstate->indtuples += 1;
494-
buildstate->indtuplesSize += IndexTupleSize(itup);
495-
496505
MemoryContextSwitchTo(oldCtx);
497506
MemoryContextReset(buildstate->giststate->tempCxt);
498507

0 commit comments

Comments
 (0)
0