]> granicus.if.org Git - postgresql/commitdiff
Fix memory leak in repeated GIN index searches.
authorTom Lane <tgl@sss.pgh.pa.us>
Sun, 13 Mar 2016 20:44:10 +0000 (16:44 -0400)
committerTom Lane <tgl@sss.pgh.pa.us>
Sun, 13 Mar 2016 20:44:31 +0000 (16:44 -0400)
Commit d88976cfa1302e8d removed this code from ginFreeScanKeys():
- if (entry->list)
- pfree(entry->list);
evidently in the belief that that ItemPointer array is allocated in the
keyCtx and so would be reclaimed by the following MemoryContextReset.
Unfortunately, it isn't and it won't.  It'd likely be a good idea for
that to become so, but as a simple and back-patchable fix in the
meantime, restore this code to ginFreeScanKeys().

Also, add a similar pfree to where startScanEntry() is about to zero out
entry->list.  I am not sure if there are any code paths where this
change prevents a leak today, but it seems like cheap future-proofing.

In passing, make the initial allocation of so->entries[] use palloc
not palloc0.  The code doesn't depend on unused entries being zero;
if it did, the array-enlargement code in ginFillScanEntry() would be
wrong.  So using palloc0 initially can only serve to confuse readers
about what the invariant is.

Per report from Felipe de Jesús Molina Bravo, via Jaime Casanova in
<CAJGNTeMR1ndMU2Thpr8GPDUfiHTV7idELJRFusA5UXUGY1y-eA@mail.gmail.com>

src/backend/access/gin/ginget.c
src/backend/access/gin/ginscan.c

index a6756d594d24509641312dbd5c289eb630e1d44f..53290a4279b93803f5fbfd1ae4cca34b1b246c0c 100644 (file)
@@ -302,6 +302,8 @@ restartScanEntry:
        entry->buffer = InvalidBuffer;
        ItemPointerSetMin(&entry->curItem);
        entry->offset = InvalidOffsetNumber;
+       if (entry->list)
+               pfree(entry->list);
        entry->list = NULL;
        entry->nlist = 0;
        entry->matchBitmap = NULL;
index 3449a30e4196ebd8ec5ef7f91811ac5e5361c0de..c449c1cbc0ed7dbc7e17bf5dac83523ecef12e92 100644 (file)
@@ -246,6 +246,8 @@ ginFreeScanKeys(GinScanOpaque so)
 
                if (entry->buffer != InvalidBuffer)
                        ReleaseBuffer(entry->buffer);
+               if (entry->list)
+                       pfree(entry->list);
                if (entry->matchIterator)
                        tbm_end_iterate(entry->matchIterator);
                if (entry->matchBitmap)
@@ -285,7 +287,7 @@ ginNewScanKey(IndexScanDesc scan)
        so->totalentries = 0;
        so->allocentries = 32;
        so->entries = (GinScanEntry *)
-               palloc0(so->allocentries * sizeof(GinScanEntry));
+               palloc(so->allocentries * sizeof(GinScanEntry));
 
        so->isVoidRes = false;