From c3a153afed84e29dac664bdc6123724a9e3a906f Mon Sep 17 00:00:00 2001
From: Tom Lane <tgl@sss.pgh.pa.us>
Date: Sat, 5 Jun 2004 19:48:09 +0000
Subject: [PATCH] Tweak palloc/repalloc to allow zero bytes to be requested, as
 per recent proposal.  Eliminate several dozen now-unnecessary hacks to avoid
 palloc(0). (It's likely there are more that I didn't find.)

---
 src/backend/access/nbtree/nbtree.c        |  4 +-
 src/backend/commands/analyze.c            | 11 ++--
 src/backend/commands/copy.c               | 29 +++++----
 src/backend/commands/tablecmds.c          |  6 +-
 src/backend/commands/vacuum.c             |  5 +-
 src/backend/commands/vacuumlazy.c         |  5 +-
 src/backend/executor/execQual.c           |  4 +-
 src/backend/optimizer/prep/prepunion.c    |  6 +-
 src/backend/optimizer/util/clauses.c      |  4 +-
 src/backend/storage/freespace/freespace.c |  4 +-
 src/backend/storage/lmgr/deadlock.c       |  7 +--
 src/backend/storage/lmgr/lock.c           |  5 +-
 src/backend/tcop/pquery.c                 |  5 +-
 src/backend/utils/adt/name.c              |  6 +-
 src/backend/utils/mmgr/README             | 22 ++++++-
 src/backend/utils/mmgr/mcxt.c             |  4 +-
 src/include/utils/memutils.h              |  7 ++-
 src/pl/plpgsql/src/pl_exec.c              | 21 +++----
 src/pl/plpython/plpython.c                | 71 +++++++++++------------
 19 files changed, 113 insertions(+), 113 deletions(-)

diff --git a/src/backend/access/nbtree/nbtree.c b/src/backend/access/nbtree/nbtree.c
index 7a1d8372d73..01fe502071e 100644
--- a/src/backend/access/nbtree/nbtree.c
+++ b/src/backend/access/nbtree/nbtree.c
@@ -12,7 +12,7 @@
  * Portions Copyright (c) 1994, Regents of the University of California
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/access/nbtree/nbtree.c,v 1.117 2004/06/02 17:28:17 tgl Exp $
+ *	  $PostgreSQL: pgsql/src/backend/access/nbtree/nbtree.c,v 1.118 2004/06/05 19:48:07 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -693,7 +693,7 @@ btvacuumcleanup(PG_FUNCTION_ARGS)
 	/* No point in remembering more than MaxFSMPages pages */
 	maxFreePages = MaxFSMPages;
 	if ((BlockNumber) maxFreePages > num_pages)
-		maxFreePages = (int) num_pages + 1;		/* +1 to avoid palloc(0) */
+		maxFreePages = (int) num_pages;
 	freePages = (BlockNumber *) palloc(maxFreePages * sizeof(BlockNumber));
 	nFreePages = 0;
 
