Fix memory leak in Memoize code

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
This commit is contained in:
David Rowley 2023-10-05 20:32:14 +13:00
parent f91c87b314
commit e4b95b9b02
1 changed files with 22 additions and 3 deletions

View 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
{