1
0
mirror of https://github.com/postgres/postgres.git synced 2025-08-18 12:22:09 +03:00

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
This commit is contained in:
Tom Lane
2018-08-16 13:01:09 -04:00
parent 1eb9221585
commit e1d19c902e
6 changed files with 125 additions and 123 deletions

View File

@@ -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)
/*
* 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))
{
/*
* 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
{
/*
* 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;
}