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:
@@ -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;
|
||||
}
|
||||
|
Reference in New Issue
Block a user