From cf34fdbbe1452b9e19c0956bc48494889e1b2777 Mon Sep 17 00:00:00 2001
From: Tom Lane <tgl@sss.pgh.pa.us>
Date: Mon, 29 Aug 2016 09:29:26 -0400
Subject: [PATCH] Make AllocSetContextCreate throw an error for bad
 context-size parameters.

The previous behavior was to silently change them to something valid.
That obscured the bugs fixed in commit ea268cdc9, and generally seems
less useful than complaining.  Unlike the previous commit, though,
we'll do this in HEAD only --- it's a bit too late to be possibly
breaking third-party code in 9.6.

Discussion: <CA+TgmobNcELVd3QmLD3tx=w7+CokRQiC4_U0txjz=WHpfdkU=w@mail.gmail.com>
---
 src/backend/utils/mmgr/aset.c | 37 ++++++++++++++++++++++-------------
 1 file changed, 23 insertions(+), 14 deletions(-)

diff --git a/src/backend/utils/mmgr/aset.c b/src/backend/utils/mmgr/aset.c
index 43c85234ce1..f44e46767b2 100644
--- a/src/backend/utils/mmgr/aset.c
+++ b/src/backend/utils/mmgr/aset.c
@@ -445,6 +445,26 @@ AllocSetContextCreate(MemoryContext parent,
 {
 	AllocSet	set;
 
+	/*
+	 * First, validate allocation parameters.  (If we're going to throw an
+	 * error, we should do so before the context is created, not after.)  We
+	 * somewhat arbitrarily enforce a minimum 1K block size.
+	 */
+	if (initBlockSize != MAXALIGN(initBlockSize) ||
+		initBlockSize < 1024)
+		elog(ERROR, "invalid initBlockSize for memory context: %zu",
+			 initBlockSize);
+	if (maxBlockSize != MAXALIGN(maxBlockSize) ||
+		maxBlockSize < initBlockSize ||
+		!AllocHugeSizeIsValid(maxBlockSize))	/* must be safe to double */
+		elog(ERROR, "invalid maxBlockSize for memory context: %zu",
+			 maxBlockSize);
+	if (minContextSize != 0 &&
+		(minContextSize != MAXALIGN(minContextSize) ||
+		 minContextSize <= ALLOC_BLOCKHDRSZ + ALLOC_CHUNKHDRSZ))
+		elog(ERROR, "invalid minContextSize for memory context: %zu",
+			 minContextSize);
+
 	/* Do the type-independent part of context creation */
 	set = (AllocSet) MemoryContextCreate(T_AllocSetContext,
 										 sizeof(AllocSetContext),
@@ -452,18 +472,7 @@ AllocSetContextCreate(MemoryContext parent,
 										 parent,
 										 name);
 
-	/*
-	 * Make sure alloc parameters are reasonable, and save them.
-	 *
-	 * We somewhat arbitrarily enforce a minimum 1K block size.
-	 */
-	initBlockSize = MAXALIGN(initBlockSize);
-	if (initBlockSize < 1024)
-		initBlockSize = 1024;
-	maxBlockSize = MAXALIGN(maxBlockSize);
-	if (maxBlockSize < initBlockSize)
-		maxBlockSize = initBlockSize;
-	Assert(AllocHugeSizeIsValid(maxBlockSize)); /* must be safe to double */
+	/* Save allocation parameters */
 	set->initBlockSize = initBlockSize;
 	set->maxBlockSize = maxBlockSize;
 	set->nextBlockSize = initBlockSize;
@@ -495,9 +504,9 @@ AllocSetContextCreate(MemoryContext parent,
 	/*
 	 * Grab always-allocated space, if requested
 	 */
-	if (minContextSize > ALLOC_BLOCKHDRSZ + ALLOC_CHUNKHDRSZ)
+	if (minContextSize > 0)
 	{
-		Size		blksize = MAXALIGN(minContextSize);
+		Size		blksize = minContextSize;
 		AllocBlock	block;
 
 		block = (AllocBlock) malloc(blksize);
-- 
GitLab