From 42d1acd2edc4a02de63c7b3d2a18056d393e373d Mon Sep 17 00:00:00 2001 From: Heikki Linnakangas Date: Mon, 16 Dec 2019 13:57:41 +0200 Subject: Fix yet another crash in page split during GiST index creation. Commit a7ee7c8513 fixed a bug in GiST page split during index creation, where we failed to re-find the position of a downlink after the page containing it was split. However, that fix was incomplete; the other call to gistinserttuples() in the same function needs to also clear 'downlinkoffnum'. Fixes bug #16134 reported by Alexander Lakhin, for real this time. The previous fix was enough to fix the crash with the reproducer script for bug #16162, but the original script for #16134 was still crashing. Backpatch to v12, like the previous incomplete fix. Discussion: https://www.postgresql.org/message-id/d869f537-abe4-d2ea-0510-38cd053f5152%40gmail.com --- src/backend/access/gist/gist.c | 31 +++++++++++++++++++------------ 1 file changed, 19 insertions(+), 12 deletions(-) (limited to 'src/backend/access/gist/gist.c') diff --git a/src/backend/access/gist/gist.c b/src/backend/access/gist/gist.c index a44112befce..12d8a68c6c1 100644 --- a/src/backend/access/gist/gist.c +++ b/src/backend/access/gist/gist.c @@ -1338,10 +1338,9 @@ gistfinishsplit(GISTInsertState *state, GISTInsertStack *stack, } LockBuffer(stack->parent->buffer, GIST_EXCLUSIVE); - gistFindCorrectParent(state->r, stack); /* - * insert downlinks for the siblings from right to left, until there are + * Insert downlinks for the siblings from right to left, until there are * only two siblings left. */ while (list_length(reversed) > 2) @@ -1349,17 +1348,17 @@ gistfinishsplit(GISTInsertState *state, GISTInsertStack *stack, right = (GISTPageSplitInfo *) linitial(reversed); left = (GISTPageSplitInfo *) lsecond(reversed); + gistFindCorrectParent(state->r, stack); if (gistinserttuples(state, stack->parent, giststate, &right->downlink, 1, InvalidOffsetNumber, left->buf, right->buf, false, false)) { /* - * If the parent page was split, need to relocate the original - * parent pointer. + * If the parent page was split, the existing downlink might + * have moved. */ stack->downlinkoffnum = InvalidOffsetNumber; - gistFindCorrectParent(state->r, stack); } /* gistinserttuples() released the lock on right->buf. */ reversed = list_delete_first(reversed); @@ -1375,13 +1374,21 @@ gistfinishsplit(GISTInsertState *state, GISTInsertStack *stack, */ tuples[0] = left->downlink; tuples[1] = right->downlink; - gistinserttuples(state, stack->parent, giststate, - tuples, 2, - stack->downlinkoffnum, - left->buf, right->buf, - true, /* Unlock parent */ - unlockbuf /* Unlock stack->buffer if caller wants that */ - ); + gistFindCorrectParent(state->r, stack); + if (gistinserttuples(state, stack->parent, giststate, + tuples, 2, + stack->downlinkoffnum, + left->buf, right->buf, + true, /* Unlock parent */ + unlockbuf /* Unlock stack->buffer if caller wants that */ + )) + { + /* + * If the parent page was split, the downlink might have moved. + */ + stack->downlinkoffnum = InvalidOffsetNumber; + } + Assert(left->buf == stack->buffer); /* -- cgit v1.2.3