Commit 9aa040d4 authored by Gregory P. Smith's avatar Gregory P. Smith

- Issue #2588, #2589: Fix potential integer underflow and overflow

  conditions in the PyOS_vsnprintf C API function.

This is a backport of r63728 and r63734 from trunk.
parent 26660401
...@@ -41,6 +41,9 @@ Core and builtins ...@@ -41,6 +41,9 @@ Core and builtins
less than zero will now raise a SystemError and return NULL to indicate a less than zero will now raise a SystemError and return NULL to indicate a
bug in the calling C code. bug in the calling C code.
- Issue #2588, #2589: Fix potential integer underflow and overflow
conditions in the PyOS_vsnprintf C API function.
Library Library
------- -------
......
...@@ -54,18 +54,28 @@ int ...@@ -54,18 +54,28 @@ int
PyOS_vsnprintf(char *str, size_t size, const char *format, va_list va) PyOS_vsnprintf(char *str, size_t size, const char *format, va_list va)
{ {
int len; /* # bytes written, excluding \0 */ int len; /* # bytes written, excluding \0 */
#ifndef HAVE_SNPRINTF #ifdef HAVE_SNPRINTF
#define _PyOS_vsnprintf_EXTRA_SPACE 1
#else
#define _PyOS_vsnprintf_EXTRA_SPACE 512
char *buffer; char *buffer;
#endif #endif
assert(str != NULL); assert(str != NULL);
assert(size > 0); assert(size > 0);
assert(format != NULL); assert(format != NULL);
/* 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) {
len = -666;
goto Done;
}
#ifdef HAVE_SNPRINTF #ifdef HAVE_SNPRINTF
len = vsnprintf(str, size, format, va); len = vsnprintf(str, size, format, va);
#else #else
/* Emulate it. */ /* Emulate it. */
buffer = PyMem_MALLOC(size + 512); buffer = PyMem_MALLOC(size + _PyOS_vsnprintf_EXTRA_SPACE);
if (buffer == NULL) { if (buffer == NULL) {
len = -666; len = -666;
goto Done; goto Done;
...@@ -75,7 +85,7 @@ PyOS_vsnprintf(char *str, size_t size, const char *format, va_list va) ...@@ -75,7 +85,7 @@ PyOS_vsnprintf(char *str, size_t size, const char *format, va_list va)
if (len < 0) if (len < 0)
/* ignore the error */; /* ignore the error */;
else if ((size_t)len >= size + 512) else if ((size_t)len >= size + _PyOS_vsnprintf_EXTRA_SPACE)
Py_FatalError("Buffer overflow in PyOS_snprintf/PyOS_vsnprintf"); Py_FatalError("Buffer overflow in PyOS_snprintf/PyOS_vsnprintf");
else { else {
...@@ -86,8 +96,10 @@ PyOS_vsnprintf(char *str, size_t size, const char *format, va_list va) ...@@ -86,8 +96,10 @@ PyOS_vsnprintf(char *str, size_t size, const char *format, va_list va)
str[to_copy] = '\0'; str[to_copy] = '\0';
} }
PyMem_FREE(buffer); PyMem_FREE(buffer);
Done:
#endif #endif
Done:
if (size > 0)
str[size-1] = '\0'; str[size-1] = '\0';
return len; return len;
#undef _PyOS_vsnprintf_EXTRA_SPACE
} }
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment