]> granicus.if.org Git - python/commitdiff
- Issue #2588, #2589: Fix potential integer underflow and overflow
authorGregory P. Smith <greg@mad-scientist.com>
Mon, 2 Jun 2008 00:07:25 +0000 (00:07 +0000)
committerGregory P. Smith <greg@mad-scientist.com>
Mon, 2 Jun 2008 00:07:25 +0000 (00:07 +0000)
  conditions in the PyOS_vsnprintf C API function.

This is a backport of r63728 and r63734 from trunk.

Misc/NEWS
Python/mysnprintf.c

index 4eb8a8070483f26da6c54d13b2e903053d563e72..6363f80630d6ffc2bfb01019331b3b22b3812348 100644 (file)
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -41,6 +41,9 @@ Core and builtins
   less than zero will now raise a SystemError and return NULL to indicate a
   bug in the calling C code.
 
+- Issue #2588, #2589: Fix potential integer underflow and overflow
+  conditions in the PyOS_vsnprintf C API function.
+
 
 Library
 -------
index 4d3770d894359b14a78680051cf58c78bdfe8972..3173863c466f6aa16b3e1f682ee46de63f152c47 100644 (file)
@@ -54,18 +54,28 @@ int
 PyOS_vsnprintf(char *str, size_t size, const char  *format, va_list va)
 {
        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;
 #endif
        assert(str != NULL);
        assert(size > 0);
        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
        len = vsnprintf(str, size, format, va);
 #else
        /* Emulate it. */
-       buffer = PyMem_MALLOC(size + 512);
+       buffer = PyMem_MALLOC(size + _PyOS_vsnprintf_EXTRA_SPACE);
        if (buffer == NULL) {
                len = -666;
                goto Done;
@@ -75,7 +85,7 @@ PyOS_vsnprintf(char *str, size_t size, const char  *format, va_list va)
        if (len < 0)
                /* 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");
 
        else {
@@ -86,8 +96,10 @@ PyOS_vsnprintf(char *str, size_t size, const char  *format, va_list va)
                str[to_copy] = '\0';
        }
        PyMem_FREE(buffer);
-Done:
 #endif
-       str[size-1] = '\0';
+Done:
+       if (size > 0)
+               str[size-1] = '\0';
        return len;
+#undef _PyOS_vsnprintf_EXTRA_SPACE
 }