* a usable vsnprintf(), then a copy of our own implementation of it will
* be linked into libpq.
*
- * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $Header: /cvsroot/pgsql/src/interfaces/libpq/pqexpbuffer.c,v 1.8 2001/01/24 19:43:31 momjian Exp $
+ * $PostgreSQL: pgsql/src/interfaces/libpq/pqexpbuffer.c,v 1.22 2006/03/05 15:59:10 momjian Exp $
*
*-------------------------------------------------------------------------
*/
-#include "postgres.h"
+#include "postgres_fe.h"
+
+#include <limits.h>
+
#include "pqexpbuffer.h"
#ifdef WIN32
-#include <stdarg.h>
-#include <stdio.h>
#include "win32.h"
#endif
}
}
-/*------------------------
+/*
* destroyPQExpBuffer(str);
+ *
* free()s both the data buffer and the PQExpBufferData.
* This is the inverse of createPQExpBuffer().
*/
}
}
-/*------------------------
+/*
* termPQExpBuffer(str)
* free()s the data buffer but not the PQExpBufferData itself.
* This is the inverse of initPQExpBuffer().
str->len = 0;
}
-/*------------------------
+/*
* resetPQExpBuffer
* Reset a PQExpBuffer to empty
*/
}
}
-/*------------------------
+/*
* enlargePQExpBuffer
* Make sure there is enough space for 'needed' more bytes in the buffer
* ('needed' does not include the terminating null).
size_t newlen;
char *newdata;
+ /*
+ * 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 >= ((size_t) INT_MAX - str->len))
+ return 0;
+
needed += str->len + 1; /* total space required now */
+
+ /* Because of the above test, we now have needed <= INT_MAX */
+
if (needed <= str->maxlen)
return 1; /* got enough space already */
/*
- * We don't want to allocate just a little more space with each
- * append; for efficiency, double the buffer size each time it
- * overflows. Actually, we might need to more than double it if
- * 'needed' is big...
+ * We don't want to allocate just a little more space with each append;
+ * for efficiency, double the buffer size each time it overflows.
+ * Actually, we might need to more than double it if 'needed' is big...
*/
newlen = (str->maxlen > 0) ? (2 * str->maxlen) : 64;
while (needed > newlen)
newlen = 2 * newlen;
+ /*
+ * Clamp to INT_MAX in case we went past it. Note we are assuming here
+ * that INT_MAX <= UINT_MAX/2, else the above loop could overflow. We
+ * will still have newlen >= needed.
+ */
+ if (newlen > (size_t) INT_MAX)
+ newlen = (size_t) INT_MAX;
+
newdata = (char *) realloc(str->data, newlen);
if (newdata != NULL)
{
return 0;
}
-/*------------------------
+/*
* printfPQExpBuffer
* Format text data under the control of fmt (an sprintf-like format string)
* and insert it into str. More space is allocated to str if necessary.
for (;;)
{
- /*----------
- * Try to format the given string into the available space;
- * but if there's hardly any space, don't bother trying,
- * just fall through to enlarge the buffer first.
- *----------
+ /*
+ * Try to format the given string into the available space; but if
+ * there's hardly any space, don't bother trying, just fall through to
+ * enlarge the buffer first.
*/
if (str->maxlen > str->len + 16)
{
* actually stored, but at least one returns -1 on failure. Be
* conservative about believing whether the print worked.
*/
- if (nprinted >= 0 && nprinted < avail - 1)
+ if (nprinted >= 0 && nprinted < (int) avail - 1)
{
/* Success. Note nprinted does not include trailing null. */
str->len += nprinted;
}
}
-/*------------------------
+/*
* appendPQExpBuffer
*
* Format text data under the control of fmt (an sprintf-like format string)
for (;;)
{
- /*----------
- * Try to format the given string into the available space;
- * but if there's hardly any space, don't bother trying,
- * just fall through to enlarge the buffer first.
- *----------
+ /*
+ * Try to format the given string into the available space; but if
+ * there's hardly any space, don't bother trying, just fall through to
+ * enlarge the buffer first.
*/
if (str->maxlen > str->len + 16)
{
* actually stored, but at least one returns -1 on failure. Be
* conservative about believing whether the print worked.
*/
- if (nprinted >= 0 && nprinted < avail - 1)
+ if (nprinted >= 0 && nprinted < (int) avail - 1)
{
/* Success. Note nprinted does not include trailing null. */
str->len += nprinted;
}
}
-/*------------------------
+/*
* appendPQExpBufferStr
* Append the given string to a PQExpBuffer, allocating more space
* if necessary.
appendBinaryPQExpBuffer(str, data, strlen(data));
}
-/*------------------------
+/*
* appendPQExpBufferChar
* Append a single byte to str.
* Like appendPQExpBuffer(str, "%c", ch) but much faster.
str->len += datalen;
/*
- * Keep a trailing null in place, even though it's probably useless
- * for binary data...
+ * Keep a trailing null in place, even though it's probably useless for
+ * binary data...
*/
str->data[str->len] = '\0';
}