aboutsummaryrefslogtreecommitdiff
path: root/src/interfaces/libpq/pqexpbuffer.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/interfaces/libpq/pqexpbuffer.c')
-rw-r--r--src/interfaces/libpq/pqexpbuffer.c68
1 files changed, 21 insertions, 47 deletions
diff --git a/src/interfaces/libpq/pqexpbuffer.c b/src/interfaces/libpq/pqexpbuffer.c
index 86b16e60fb2..0814ec6dbe0 100644
--- a/src/interfaces/libpq/pqexpbuffer.c
+++ b/src/interfaces/libpq/pqexpbuffer.c
@@ -295,76 +295,50 @@ appendPQExpBufferVA(PQExpBuffer str, const char *fmt, va_list args)
*/
if (str->maxlen > str->len + 16)
{
- /*
- * Note: we intentionally leave one byte unused, as a guard against
- * old broken versions of vsnprintf.
- */
- avail = str->maxlen - str->len - 1;
-
- errno = 0;
+ avail = str->maxlen - str->len;
nprinted = vsnprintf(str->data + str->len, avail, fmt, args);
/*
- * If vsnprintf reports an error other than ENOMEM, fail.
+ * If vsnprintf reports an error, fail (we assume this means there's
+ * something wrong with the format string).
*/
- if (nprinted < 0 && errno != 0 && errno != ENOMEM)
+ if (unlikely(nprinted < 0))
{
markPQExpBufferBroken(str);
return true;
}
- /*
- * Note: some versions of vsnprintf return the number of chars
- * actually stored, not the total space needed as C99 specifies. And
- * at least one returns -1 on failure. Be conservative about
- * believing whether the print worked.
- */
- if (nprinted >= 0 && (size_t) nprinted < avail - 1)
+ if ((size_t) nprinted < avail)
{
/* Success. Note nprinted does not include trailing null. */
str->len += nprinted;
return true;
}
- if (nprinted >= 0 && (size_t) nprinted > avail)
- {
- /*
- * This appears to be a C99-compliant vsnprintf, so believe its
- * estimate of the required space. (If it's wrong, the logic will
- * still work, but we may loop multiple times.) Note that the
- * space needed should be only nprinted+1 bytes, but we'd better
- * allocate one more than that so that the test above will succeed
- * next time.
- *
- * In the corner case where the required space just barely
- * overflows, fail.
- */
- if (nprinted > INT_MAX - 2)
- {
- markPQExpBufferBroken(str);
- return true;
- }
- needed = nprinted + 2;
- }
- else
+ /*
+ * We assume a C99-compliant vsnprintf, so believe its estimate of the
+ * required space, and add one for the trailing null. (If it's wrong,
+ * the logic will still work, but we may loop multiple times.)
+ *
+ * Choke if the required space would exceed INT_MAX, since str->maxlen
+ * can't represent more than that.
+ */
+ if (unlikely(nprinted > INT_MAX - 1))
{
- /*
- * Buffer overrun, and we don't know how much space is needed.
- * Estimate twice the previous buffer size, but not more than
- * INT_MAX.
- */
- if (avail >= INT_MAX / 2)
- needed = INT_MAX;
- else
- needed = avail * 2;
+ markPQExpBufferBroken(str);
+ return true;
}
+ needed = nprinted + 1;
}
else
{
/*
* We have to guess at how much to enlarge, since we're skipping the
- * formatting work.
+ * formatting work. Fortunately, because of enlargePQExpBuffer's
+ * preference for power-of-2 sizes, this number isn't very sensitive;
+ * the net effect is that we'll double the buffer size before trying
+ * to run vsnprintf, which seems sensible.
*/
needed = 32;
}