summaryrefslogtreecommitdiff
path: root/src/interfaces
diff options
context:
space:
mode:
authorTom Lane2018-08-16 17:01:09 +0000
committerTom Lane2018-08-16 17:01:09 +0000
commite1d19c902e59ad739cb4b6267ee2073a61e86cd3 (patch)
treee6090aad9384ba77d324694e2553d02e1d0b7566 /src/interfaces
parent1eb9221585c25cad1a563bc3414f697dae3fbc8b (diff)
Require a C99-compliant snprintf(), and remove related workarounds.
Since our substitute snprintf now returns a C99-compliant result, there's no need anymore to have complicated code to cope with pre-C99 behavior. We can just make configure substitute snprintf.c if it finds that the system snprintf() is pre-C99. (Note: I do not believe that there are any platforms where this test will trigger that weren't already being rejected due to our other C99-ish feature requirements for snprintf. But let's add the check for paranoia's sake.) Then, simplify the call sites that had logic to cope with the pre-C99 definition. I also dropped some stuff that was being paranoid about the possibility of snprintf overrunning the given buffer. The only reports we've ever heard of that being a problem were for Solaris 7, which is long dead, and we've sure not heard any reports of these assertions triggering in a long time. So let's drop that complexity too. Likewise, drop some code that wasn't trusting snprintf to set errno when it returns -1. That would be not-per-spec, and again there's no real reason to believe it is a live issue, especially not for snprintfs that pass all of configure's feature checks. Discussion: https://postgr.es/m/17245.1534289329@sss.pgh.pa.us
Diffstat (limited to 'src/interfaces')
-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;
}