From 9dab9ab5e488e921ba6f948fa760566cd61e45a9 Mon Sep 17 00:00:00 2001
From: Tom Lane <tgl@sss.pgh.pa.us>
Date: Sun, 21 May 2000 02:28:55 +0000
Subject: [PATCH] Repair memory leaks that caused CacheCxt to grow without
 bound.  We really ought to fix relcache entry construction so that it does
 not do so much with CurrentMemoryContext = CacheCxt.  As is, relatively
 harmless leaks in either sequential or index scanning translate to permanent
 leaks if they occur when called from relcache build. For the moment, however,
 the path of least resistance is to repair all such leaks...

---
 src/backend/access/heap/heapam.c   |  5 +++-
 src/backend/utils/cache/relcache.c | 45 +++++++++++++++---------------
 2 files changed, 27 insertions(+), 23 deletions(-)

diff --git a/src/backend/access/heap/heapam.c b/src/backend/access/heap/heapam.c
index 29d6c9e0f9e..e7a549d410b 100644
--- a/src/backend/access/heap/heapam.c
+++ b/src/backend/access/heap/heapam.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/access/heap/heapam.c,v 1.67 2000/04/12 17:14:45 momjian Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/access/heap/heapam.c,v 1.68 2000/05/21 02:28:54 tgl Exp $
  *
  *
  * INTERFACE ROUTINES
@@ -766,6 +766,9 @@ heap_endscan(HeapScanDesc scan)
 	 */
 	RelationDecrementReferenceCount(scan->rs_rd);
 
+	if (scan->rs_key)
+		pfree(scan->rs_key);
+
 	pfree(scan);
 }
 
diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c
index 41fcdf1d273..b9e86d905ec 100644
--- a/src/backend/utils/cache/relcache.c
+++ b/src/backend/utils/cache/relcache.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/utils/cache/relcache.c,v 1.95 2000/04/12 17:15:54 momjian Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/utils/cache/relcache.c,v 1.96 2000/05/21 02:28:55 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -245,6 +245,9 @@ static bool criticalRelcacheBuild = false;
  *		this is used by RelationBuildDesc to find a pg_class
  *		tuple matching either a relation name or a relation id
  *		as specified in buildinfo.
+ *
+ *		NB: the returned tuple has been copied into palloc'd storage
+ *		and must eventually be freed with heap_freetuple.
  * --------------------------------
  */
 static HeapTuple
@@ -356,6 +359,8 @@ scan_pg_rel_ind(RelationBuildDescInfo buildinfo)
 
 	heap_close(pg_class_desc, AccessShareLock);
 
+	/* The xxxIndexScan routines will have returned a palloc'd tuple. */
+
 	return return_tuple;
 }
 
@@ -519,9 +524,9 @@ build_tupdesc_seq(RelationBuildDescInfo buildinfo,
 			relation->rd_att->attrs[attp->attnum - 1] =
 				(Form_pg_attribute) palloc(ATTRIBUTE_TUPLE_SIZE);
 
-			memmove((char *) (relation->rd_att->attrs[attp->attnum - 1]),
-					(char *) attp,
-					ATTRIBUTE_TUPLE_SIZE);
+			memcpy((char *) (relation->rd_att->attrs[attp->attnum - 1]),
+				   (char *) attp,
+				   ATTRIBUTE_TUPLE_SIZE);
 			need--;
 			/* Update if this attribute have a constraint */
 			if (attp->attnotnull)
@@ -571,11 +576,6 @@ build_tupdesc_ind(RelationBuildDescInfo buildinfo,
 	int			ndef = 0;
 	int			i;
 
-#ifdef	_DROP_COLUMN_HACK__
-	bool		columnDropped;
-
-#endif	 /* _DROP_COLUMN_HACK__ */
-
 	constr->has_not_null = false;
 
 	attrel = heap_openr(AttributeRelationName, AccessShareLock);
@@ -583,14 +583,15 @@ build_tupdesc_ind(RelationBuildDescInfo buildinfo,
 	for (i = 1; i <= relation->rd_rel->relnatts; i++)
 	{
 #ifdef	_DROP_COLUMN_HACK__
-		columnDropped = false;
+		bool		columnDropped = false;
 #endif	 /* _DROP_COLUMN_HACK__ */
+
 		atttup = (HeapTuple) AttributeRelidNumIndexScan(attrel,
 										  RelationGetRelid(relation), i);
 
 		if (!HeapTupleIsValid(atttup))
-#ifdef	_DROP_COLUMN_HACK__
 		{
+#ifdef	_DROP_COLUMN_HACK__
 			atttup = (HeapTuple) AttributeRelidNumIndexScan(attrel,
 					RelationGetRelid(relation), DROPPED_COLUMN_INDEX(i));
 			if (!HeapTupleIsValid(atttup))
@@ -599,21 +600,24 @@ build_tupdesc_ind(RelationBuildDescInfo buildinfo,
 					 RelationGetRelationName(relation));
 #ifdef	_DROP_COLUMN_HACK__
 			columnDropped = true;
-		}
 #endif	 /* _DROP_COLUMN_HACK__ */
-		attp = (Form_pg_attribute) GETSTRUCT(atttup);
+		}
 
-		relation->rd_att->attrs[i - 1] =
+		relation->rd_att->attrs[i - 1] = attp =
 			(Form_pg_attribute) palloc(ATTRIBUTE_TUPLE_SIZE);
 
-		memmove((char *) (relation->rd_att->attrs[i - 1]),
-				(char *) attp,
-				ATTRIBUTE_TUPLE_SIZE);
+		memcpy((char *) attp,
+			   (char *) (Form_pg_attribute) GETSTRUCT(atttup),
+			   ATTRIBUTE_TUPLE_SIZE);
+
+		/* don't forget to free the tuple returned from xxxIndexScan */
+		heap_freetuple(atttup);
 
 #ifdef	_DROP_COLUMN_HACK__
 		if (columnDropped)
 			continue;
 #endif	 /* _DROP_COLUMN_HACK__ */
+
 		/* Update if this attribute have a constraint */
 		if (attp->attnotnull)
 			constr->has_not_null = true;
@@ -1117,12 +1121,9 @@ formrdesc(char *relationName,
 	for (i = 0; i < natts; i++)
 	{
 		relation->rd_att->attrs[i] = (Form_pg_attribute) palloc(ATTRIBUTE_TUPLE_SIZE);
-
-		MemSet((char *) relation->rd_att->attrs[i], 0,
+		memcpy((char *) relation->rd_att->attrs[i],
+			   (char *) &att[i],
 			   ATTRIBUTE_TUPLE_SIZE);
-		memmove((char *) relation->rd_att->attrs[i],
-				(char *) &att[i],
-				ATTRIBUTE_TUPLE_SIZE);
 	}
 
 	/* ----------------
-- 
GitLab