+++ /dev/null
-#include "Python.h"\r
-#include <ctype.h>\r
-\r
-/* snprintf() wrappers. If the platform has vsnprintf, we use it, else we\r
- emulate it in a half-hearted way. Even if the platform has it, we wrap\r
- it because platforms differ in what vsnprintf does in case the buffer\r
- is too small: C99 behavior is to return the number of characters that\r
- would have been written had the buffer not been too small, and to set\r
- the last byte of the buffer to \0. At least MS _vsnprintf returns a\r
- negative value instead, and fills the entire buffer with non-\0 data.\r
-\r
- The wrappers ensure that str[size-1] is always \0 upon return.\r
-\r
- PyOS_snprintf and PyOS_vsnprintf never write more than size bytes\r
- (including the trailing '\0') into str.\r
-\r
- If the platform doesn't have vsnprintf, and the buffer size needed to\r
- avoid truncation exceeds size by more than 512, Python aborts with a\r
- Py_FatalError.\r
-\r
- Return value (rv):\r
-\r
- When 0 <= rv < size, the output conversion was unexceptional, and\r
- rv characters were written to str (excluding a trailing \0 byte at\r
- str[rv]).\r
-\r
- When rv >= size, output conversion was truncated, and a buffer of\r
- size rv+1 would have been needed to avoid truncation. str[size-1]\r
- is \0 in this case.\r
-\r
- When rv < 0, "something bad happened". str[size-1] is \0 in this\r
- case too, but the rest of str is unreliable. It could be that\r
- an error in format codes was detected by libc, or on platforms\r
- with a non-C99 vsnprintf simply that the buffer wasn't big enough\r
- to avoid truncation, or on platforms without any vsnprintf that\r
- PyMem_Malloc couldn't obtain space for a temp buffer.\r
-\r
- CAUTION: Unlike C99, str != NULL and size > 0 are required.\r
-*/\r
-\r
-int\r
-PyOS_snprintf(char *str, size_t size, const char *format, ...)\r
-{\r
- int rc;\r
- va_list va;\r
-\r
- va_start(va, format);\r
- rc = PyOS_vsnprintf(str, size, format, va);\r
- va_end(va);\r
- return rc;\r
-}\r
-\r
-int\r
-PyOS_vsnprintf(char *str, size_t size, const char *format, va_list va)\r
-{\r
- int len; /* # bytes written, excluding \0 */\r
-#ifdef HAVE_SNPRINTF\r
-#define _PyOS_vsnprintf_EXTRA_SPACE 1\r
-#else\r
-#define _PyOS_vsnprintf_EXTRA_SPACE 512\r
- char *buffer;\r
-#endif\r
- assert(str != NULL);\r
- assert(size > 0);\r
- assert(format != NULL);\r
- /* We take a size_t as input but return an int. Sanity check\r
- * our input so that it won't cause an overflow in the\r
- * vsnprintf return value or the buffer malloc size. */\r
- if (size > INT_MAX - _PyOS_vsnprintf_EXTRA_SPACE) {\r
- len = -666;\r
- goto Done;\r
- }\r
-\r
-#ifdef HAVE_SNPRINTF\r
- len = vsnprintf(str, size, format, va);\r
-#else\r
- /* Emulate it. */\r
- buffer = PyMem_MALLOC(size + _PyOS_vsnprintf_EXTRA_SPACE);\r
- if (buffer == NULL) {\r
- len = -666;\r
- goto Done;\r
- }\r
-\r
- len = vsprintf(buffer, format, va);\r
- if (len < 0)\r
- /* ignore the error */;\r
-\r
- else if ((size_t)len >= size + _PyOS_vsnprintf_EXTRA_SPACE)\r
- Py_FatalError("Buffer overflow in PyOS_snprintf/PyOS_vsnprintf");\r
-\r
- else {\r
- const size_t to_copy = (size_t)len < size ?\r
- (size_t)len : size - 1;\r
- assert(to_copy < size);\r
- memcpy(str, buffer, to_copy);\r
- str[to_copy] = '\0';\r
- }\r
- PyMem_FREE(buffer);\r
-#endif\r
-Done:\r
- if (size > 0)\r
- str[size-1] = '\0';\r
- return len;\r
-#undef _PyOS_vsnprintf_EXTRA_SPACE\r
-}\r