mirror of
				https://github.com/postgres/postgres.git
				synced 2025-11-03 09:13:20 +03:00 
			
		
		
		
	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:
		@@ -158,10 +158,14 @@ static uint32
 | 
				
			|||||||
MemoizeHash_hash(struct memoize_hash *tb, const MemoizeKey *key)
 | 
					MemoizeHash_hash(struct memoize_hash *tb, const MemoizeKey *key)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	MemoizeState *mstate = (MemoizeState *) tb->private_data;
 | 
						MemoizeState *mstate = (MemoizeState *) tb->private_data;
 | 
				
			||||||
 | 
						ExprContext *econtext = mstate->ss.ps.ps_ExprContext;
 | 
				
			||||||
 | 
						MemoryContext oldcontext;
 | 
				
			||||||
	TupleTableSlot *pslot = mstate->probeslot;
 | 
						TupleTableSlot *pslot = mstate->probeslot;
 | 
				
			||||||
	uint32		hashkey = 0;
 | 
						uint32		hashkey = 0;
 | 
				
			||||||
	int			numkeys = mstate->nkeys;
 | 
						int			numkeys = mstate->nkeys;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						oldcontext = MemoryContextSwitchTo(econtext->ecxt_per_tuple_memory);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (mstate->binary_mode)
 | 
						if (mstate->binary_mode)
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		for (int i = 0; i < numkeys; i++)
 | 
							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);
 | 
						return murmurhash32(hashkey);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -226,7 +232,11 @@ MemoizeHash_equal(struct memoize_hash *tb, const MemoizeKey *key1,
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	if (mstate->binary_mode)
 | 
						if (mstate->binary_mode)
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
 | 
							MemoryContext oldcontext;
 | 
				
			||||||
		int			numkeys = mstate->nkeys;
 | 
							int			numkeys = mstate->nkeys;
 | 
				
			||||||
 | 
							bool		match = true;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							oldcontext = MemoryContextSwitchTo(econtext->ecxt_per_tuple_memory);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		slot_getallattrs(tslot);
 | 
							slot_getallattrs(tslot);
 | 
				
			||||||
		slot_getallattrs(pslot);
 | 
							slot_getallattrs(pslot);
 | 
				
			||||||
@@ -236,7 +246,10 @@ MemoizeHash_equal(struct memoize_hash *tb, const MemoizeKey *key1,
 | 
				
			|||||||
			FormData_pg_attribute *attr;
 | 
								FormData_pg_attribute *attr;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			if (tslot->tts_isnull[i] != pslot->tts_isnull[i])
 | 
								if (tslot->tts_isnull[i] != pslot->tts_isnull[i])
 | 
				
			||||||
				return false;
 | 
								{
 | 
				
			||||||
 | 
									match = false;
 | 
				
			||||||
 | 
									break;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			/* both NULL? they're equal */
 | 
								/* both NULL? they're equal */
 | 
				
			||||||
			if (tslot->tts_isnull[i])
 | 
								if (tslot->tts_isnull[i])
 | 
				
			||||||
@@ -246,9 +259,15 @@ MemoizeHash_equal(struct memoize_hash *tb, const MemoizeKey *key1,
 | 
				
			|||||||
			attr = &tslot->tts_tupleDescriptor->attrs[i];
 | 
								attr = &tslot->tts_tupleDescriptor->attrs[i];
 | 
				
			||||||
			if (!datum_image_eq(tslot->tts_values[i], pslot->tts_values[i],
 | 
								if (!datum_image_eq(tslot->tts_values[i], pslot->tts_values[i],
 | 
				
			||||||
								attr->attbyval, attr->attlen))
 | 
													attr->attbyval, attr->attlen))
 | 
				
			||||||
				return false;
 | 
								{
 | 
				
			||||||
 | 
									match = false;
 | 
				
			||||||
 | 
									break;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		return true;
 | 
					
 | 
				
			||||||
 | 
							ResetExprContext(econtext);
 | 
				
			||||||
 | 
							MemoryContextSwitchTo(oldcontext);
 | 
				
			||||||
 | 
							return match;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	else
 | 
						else
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user