Changeset 391 for python/trunk/Python/mysnprintf.c
- Timestamp:
- Mar 19, 2014, 11:31:01 PM (11 years ago)
- Location:
- python/trunk
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
python/trunk
-
Property svn:mergeinfo
set to
/python/vendor/Python-2.7.6 merged eligible /python/vendor/current merged eligible
-
Property svn:mergeinfo
set to
-
python/trunk/Python/mysnprintf.c
r2 r391 21 21 Return value (rv): 22 22 23 24 25 23 When 0 <= rv < size, the output conversion was unexceptional, and 24 rv characters were written to str (excluding a trailing \0 byte at 25 str[rv]). 26 26 27 28 29 27 When rv >= size, output conversion was truncated, and a buffer of 28 size rv+1 would have been needed to avoid truncation. str[size-1] 29 is \0 in this case. 30 30 31 32 33 34 35 36 31 When rv < 0, "something bad happened". str[size-1] is \0 in this 32 case too, but the rest of str is unreliable. It could be that 33 an error in format codes was detected by libc, or on platforms 34 with a non-C99 vsnprintf simply that the buffer wasn't big enough 35 to avoid truncation, or on platforms without any vsnprintf that 36 PyMem_Malloc couldn't obtain space for a temp buffer. 37 37 38 38 CAUTION: Unlike C99, str != NULL and size > 0 are required. … … 42 42 PyOS_snprintf(char *str, size_t size, const char *format, ...) 43 43 { 44 45 44 int rc; 45 va_list va; 46 46 47 48 49 50 47 va_start(va, format); 48 rc = PyOS_vsnprintf(str, size, format, va); 49 va_end(va); 50 return rc; 51 51 } 52 52 … … 54 54 PyOS_vsnprintf(char *str, size_t size, const char *format, va_list va) 55 55 { 56 56 int len; /* # bytes written, excluding \0 */ 57 57 #ifdef HAVE_SNPRINTF 58 58 #define _PyOS_vsnprintf_EXTRA_SPACE 1 59 59 #else 60 60 #define _PyOS_vsnprintf_EXTRA_SPACE 512 61 61 char *buffer; 62 62 #endif 63 64 65 66 67 68 69 70 71 72 63 assert(str != NULL); 64 assert(size > 0); 65 assert(format != NULL); 66 /* We take a size_t as input but return an int. Sanity check 67 * our input so that it won't cause an overflow in the 68 * vsnprintf return value or the buffer malloc size. */ 69 if (size > INT_MAX - _PyOS_vsnprintf_EXTRA_SPACE) { 70 len = -666; 71 goto Done; 72 } 73 73 74 74 #ifdef HAVE_SNPRINTF 75 75 len = vsnprintf(str, size, format, va); 76 76 #else 77 78 79 80 81 82 77 /* Emulate it. */ 78 buffer = PyMem_MALLOC(size + _PyOS_vsnprintf_EXTRA_SPACE); 79 if (buffer == NULL) { 80 len = -666; 81 goto Done; 82 } 83 83 84 85 86 84 len = vsprintf(buffer, format, va); 85 if (len < 0) 86 /* ignore the error */; 87 87 88 89 88 else if ((size_t)len >= size + _PyOS_vsnprintf_EXTRA_SPACE) 89 Py_FatalError("Buffer overflow in PyOS_snprintf/PyOS_vsnprintf"); 90 90 91 92 93 94 95 96 97 98 91 else { 92 const size_t to_copy = (size_t)len < size ? 93 (size_t)len : size - 1; 94 assert(to_copy < size); 95 memcpy(str, buffer, to_copy); 96 str[to_copy] = '\0'; 97 } 98 PyMem_FREE(buffer); 99 99 #endif 100 100 Done: 101 102 103 101 if (size > 0) 102 str[size-1] = '\0'; 103 return len; 104 104 #undef _PyOS_vsnprintf_EXTRA_SPACE 105 105 }
Note:
See TracChangeset
for help on using the changeset viewer.