Fix memory leak in Memoize code
authorDavid Rowley <drowley@postgresql.org>
Thu, 5 Oct 2023 07:30:47 +0000 (20:30 +1300)
committerDavid Rowley <drowley@postgresql.org>
Thu, 5 Oct 2023 07:30:47 +0000 (20:30 +1300)
Ensure we switch to the per-tuple memory context to prevent any memory
leaks of detoasted Datums in MemoizeHash_hash() and MemoizeHash_equal().

Reported-by: Orlov Aleksej
Author: Orlov Aleksej, David Rowley
Discussion: https://postgr.es/m/83281eed63c74e4f940317186372abfd%40cft.ru
Backpatch-through: 14, where Memoize was added

src/backend/executor/nodeMemoize.c

index 94bf4792873a8ce18dd5919df784c2f00eae83df..1085b3c79dd3cce053bd24d20147e0234d9d1b59 100644 (file)
@@ -158,10 +158,14 @@ static uint32
 MemoizeHash_hash(struct memoize_hash *tb, const MemoizeKey *key)
 {
        MemoizeState *mstate = (MemoizeState *) tb->private_data;
+       ExprContext *econtext = mstate->ss.ps.ps_ExprContext;
+       MemoryContext oldcontext;
        TupleTableSlot *pslot = mstate->probeslot;
        uint32          hashkey = 0;
        int                     numkeys = mstate->nkeys;
 
+       oldcontext = MemoryContextSwitchTo(econtext->ecxt_per_tuple_memory);
+
        if (mstate->binary_mode)
        {
                for (int i = 0; i < numkeys; i++)
@@ -203,6 +207,8 @@ MemoizeHash_hash(struct memoize_hash *tb, const MemoizeKey *key)
                }
        }
 
+       ResetExprContext(econtext);
+       MemoryContextSwitchTo(oldcontext);
        return murmurhash32(hashkey);
 }
 
@@ -226,7 +232,11 @@ MemoizeHash_equal(struct memoize_hash *tb, const MemoizeKey *key1,
 
        if (mstate->binary_mode)
        {
+               MemoryContext oldcontext;
                int                     numkeys = mstate->nkeys;
+               bool            match = true;
+
+               oldcontext = MemoryContextSwitchTo(econtext->ecxt_per_tuple_memory);
 
                slot_getallattrs(tslot);
                slot_getallattrs(pslot);
@@ -236,7 +246,10 @@ MemoizeHash_equal(struct memoize_hash *tb, const MemoizeKey *key1,
                        FormData_pg_attribute *attr;
 
                        if (tslot->tts_isnull[i] != pslot->tts_isnull[i])
-                               return false;
+                       {
+                               match = false;
+                               break;
+                       }
 
                        /* both NULL? they're equal */
                        if (tslot->tts_isnull[i])
@@ -246,9 +259,15 @@ MemoizeHash_equal(struct memoize_hash *tb, const MemoizeKey *key1,
                        attr = &tslot->tts_tupleDescriptor->attrs[i];
                        if (!datum_image_eq(tslot->tts_values[i], pslot->tts_values[i],
                                                                attr->attbyval, attr->attlen))
-                               return false;
+                       {
+                               match = false;
+                               break;
+                       }
                }
-               return true;
+
+               ResetExprContext(econtext);
+               MemoryContextSwitchTo(oldcontext);
+               return match;
        }
        else
        {