aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTom Lane <tgl@sss.pgh.pa.us>2004-05-11 20:07:38 +0000
committerTom Lane <tgl@sss.pgh.pa.us>2004-05-11 20:07:38 +0000
commit5e027b19cd79c944a3fb1b9024745d563c9e57cb (patch)
tree58ba44e4acf2205bc203d0bad5bdaad9b6dd3867
parentb8de9b216ffaa52d6c4cac09292f2c0e9fbf8c53 (diff)
downloadpostgresql-5e027b19cd79c944a3fb1b9024745d563c9e57cb.tar.gz
postgresql-5e027b19cd79c944a3fb1b9024745d563c9e57cb.zip
Add tests to enlargeStringInfo() to avoid possible buffer-overrun or
infinite-loop problems if a bogus data length is passed.
-rw-r--r--src/backend/lib/stringinfo.c24
1 files changed, 23 insertions, 1 deletions
diff --git a/src/backend/lib/stringinfo.c b/src/backend/lib/stringinfo.c
index 3d7c24bb4fa..d23e6a254a9 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
*
- * $Id: stringinfo.c,v 1.36 2003/08/04 02:39:59 momjian Exp $
+ * $Id: stringinfo.c,v 1.36.4.1 2004/05/11 20:07:38 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;