From a2160c5eeb9c6457dc2da5f7a406dee182e302c4 Mon Sep 17 00:00:00 2001
From: Tom Lane <tgl@sss.pgh.pa.us>
Date: Tue, 11 May 2004 20:07:26 +0000
Subject: [PATCH] Add tests to enlargeStringInfo() to avoid possible
 buffer-overrun or infinite-loop problems if a bogus data length is passed.

---
 src/backend/lib/stringinfo.c | 24 +++++++++++++++++++++++-
 1 file changed, 23 insertions(+), 1 deletion(-)

diff --git a/src/backend/lib/stringinfo.c b/src/backend/lib/stringinfo.c
index 26fdbc8e488..4ca8ffeaa99 100644
--- a/src/backend/lib/stringinfo.c
+++ b/src/backend/lib/stringinfo.c
@@ -9,13 +9,14 @@
  * Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- *	  $PostgreSQL: pgsql/src/backend/lib/stringinfo.c,v 1.37 2003/11/29 22:39:42 pgsql Exp $
+ *	  $PostgreSQL: pgsql/src/backend/lib/stringinfo.c,v 1.38 2004/05/11 20:07:26 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
 #include "postgres.h"
 
 #include "lib/stringinfo.h"
+#include "utils/memutils.h"
 
 
 /*
@@ -220,7 +221,20 @@ enlargeStringInfo(StringInfo str, int needed)
 {
 	int			newlen;
 
+	/*
+	 * Guard against ridiculous "needed" values, which can occur if we're
+	 * fed bogus data.  Without this, we can get an overflow or infinite
+	 * loop in the following.
+	 */
+	if (needed < 0 ||
+		((Size) needed) >= (MaxAllocSize - (Size) str->len))
+		elog(ERROR, "invalid string enlargement request size %d",
+			 needed);
+
 	needed += str->len + 1;		/* total space required now */
+
+	/* Because of the above test, we now have needed <= MaxAllocSize */
+
 	if (needed <= str->maxlen)
 		return;					/* got enough space already */
 
@@ -234,6 +248,14 @@ enlargeStringInfo(StringInfo str, int needed)
 	while (needed > newlen)
 		newlen = 2 * newlen;
 
+	/*
+	 * Clamp to MaxAllocSize in case we went past it.  Note we are assuming
+	 * here that MaxAllocSize <= INT_MAX/2, else the above loop could
+	 * overflow.  We will still have newlen >= needed.
+	 */
+	if (newlen > (int) MaxAllocSize)
+		newlen = (int) MaxAllocSize;
+
 	str->data = (char *) repalloc(str->data, newlen);
 
 	str->maxlen = newlen;
-- 
GitLab