Mercurial > cpython-lru_cache-weakref
comparison Python/mysnprintf.c @ 61467:f197407bdba2 3.1
Recorded merge of revisions 81032 via svnmerge from
svn+ssh://pythondev@svn.python.org/python/branches/py3k
................
r81032 | antoine.pitrou | 2010-05-09 17:52:27 +0200 (dim., 09 mai 2010) | 9 lines
Recorded merge of revisions 81029 via svnmerge from
svn+ssh://pythondev@svn.python.org/python/trunk
........
r81029 | antoine.pitrou | 2010-05-09 16:46:46 +0200 (dim., 09 mai 2010) | 3 lines
Untabify C files. Will watch buildbots.
........
................
| author | Antoine Pitrou <solipsis@pitrou.net> |
|---|---|
| date | Sun, 09 May 2010 16:14:21 +0000 |
| parents | ae5f5156b882 |
| children |
comparison
equal
deleted
inserted
replaced
| 61459:f8c19c5f5dd2 | 61467:f197407bdba2 |
|---|---|
| 17 avoid truncation exceeds size by more than 512, Python aborts with a | 17 avoid truncation exceeds size by more than 512, Python aborts with a |
| 18 Py_FatalError. | 18 Py_FatalError. |
| 19 | 19 |
| 20 Return value (rv): | 20 Return value (rv): |
| 21 | 21 |
| 22 When 0 <= rv < size, the output conversion was unexceptional, and | 22 When 0 <= rv < size, the output conversion was unexceptional, and |
| 23 rv characters were written to str (excluding a trailing \0 byte at | 23 rv characters were written to str (excluding a trailing \0 byte at |
| 24 str[rv]). | 24 str[rv]). |
| 25 | 25 |
| 26 When rv >= size, output conversion was truncated, and a buffer of | 26 When rv >= size, output conversion was truncated, and a buffer of |
| 27 size rv+1 would have been needed to avoid truncation. str[size-1] | 27 size rv+1 would have been needed to avoid truncation. str[size-1] |
| 28 is \0 in this case. | 28 is \0 in this case. |
| 29 | 29 |
| 30 When rv < 0, "something bad happened". str[size-1] is \0 in this | 30 When rv < 0, "something bad happened". str[size-1] is \0 in this |
| 31 case too, but the rest of str is unreliable. It could be that | 31 case too, but the rest of str is unreliable. It could be that |
| 32 an error in format codes was detected by libc, or on platforms | 32 an error in format codes was detected by libc, or on platforms |
| 33 with a non-C99 vsnprintf simply that the buffer wasn't big enough | 33 with a non-C99 vsnprintf simply that the buffer wasn't big enough |
| 34 to avoid truncation, or on platforms without any vsnprintf that | 34 to avoid truncation, or on platforms without any vsnprintf that |
| 35 PyMem_Malloc couldn't obtain space for a temp buffer. | 35 PyMem_Malloc couldn't obtain space for a temp buffer. |
| 36 | 36 |
| 37 CAUTION: Unlike C99, str != NULL and size > 0 are required. | 37 CAUTION: Unlike C99, str != NULL and size > 0 are required. |
| 38 */ | 38 */ |
| 39 | 39 |
| 40 int | 40 int |
| 41 PyOS_snprintf(char *str, size_t size, const char *format, ...) | 41 PyOS_snprintf(char *str, size_t size, const char *format, ...) |
| 42 { | 42 { |
| 43 int rc; | 43 int rc; |
| 44 va_list va; | 44 va_list va; |
| 45 | 45 |
| 46 va_start(va, format); | 46 va_start(va, format); |
| 47 rc = PyOS_vsnprintf(str, size, format, va); | 47 rc = PyOS_vsnprintf(str, size, format, va); |
| 48 va_end(va); | 48 va_end(va); |
| 49 return rc; | 49 return rc; |
| 50 } | 50 } |
| 51 | 51 |
| 52 int | 52 int |
| 53 PyOS_vsnprintf(char *str, size_t size, const char *format, va_list va) | 53 PyOS_vsnprintf(char *str, size_t size, const char *format, va_list va) |
| 54 { | 54 { |
| 55 int len; /* # bytes written, excluding \0 */ | 55 int len; /* # bytes written, excluding \0 */ |
| 56 #ifdef HAVE_SNPRINTF | 56 #ifdef HAVE_SNPRINTF |
| 57 #define _PyOS_vsnprintf_EXTRA_SPACE 1 | 57 #define _PyOS_vsnprintf_EXTRA_SPACE 1 |
| 58 #else | 58 #else |
| 59 #define _PyOS_vsnprintf_EXTRA_SPACE 512 | 59 #define _PyOS_vsnprintf_EXTRA_SPACE 512 |
| 60 char *buffer; | 60 char *buffer; |
| 61 #endif | 61 #endif |
| 62 assert(str != NULL); | 62 assert(str != NULL); |
| 63 assert(size > 0); | 63 assert(size > 0); |
| 64 assert(format != NULL); | 64 assert(format != NULL); |
| 65 /* We take a size_t as input but return an int. Sanity check | 65 /* We take a size_t as input but return an int. Sanity check |
| 66 * our input so that it won't cause an overflow in the | 66 * our input so that it won't cause an overflow in the |
| 67 * vsnprintf return value or the buffer malloc size. */ | 67 * vsnprintf return value or the buffer malloc size. */ |
| 68 if (size > INT_MAX - _PyOS_vsnprintf_EXTRA_SPACE) { | 68 if (size > INT_MAX - _PyOS_vsnprintf_EXTRA_SPACE) { |
| 69 len = -666; | 69 len = -666; |
| 70 goto Done; | 70 goto Done; |
| 71 } | 71 } |
| 72 | 72 |
| 73 #ifdef HAVE_SNPRINTF | 73 #ifdef HAVE_SNPRINTF |
| 74 len = vsnprintf(str, size, format, va); | 74 len = vsnprintf(str, size, format, va); |
| 75 #else | 75 #else |
| 76 /* Emulate it. */ | 76 /* Emulate it. */ |
| 77 buffer = PyMem_MALLOC(size + _PyOS_vsnprintf_EXTRA_SPACE); | 77 buffer = PyMem_MALLOC(size + _PyOS_vsnprintf_EXTRA_SPACE); |
| 78 if (buffer == NULL) { | 78 if (buffer == NULL) { |
| 79 len = -666; | 79 len = -666; |
| 80 goto Done; | 80 goto Done; |
| 81 } | 81 } |
| 82 | 82 |
| 83 len = vsprintf(buffer, format, va); | 83 len = vsprintf(buffer, format, va); |
| 84 if (len < 0) | 84 if (len < 0) |
| 85 /* ignore the error */; | 85 /* ignore the error */; |
| 86 | 86 |
| 87 else if ((size_t)len >= size + _PyOS_vsnprintf_EXTRA_SPACE) | 87 else if ((size_t)len >= size + _PyOS_vsnprintf_EXTRA_SPACE) |
| 88 Py_FatalError("Buffer overflow in PyOS_snprintf/PyOS_vsnprintf"); | 88 Py_FatalError("Buffer overflow in PyOS_snprintf/PyOS_vsnprintf"); |
| 89 | 89 |
| 90 else { | 90 else { |
| 91 const size_t to_copy = (size_t)len < size ? | 91 const size_t to_copy = (size_t)len < size ? |
| 92 (size_t)len : size - 1; | 92 (size_t)len : size - 1; |
| 93 assert(to_copy < size); | 93 assert(to_copy < size); |
| 94 memcpy(str, buffer, to_copy); | 94 memcpy(str, buffer, to_copy); |
| 95 str[to_copy] = '\0'; | 95 str[to_copy] = '\0'; |
| 96 } | 96 } |
| 97 PyMem_FREE(buffer); | 97 PyMem_FREE(buffer); |
| 98 #endif | 98 #endif |
| 99 Done: | 99 Done: |
| 100 if (size > 0) | 100 if (size > 0) |
| 101 str[size-1] = '\0'; | 101 str[size-1] = '\0'; |
| 102 return len; | 102 return len; |
| 103 #undef _PyOS_vsnprintf_EXTRA_SPACE | 103 #undef _PyOS_vsnprintf_EXTRA_SPACE |
| 104 } | 104 } |
