]> granicus.if.org Git - postgresql/commitdiff
Fix memory leaks in GIN index vacuum.
authorHeikki Linnakangas <heikki.linnakangas@iki.fi>
Thu, 12 Mar 2015 14:29:58 +0000 (15:29 +0100)
committerHeikki Linnakangas <heikki.linnakangas@iki.fi>
Thu, 12 Mar 2015 14:34:32 +0000 (15:34 +0100)
Per bug #12850 by Walter Nordmann. Backpatch to 9.4 where the leak was
introduced.

src/backend/access/gin/ginvacuum.c

index 9e76df36129f0497637bf295ce8e2428532e1a22..eba572b0d8afaff71815b3d9bebdc8ce07f69086 100644 (file)
@@ -432,27 +432,32 @@ ginVacuumEntryPage(GinVacuumState *gvs, Buffer buffer, BlockNumber *roots, uint3
                else if (GinGetNPosting(itup) > 0)
                {
                        int                     nitems;
-                       ItemPointer uncompressed;
+                       ItemPointer items_orig;
+                       bool            free_items_orig;
+                       ItemPointer items;
 
-                       /*
-                        * Vacuum posting list with proper function for compressed and
-                        * uncompressed format.
-                        */
+                       /* Get list of item pointers from the tuple. */
                        if (GinItupIsCompressed(itup))
-                               uncompressed = ginPostingListDecode((GinPostingList *) GinGetPosting(itup), &nitems);
+                       {
+                               items_orig = ginPostingListDecode((GinPostingList *) GinGetPosting(itup), &nitems);
+                               free_items_orig = true;
+                       }
                        else
                        {
-                               uncompressed = (ItemPointer) GinGetPosting(itup);
+                               items_orig = (ItemPointer) GinGetPosting(itup);
                                nitems = GinGetNPosting(itup);
+                               free_items_orig = false;
                        }
 
-                       uncompressed = ginVacuumItemPointers(gvs, uncompressed, nitems,
-                                                                                                &nitems);
-                       if (uncompressed)
+                       /* Remove any items from the list that need to be vacuumed. */
+                       items = ginVacuumItemPointers(gvs, items_orig, nitems, &nitems);
+
+                       if (free_items_orig)
+                               pfree(items_orig);
+
+                       /* If any item pointers were removed, recreate the tuple. */
+                       if (items)
                        {
-                               /*
-                                * Some ItemPointers were deleted, recreate tuple.
-                                */
                                OffsetNumber attnum;
                                Datum           key;
                                GinNullCategory category;
@@ -461,7 +466,7 @@ ginVacuumEntryPage(GinVacuumState *gvs, Buffer buffer, BlockNumber *roots, uint3
 
                                if (nitems > 0)
                                {
-                                       plist = ginCompressPostingList(uncompressed, nitems, GinMaxItemSize, NULL);
+                                       plist = ginCompressPostingList(items, nitems, GinMaxItemSize, NULL);
                                        plistsize = SizeOfGinPostingList(plist);
                                }
                                else
@@ -500,6 +505,7 @@ ginVacuumEntryPage(GinVacuumState *gvs, Buffer buffer, BlockNumber *roots, uint3
                                                 RelationGetRelationName(gvs->index));
 
                                pfree(itup);
+                               pfree(items);
                        }
                }
        }