diff --git a/src/backend/commands/analyze.c b/src/backend/commands/analyze.c
index 4efaf653ede..cf1c2e9f1d2 100644
--- a/src/backend/commands/analyze.c
+++ b/src/backend/commands/analyze.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/commands/analyze.c,v 1.73 2004/05/26 04:41:09 neilc Exp $
+ *	  $PostgreSQL: pgsql/src/backend/commands/analyze.c,v 1.74 2004/06/05 19:48:07 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -226,9 +226,8 @@ analyze_rel(Oid relid, VacuumStmt *vacstmt)
 	else
 	{
 		attr_cnt = onerel->rd_att->natts;
-		/* +1 here is just to avoid palloc(0) with zero-column table */
-		vacattrstats = (VacAttrStats **) palloc((attr_cnt + 1) *
-												sizeof(VacAttrStats *));
+		vacattrstats = (VacAttrStats **)
+			palloc(attr_cnt * sizeof(VacAttrStats *));
 		tcnt = 0;
 		for (i = 1; i <= attr_cnt; i++)
 		{
@@ -505,8 +504,8 @@ compute_index_stats(Relation onerel, double totalrows,
 							estate);
 
 		/* Compute and save index expression values */
-		exprvals = (Datum *) palloc((numrows * attr_cnt + 1) * sizeof(Datum));
-		exprnulls = (bool *) palloc((numrows * attr_cnt + 1) * sizeof(bool));
+		exprvals = (Datum *) palloc(numrows * attr_cnt * sizeof(Datum));
+		exprnulls = (bool *) palloc(numrows * attr_cnt * sizeof(bool));
 		numindexrows = 0;
 		tcnt = 0;
 		for (rowno = 0; rowno < numrows; rowno++)
diff --git a/src/backend/commands/copy.c b/src/backend/commands/copy.c
index a666516fb39..13ed62b8df2 100644
--- a/src/backend/commands/copy.c
+++ b/src/backend/commands/copy.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/commands/copy.c,v 1.224 2004/05/26 04:41:10 neilc Exp $
+ *	  $PostgreSQL: pgsql/src/backend/commands/copy.c,v 1.225 2004/06/05 19:48:07 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -1158,13 +1158,11 @@ CopyTo(Relation rel, List *attnumlist, bool binary, bool oids,
 
 	/*
 	 * Get info about the columns we need to process.
-	 *
-	 * +1's here are to avoid palloc(0) in a zero-column table.
 	 */
-	out_functions = (FmgrInfo *) palloc((num_phys_attrs + 1) * sizeof(FmgrInfo));
-	elements = (Oid *) palloc((num_phys_attrs + 1) * sizeof(Oid));
-	isvarlena = (bool *) palloc((num_phys_attrs + 1) * sizeof(bool));
-	force_quote = (bool *) palloc((num_phys_attrs + 1) * sizeof(bool));
+	out_functions = (FmgrInfo *) palloc(num_phys_attrs * sizeof(FmgrInfo));
+	elements = (Oid *) palloc(num_phys_attrs * sizeof(Oid));
+	isvarlena = (bool *) palloc(num_phys_attrs * sizeof(bool));
+	force_quote = (bool *) palloc(num_phys_attrs * sizeof(bool));
 	foreach(cur, attnumlist)
 	{
 		int			attnum = lfirst_int(cur);
@@ -1501,14 +1499,13 @@ CopyFrom(Relation rel, List *attnumlist, bool binary, bool oids,
 	 * relation, including the input function, the element type (to pass
 	 * to the input function), and info about defaults and constraints.
 	 * (Which input function we use depends on text/binary format choice.)
-	 * +1's here are to avoid palloc(0) in a zero-column table.
 	 */
-	in_functions = (FmgrInfo *) palloc((num_phys_attrs + 1) * sizeof(FmgrInfo));
-	elements = (Oid *) palloc((num_phys_attrs + 1) * sizeof(Oid));
-	defmap = (int *) palloc((num_phys_attrs + 1) * sizeof(int));
-	defexprs = (ExprState **) palloc((num_phys_attrs + 1) * sizeof(ExprState *));
-	constraintexprs = (ExprState **) palloc0((num_phys_attrs + 1) * sizeof(ExprState *));
-	force_notnull = (bool *) palloc((num_phys_attrs + 1) * sizeof(bool));
+	in_functions = (FmgrInfo *) palloc(num_phys_attrs * sizeof(FmgrInfo));
+	elements = (Oid *) palloc(num_phys_attrs * sizeof(Oid));
+	defmap = (int *) palloc(num_phys_attrs * sizeof(int));
+	defexprs = (ExprState **) palloc(num_phys_attrs * sizeof(ExprState *));
+	constraintexprs = (ExprState **) palloc0(num_phys_attrs * sizeof(ExprState *));
+	force_notnull = (bool *) palloc(num_phys_attrs * sizeof(bool));
 
 	for (attnum = 1; attnum <= num_phys_attrs; attnum++)
 	{
@@ -1635,8 +1632,8 @@ CopyFrom(Relation rel, List *attnumlist, bool binary, bool oids,
 		fmgr_info(in_func_oid, &oid_in_function);
 	}
 
-	values = (Datum *) palloc((num_phys_attrs + 1) * sizeof(Datum));
-	nulls = (char *) palloc((num_phys_attrs + 1) * sizeof(char));
+	values = (Datum *) palloc(num_phys_attrs * sizeof(Datum));
+	nulls = (char *) palloc(num_phys_attrs * sizeof(char));
 
 	/* Make room for a PARAM_EXEC value for domain constraint checks */
 	if (hasConstraints)
diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c
index 492532363a5..66c1b95135a 100644
--- a/src/backend/commands/tablecmds.c
+++ b/src/backend/commands/tablecmds.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/commands/tablecmds.c,v 1.110 2004/06/04 20:35:21 tgl Exp $
+ *	  $PostgreSQL: pgsql/src/backend/commands/tablecmds.c,v 1.111 2004/06/05 19:48:07 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -727,10 +727,10 @@ MergeAttributes(List *schema, List *supers, bool istemp,
 		 * newattno[] will contain the child-table attribute numbers for
 		 * the attributes of this parent table.  (They are not the same
 		 * for parents after the first one, nor if we have dropped
-		 * columns.)  +1 is to prevent error if parent has zero columns.
+		 * columns.)
 		 */
 		newattno = (AttrNumber *)
-			palloc((tupleDesc->natts + 1) * sizeof(AttrNumber));
+			palloc(tupleDesc->natts * sizeof(AttrNumber));
 
 		for (parent_attno = 1; parent_attno <= tupleDesc->natts;
 			 parent_attno++)
diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index aa6491af1c0..68164a9a80c 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -13,7 +13,7 @@
  *
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/commands/vacuum.c,v 1.279 2004/05/31 19:24:05 tgl Exp $
+ *	  $PostgreSQL: pgsql/src/backend/commands/vacuum.c,v 1.280 2004/06/05 19:48:07 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -2883,9 +2883,8 @@ vac_update_fsm(Relation onerel, VacPageList fraged_pages,
 	 */
 	threshold = GetAvgFSMRequestSize(&onerel->rd_node);
 
-	/* +1 to avoid palloc(0) */
 	pageSpaces = (PageFreeSpaceInfo *)
-		palloc((nPages + 1) * sizeof(PageFreeSpaceInfo));
+		palloc(nPages * sizeof(PageFreeSpaceInfo));
 	outPages = 0;
 
 	for (i = 0; i < nPages; i++)
diff --git a/src/backend/commands/vacuumlazy.c b/src/backend/commands/vacuumlazy.c
index f67c1c76fee..2e4b263b1a7 100644
--- a/src/backend/commands/vacuumlazy.c
+++ b/src/backend/commands/vacuumlazy.c
@@ -31,7 +31,7 @@
  *
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/commands/vacuumlazy.c,v 1.41 2004/05/31 19:24:05 tgl Exp $
+ *	  $PostgreSQL: pgsql/src/backend/commands/vacuumlazy.c,v 1.42 2004/06/05 19:48:07 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -918,9 +918,6 @@ lazy_space_alloc(LVRelStats *vacrelstats, BlockNumber relblocks)
 	/* No need to allocate more pages than the relation has blocks */
 	if (relblocks < (BlockNumber) maxpages)
 		maxpages = (int) relblocks;
-	/* avoid palloc(0) */
-	if (maxpages < 1)
-		maxpages = 1;
 
 	vacrelstats->fs_is_heap = false;
 	vacrelstats->num_free_pages = 0;
diff --git a/src/backend/executor/execQual.c b/src/backend/executor/execQual.c
index e53820efed0..8ada5e6faf2 100644
--- a/src/backend/executor/execQual.c
+++ b/src/backend/executor/execQual.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/executor/execQual.c,v 1.162 2004/06/01 03:28:41 tgl Exp $
+ *	  $PostgreSQL: pgsql/src/backend/executor/execQual.c,v 1.163 2004/06/05 19:48:08 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -2129,8 +2129,6 @@ ExecEvalRow(RowExprState *rstate,
 
 	/* Allocate workspace */
 	nargs = list_length(rstate->args);
-	if (nargs == 0)				/* avoid palloc(0) if no fields */
-		nargs = 1;
 	values = (Datum *) palloc(nargs * sizeof(Datum));
 	nulls = (char *) palloc(nargs * sizeof(char));
 
diff --git a/src/backend/optimizer/prep/prepunion.c b/src/backend/optimizer/prep/prepunion.c
index abc5af7784f..0e1b4f2aec0 100644
--- a/src/backend/optimizer/prep/prepunion.c
+++ b/src/backend/optimizer/prep/prepunion.c
@@ -14,7 +14,7 @@
  *
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/optimizer/prep/prepunion.c,v 1.113 2004/06/05 01:55:04 tgl Exp $
+ *	  $PostgreSQL: pgsql/src/backend/optimizer/prep/prepunion.c,v 1.114 2004/06/05 19:48:08 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -538,9 +538,9 @@ generate_append_tlist(List *colTypes, bool flag,
 	 * First extract typmods to use.
 	 *
 	 * If the inputs all agree on type and typmod of a particular column, use
-	 * that typmod; else use -1.  (+1 here in case of zero columns.)
+	 * that typmod; else use -1.
 	 */
-	colTypmods = (int32 *) palloc(list_length(colTypes) * sizeof(int32) + 1);
+	colTypmods = (int32 *) palloc(list_length(colTypes) * sizeof(int32));
 
 	foreach(planl, input_plans)
 	{
diff --git a/src/backend/optimizer/util/clauses.c b/src/backend/optimizer/util/clauses.c
index bf12320626d..b22360ac2b1 100644
--- a/src/backend/optimizer/util/clauses.c
+++ b/src/backend/optimizer/util/clauses.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/optimizer/util/clauses.c,v 1.173 2004/06/01 04:47:45 tgl Exp $
+ *	  $PostgreSQL: pgsql/src/backend/optimizer/util/clauses.c,v 1.174 2004/06/05 19:48:08 tgl Exp $
  *
  * HISTORY
  *	  AUTHOR			DATE			MAJOR EVENT
@@ -2016,7 +2016,7 @@ inline_function(Oid funcid, Oid result_type, List *args,
 	 * actual substitution of the inputs.  So start building expression
 	 * with inputs substituted.
 	 */
-	usecounts = (int *) palloc0((funcform->pronargs + 1) * sizeof(int));
+	usecounts = (int *) palloc0(funcform->pronargs * sizeof(int));
 	newexpr = substitute_actual_parameters(newexpr, funcform->pronargs,
 										   args, usecounts);
 
diff --git a/src/backend/storage/freespace/freespace.c b/src/backend/storage/freespace/freespace.c
index 3c149c3510b..527ad8496ab 100644
--- a/src/backend/storage/freespace/freespace.c
+++ b/src/backend/storage/freespace/freespace.c
@@ -8,7 +8,7 @@
  * Portions Copyright (c) 1994, Regents of the University of California
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/storage/freespace/freespace.c,v 1.30 2004/01/26 22:35:32 tgl Exp $
+ *	  $PostgreSQL: pgsql/src/backend/storage/freespace/freespace.c,v 1.31 2004/06/05 19:48:08 tgl Exp $
  *
  *
  * NOTES:
@@ -893,7 +893,7 @@ LoadFreeSpaceMap(void)
 			len = nPages * sizeof(IndexFSMPageData);
 		else
 			len = nPages * sizeof(FSMPageData);
-		data = (char *) palloc(len + 1);		/* +1 to avoid palloc(0) */
+		data = (char *) palloc(len);
 		if (fread(data, 1, len, fp) != len)
 		{
 			elog(LOG, "premature EOF in \"%s\"", cachefilename);
diff --git a/src/backend/storage/lmgr/deadlock.c b/src/backend/storage/lmgr/deadlock.c
index 905b96f66bf..4170221b22f 100644
--- a/src/backend/storage/lmgr/deadlock.c
+++ b/src/backend/storage/lmgr/deadlock.c
@@ -12,7 +12,7 @@
  *
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/storage/lmgr/deadlock.c,v 1.27 2003/12/01 21:59:25 momjian Exp $
+ *	  $PostgreSQL: pgsql/src/backend/storage/lmgr/deadlock.c,v 1.28 2004/06/05 19:48:08 tgl Exp $
  *
  *	Interface:
  *
@@ -147,11 +147,10 @@ InitDeadLockChecking(void)
 	 * We need to consider rearranging at most MaxBackends/2 wait queues
 	 * (since it takes at least two waiters in a queue to create a soft
 	 * edge), and the expanded form of the wait queues can't involve more
-	 * than MaxBackends total waiters.	(But avoid palloc(0) if
-	 * MaxBackends = 1.)
+	 * than MaxBackends total waiters.
 	 */
 	waitOrders = (WAIT_ORDER *)
-		palloc(((MaxBackends + 1) / 2) * sizeof(WAIT_ORDER));
+		palloc((MaxBackends / 2) * sizeof(WAIT_ORDER));
 	waitOrderProcs = (PGPROC **) palloc(MaxBackends * sizeof(PGPROC *));
 
 	/*
diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c
index 88179a0731a..c04f3b5c88a 100644
--- a/src/backend/storage/lmgr/lock.c
+++ b/src/backend/storage/lmgr/lock.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/storage/lmgr/lock.c,v 1.132 2004/05/28 05:13:05 tgl Exp $
+ *	  $PostgreSQL: pgsql/src/backend/storage/lmgr/lock.c,v 1.133 2004/06/05 19:48:08 tgl Exp $
  *
  * NOTES
  *	  Outside modules can create a lock table and acquire/release
@@ -1361,9 +1361,6 @@ GetLockStatusData(void)
 
 	data->nelements = i = proclockTable->hctl->nentries;
 
-	if (i == 0)
-		i = 1;					/* avoid palloc(0) if empty table */
-
 	data->proclockaddrs = (SHMEM_OFFSET *) palloc(sizeof(SHMEM_OFFSET) * i);
 	data->proclocks = (PROCLOCK *) palloc(sizeof(PROCLOCK) * i);
 	data->procs = (PGPROC *) palloc(sizeof(PGPROC) * i);
diff --git a/src/backend/tcop/pquery.c b/src/backend/tcop/pquery.c
index e79c58f7025..85d05ed1b8b 100644
--- a/src/backend/tcop/pquery.c
+++ b/src/backend/tcop/pquery.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/tcop/pquery.c,v 1.79 2004/05/26 18:54:08 tgl Exp $
+ *	  $PostgreSQL: pgsql/src/backend/tcop/pquery.c,v 1.80 2004/06/05 19:48:08 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -347,10 +347,9 @@ PortalSetResultFormat(Portal portal, int nFormats, int16 *formats)
 	if (portal->tupDesc == NULL)
 		return;
 	natts = portal->tupDesc->natts;
-	/* +1 avoids palloc(0) if no columns */
 	portal->formats = (int16 *)
 		MemoryContextAlloc(PortalGetHeapMemory(portal),
-						   (natts + 1) * sizeof(int16));
+						   natts * sizeof(int16));
 	if (nFormats > 1)
 	{
 		/* format specified for each column */
diff --git a/src/backend/utils/adt/name.c b/src/backend/utils/adt/name.c
index ecac8d2d500..cf4f14c3e15 100644
--- a/src/backend/utils/adt/name.c
+++ b/src/backend/utils/adt/name.c
@@ -14,7 +14,7 @@
  *
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/utils/adt/name.c,v 1.52 2004/05/30 23:40:35 neilc Exp $
+ *	  $PostgreSQL: pgsql/src/backend/utils/adt/name.c,v 1.53 2004/06/05 19:48:09 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -358,9 +358,7 @@ current_schemas(PG_FUNCTION_ARGS)
 	int			i;
 	ArrayType  *array;
 
-	/* +1 here is just to avoid palloc(0) error */
-
-	names = (Datum *) palloc((list_length(search_path) + 1) * sizeof(Datum));
+	names = (Datum *) palloc(list_length(search_path) * sizeof(Datum));
 	i = 0;
 	foreach(l, search_path)
 	{
diff --git a/src/backend/utils/mmgr/README b/src/backend/utils/mmgr/README
index 409cfd768c8..f705827c1b6 100644
--- a/src/backend/utils/mmgr/README
+++ b/src/backend/utils/mmgr/README
@@ -1,4 +1,4 @@
-$PostgreSQL: pgsql/src/backend/utils/mmgr/README,v 1.5 2003/11/29 19:52:04 pgsql Exp $
+$PostgreSQL: pgsql/src/backend/utils/mmgr/README,v 1.6 2004/06/05 19:48:09 tgl Exp $
 
 Notes about memory allocation redesign
 --------------------------------------
@@ -53,6 +53,26 @@ that can be reset or deleted at strategic times within a query, such as
 after each tuple.
 
 
+Some notes about the palloc API versus standard C library
+---------------------------------------------------------
+
+The behavior of palloc and friends is similar to the standard C library's
+malloc and friends, but there are some deliberate differences too.  Here
+are some notes to clarify the behavior.
+
+* If out of memory, palloc and repalloc exit via elog(ERROR).  They never
+return NULL, and it is not necessary or useful to test for such a result.
+
+* palloc(0) is explicitly a valid operation.  It does not return a NULL
+pointer, but a valid chunk of which no bytes may be used.  (However, the
+chunk might later be repalloc'd larger; it can also be pfree'd without
+error.)  (Note: this behavior is new in Postgres 7.5; earlier versions
+disallowed palloc(0).  It seems more consistent to allow it, however.)
+Similarly, repalloc allows realloc'ing to zero size.
+
+* pfree and repalloc do not accept a NULL pointer.  This is intentional.
+
+
 pfree/repalloc no longer depend on CurrentMemoryContext
 -------------------------------------------------------
 
diff --git a/src/backend/utils/mmgr/mcxt.c b/src/backend/utils/mmgr/mcxt.c
index bc139a7d96a..c444886e140 100644
--- a/src/backend/utils/mmgr/mcxt.c
+++ b/src/backend/utils/mmgr/mcxt.c
@@ -14,7 +14,7 @@
  *
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/utils/mmgr/mcxt.c,v 1.44 2003/11/29 19:52:04 pgsql Exp $
+ *	  $PostgreSQL: pgsql/src/backend/utils/mmgr/mcxt.c,v 1.45 2004/06/05 19:48:09 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -565,7 +565,7 @@ pfree(void *pointer)
 
 /*
  * repalloc
- *
+ *		Adjust the size of a previously allocated chunk.
  */
 void *
 repalloc(void *pointer, Size size)
diff --git a/src/include/utils/memutils.h b/src/include/utils/memutils.h
index 29e3878c998..7865859c062 100644
--- a/src/include/utils/memutils.h
+++ b/src/include/utils/memutils.h
@@ -10,7 +10,7 @@
  * Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/include/utils/memutils.h,v 1.54 2003/11/29 22:41:15 pgsql Exp $
+ * $PostgreSQL: pgsql/src/include/utils/memutils.h,v 1.55 2004/06/05 19:48:09 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -31,10 +31,13 @@
  *
  * XXX This is deliberately chosen to correspond to the limiting size
  * of varlena objects under TOAST.	See VARATT_MASK_SIZE in postgres.h.
+ *
+ * XXX Also, various places in aset.c assume they can compute twice an
+ * allocation's size without overflow, so beware of raising this.
  */
 #define MaxAllocSize	((Size) 0x3fffffff)		/* 1 gigabyte - 1 */
 
-#define AllocSizeIsValid(size)	(0 < (size) && (size) <= MaxAllocSize)
+#define AllocSizeIsValid(size)	((Size) (size) <= MaxAllocSize)
 
 /*
  * All chunks allocated by any memory context manager are required to be
diff --git a/src/pl/plpgsql/src/pl_exec.c b/src/pl/plpgsql/src/pl_exec.c
index 5a3d77a07c6..e479094099e 100644
--- a/src/pl/plpgsql/src/pl_exec.c
+++ b/src/pl/plpgsql/src/pl_exec.c
@@ -3,7 +3,7 @@
  *			  procedural language
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/pl/plpgsql/src/pl_exec.c,v 1.104 2004/06/04 02:37:06 tgl Exp $
+ *	  $PostgreSQL: pgsql/src/pl/plpgsql/src/pl_exec.c,v 1.105 2004/06/05 19:48:09 tgl Exp $
  *
  *	  This software is copyrighted by Jan Wieck - Hamburg.
  *
@@ -1942,10 +1942,8 @@ exec_prepare_plan(PLpgSQL_execstate * estate,
 	/*
 	 * We need a temporary argtypes array to load with data. (The finished
 	 * plan structure will contain a copy of it.)
-	 *
-	 * +1 is just to avoid palloc(0) error.
 	 */
-	argtypes = (Oid *) palloc(sizeof(Oid) * (expr->nparams + 1));
+	argtypes = (Oid *) palloc(expr->nparams * sizeof(Oid));
 
 	for (i = 0; i < expr->nparams; i++)
 	{
@@ -1998,8 +1996,8 @@ exec_stmt_execsql(PLpgSQL_execstate * estate,
 	/*
 	 * Now build up the values and nulls arguments for SPI_execp()
 	 */
-	values = palloc(sizeof(Datum) * (expr->nparams + 1));
-	nulls = palloc(expr->nparams + 1);
+	values = (Datum *) palloc(expr->nparams * sizeof(Datum));
+	nulls = (char *) palloc(expr->nparams * sizeof(char));
 
 	for (i = 0; i < expr->nparams; i++)
 	{
@@ -2479,8 +2477,8 @@ exec_stmt_open(PLpgSQL_execstate * estate, PLpgSQL_stmt_open * stmt)
 	 * refcursor opened with OPEN ... FOR SELECT ...;
 	 * ----------
 	 */
-	values = palloc(sizeof(Datum) * (query->nparams + 1));
-	nulls = palloc(query->nparams + 1);
+	values = (Datum *) palloc(query->nparams * sizeof(Datum));
+	nulls = (char *) palloc(query->nparams * sizeof(char));
 
 	for (i = 0; i < query->nparams; i++)
 	{
@@ -3324,8 +3322,8 @@ exec_run_select(PLpgSQL_execstate * estate,
 	/*
 	 * Now build up the values and nulls arguments for SPI_execp()
 	 */
-	values = palloc(sizeof(Datum) * (expr->nparams + 1));
-	nulls = palloc(expr->nparams + 1);
+	values = (Datum *) palloc(expr->nparams * sizeof(Datum));
+	nulls = (char *) palloc(expr->nparams * sizeof(char));
 
 	for (i = 0; i < expr->nparams; i++)
 	{
@@ -3528,8 +3526,7 @@ exec_move_row(PLpgSQL_execstate * estate,
 			/* If we have a tupdesc but no data, form an all-nulls tuple */
 			char	   *nulls;
 
-			/* +1 to avoid possible palloc(0) if no attributes */
-			nulls = (char *) palloc(tupdesc->natts * sizeof(char) + 1);
+			nulls = (char *) palloc(tupdesc->natts * sizeof(char));
 			memset(nulls, 'n', tupdesc->natts * sizeof(char));
 
 			rec->tup = heap_formtuple(tupdesc, NULL, nulls);
diff --git a/src/pl/plpython/plpython.c b/src/pl/plpython/plpython.c
index f660adf2973..d07af29c816 100644
--- a/src/pl/plpython/plpython.c
+++ b/src/pl/plpython/plpython.c
@@ -29,7 +29,7 @@
  * MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
  *
  * IDENTIFICATION
- *	$PostgreSQL: pgsql/src/pl/plpython/plpython.c,v 1.47 2004/05/07 00:24:59 tgl Exp $
+ *	$PostgreSQL: pgsql/src/pl/plpython/plpython.c,v 1.48 2004/06/05 19:48:09 tgl Exp $
  *
  *********************************************************************
  */
@@ -531,10 +531,9 @@ PLy_modify_tuple(PLyProcedure * proc, PyObject * pltd, TriggerData *tdata,
 	plkeys = PyDict_Keys(plntup);
 	natts = PyList_Size(plkeys);
 
-	/* +1 to avoid palloc(0) on empty tuple */
-	modattrs = palloc(natts * sizeof(int) + 1);
-	modvalues = palloc(natts * sizeof(Datum) + 1);
-	modnulls = palloc(natts + 1);
+	modattrs = (int *) palloc(natts * sizeof(int));
+	modvalues = (Datum *) palloc(natts * sizeof(Datum));
+	modnulls = (char *) palloc(natts * sizeof(char));
 
 	tupdesc = tdata->tg_relation->rd_att;
 
@@ -2174,48 +2173,46 @@ PLy_spi_execute_plan(PyObject * ob, PyObject * list, int limit)
 		RERAISE_EXC();
 	}
 
-	if (nargs)
+	nulls = palloc(nargs * sizeof(char));
+
+	for (i = 0; i < nargs; i++)
 	{
-		nulls = palloc((nargs + 1) * sizeof(char));
+		PyObject   *elem,
+				   *so;
+		char	   *sv;
 
-		for (i = 0; i < nargs; i++)
+		elem = PySequence_GetItem(list, i);
+		if (elem != Py_None)
 		{
-			PyObject   *elem,
-					   *so;
-			char	   *sv;
+			so = PyObject_Str(elem);
+			sv = PyString_AsString(so);
 
-			elem = PySequence_GetItem(list, i);
-			if (elem != Py_None)
-			{
-				so = PyObject_Str(elem);
-				sv = PyString_AsString(so);
-
-				/*
-				 * FIXME -- if this can elog, we have leak
-				 */
-				plan->values[i] = FunctionCall3(&(plan->args[i].out.d.typfunc),
-												CStringGetDatum(sv),
-						   ObjectIdGetDatum(plan->args[i].out.d.typelem),
-												Int32GetDatum(-1));
+			/*
+			 * FIXME -- if this can elog, we have leak
+			 */
+			plan->values[i] =
+				FunctionCall3(&(plan->args[i].out.d.typfunc),
+							  CStringGetDatum(sv),
+							  ObjectIdGetDatum(plan->args[i].out.d.typelem),
+							  Int32GetDatum(-1));
 
-				Py_DECREF(so);
-				Py_DECREF(elem);
+			Py_DECREF(so);
+			Py_DECREF(elem);
 
-				nulls[i] = ' ';
-			}
-			else
-			{
-				Py_DECREF(elem);
-				plan->values[i] = (Datum) 0;
-				nulls[i] = 'n';
-			}
+			nulls[i] = ' ';
+		}
+		else
+		{
+			Py_DECREF(elem);
+			plan->values[i] = (Datum) 0;
+			nulls[i] = 'n';
 		}
-		nulls[i] = '\0';
 	}
-	else
-		nulls = NULL;
 
 	rv = SPI_execp(plan->plan, plan->values, nulls, limit);
+
+	pfree(nulls);
+
 	RESTORE_EXC();
 
 	for (i = 0; i < nargs; i++)
-- 
GitLab