]> granicus.if.org Git - postgresql/commitdiff
Fix bug in GIN posting tree root creation.
authorHeikki Linnakangas <heikki.linnakangas@iki.fi>
Wed, 13 Nov 2013 11:44:46 +0000 (13:44 +0200)
committerHeikki Linnakangas <heikki.linnakangas@iki.fi>
Wed, 13 Nov 2013 11:47:59 +0000 (13:47 +0200)
The root page is filled with as many items as fit, and the rest are inserted
using normal insertions. However, I fumbled the variable names, and the code
actually memcpy'd all the items on the page, overflowing the buffer. While
at it, rename the variable to make the distinction more clear.

Reported by Teodor Sigaev. This bug was introduced by my recent
refactorings, so no backpatching required.

src/backend/access/gin/gindatapage.c

index 049db38a2bf9c2bc1ec6a1aec1d38228a898fa3e..c9506cc0de1f7b24bd5bc8ddfcbb15a1b4f4c2f7 100644 (file)
@@ -623,10 +623,10 @@ createPostingTree(Relation index, ItemPointerData *items, uint32 nitems,
        BlockNumber blkno;
        Buffer          buffer;
        Page            page;
-       int                     itemsCount;
+       int                     nrootitems;
 
        /* Calculate how many TIDs will fit on first page. */
-       itemsCount = Min(nitems, GinMaxLeafDataItems);
+       nrootitems = Min(nitems, GinMaxLeafDataItems);
 
        /*
         * Create the root page.
@@ -638,8 +638,8 @@ createPostingTree(Relation index, ItemPointerData *items, uint32 nitems,
        START_CRIT_SECTION();
 
        GinInitBuffer(buffer, GIN_DATA | GIN_LEAF);
-       memcpy(GinDataPageGetData(page), items, sizeof(ItemPointerData) * nitems);
-       GinPageGetOpaque(page)->maxoff = nitems;
+       memcpy(GinDataPageGetData(page), items, sizeof(ItemPointerData) * nrootitems);
+       GinPageGetOpaque(page)->maxoff = nrootitems;
 
        MarkBufferDirty(buffer);
 
@@ -651,7 +651,7 @@ createPostingTree(Relation index, ItemPointerData *items, uint32 nitems,
 
                data.node = index->rd_node;
                data.blkno = blkno;
-               data.nitem = nitems;
+               data.nitem = nrootitems;
 
                rdata[0].buffer = InvalidBuffer;
                rdata[0].data = (char *) &data;
@@ -660,7 +660,7 @@ createPostingTree(Relation index, ItemPointerData *items, uint32 nitems,
 
                rdata[1].buffer = InvalidBuffer;
                rdata[1].data = (char *) items;
-               rdata[1].len = sizeof(ItemPointerData) * itemsCount;
+               rdata[1].len = sizeof(ItemPointerData) * nrootitems;
                rdata[1].next = NULL;
 
                recptr = XLogInsert(RM_GIN_ID, XLOG_GIN_CREATE_PTREE, rdata);
@@ -678,7 +678,7 @@ createPostingTree(Relation index, ItemPointerData *items, uint32 nitems,
        /*
         * Add any remaining TIDs to the newly-created posting tree.
         */
-       if (itemsCount < nitems)
+       if (nitems > nrootitems)
        {
                GinPostingTreeScan *gdi;
 
@@ -686,8 +686,8 @@ createPostingTree(Relation index, ItemPointerData *items, uint32 nitems,
                gdi->btree.isBuild = (buildStats != NULL);
 
                ginInsertItemPointers(gdi,
-                                                         items + itemsCount,
-                                                         nitems - itemsCount,
+                                                         items + nrootitems,
+                                                         nitems - nrootitems,
                                                          buildStats);
 
                pfree(gdi);