bpo-36020: Require vsnprintf() to build Python by vstinner · Pull Request #20899 · python/cpython

Expand Up @@ -15,10 +15,6 @@ PyOS_snprintf and PyOS_vsnprintf never write more than size bytes (including the trailing '\0') into str.
If the platform doesn't have vsnprintf, and the buffer size needed to avoid truncation exceeds size by more than 512, Python aborts with a Py_FatalError.
Return value (rv):
When 0 <= rv < size, the output conversion was unexceptional, and Expand All @@ -37,6 +33,7 @@ PyMem_Malloc couldn't obtain space for a temp buffer.
CAUTION: Unlike C99, str != NULL and size > 0 are required. Also, size must be smaller than INT_MAX. */
int Expand All @@ -56,56 +53,27 @@ PyOS_vsnprintf(char *str, size_t size, const char *format, va_list va) { assert(str != NULL); assert(size > 0); assert(size <= (INT_MAX - 1)); assert(format != NULL);
int len; /* # bytes written, excluding \0 */ #if defined(_MSC_VER) || defined(HAVE_SNPRINTF) # define _PyOS_vsnprintf_EXTRA_SPACE 1 #else # define _PyOS_vsnprintf_EXTRA_SPACE 512 char *buffer; #endif /* We take a size_t as input but return an int. Sanity check * our input so that it won't cause an overflow in the * vsnprintf return value or the buffer malloc size. */ if (size > INT_MAX - _PyOS_vsnprintf_EXTRA_SPACE) { * vsnprintf return value. */ if (size > INT_MAX - 1) { len = -666; goto Done; }
#if defined(_MSC_VER) len = _vsnprintf(str, size, format, va); #elif defined(HAVE_SNPRINTF) len = vsnprintf(str, size, format, va); #else /* Emulate vsnprintf(). */ buffer = PyMem_MALLOC(size + _PyOS_vsnprintf_EXTRA_SPACE); if (buffer == NULL) { len = -666; goto Done; }
len = vsprintf(buffer, format, va); if (len < 0) { /* ignore the error */; } else if ((size_t)len >= size + _PyOS_vsnprintf_EXTRA_SPACE) { _Py_FatalErrorFunc(__func__, "Buffer overflow"); } else { const size_t to_copy = (size_t)len < size ? (size_t)len : size - 1; assert(to_copy < size); memcpy(str, buffer, to_copy); str[to_copy] = '\0'; } PyMem_FREE(buffer); len = vsnprintf(str, size, format, va); #endif
Done: if (size > 0) { str[size-1] = '\0'; } return len; #undef _PyOS_vsnprintf_EXTRA_SPACE }