OSDN Git Service

Add tests to enlargeStringInfo() to avoid possible buffer-overrun or
authorTom Lane <tgl@sss.pgh.pa.us>
Tue, 11 May 2004 20:07:26 +0000 (20:07 +0000)
committerTom Lane <tgl@sss.pgh.pa.us>
Tue, 11 May 2004 20:07:26 +0000 (20:07 +0000)
infinite-loop problems if a bogus data length is passed.

src/backend/lib/stringinfo.c

index 26fdbc8..4ca8ffe 100644 (file)
@@ -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;