22
When 0 <= rv < size, the output conversion was unexceptional, and
23
rv characters were written to str (excluding a trailing \0 byte at
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]
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
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
34
to avoid truncation, or on platforms without any vsnprintf that
35
PyMem_Malloc couldn't obtain space for a temp buffer.
22
When 0 <= rv < size, the output conversion was unexceptional, and
23
rv characters were written to str (excluding a trailing \0 byte at
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]
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
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
34
to avoid truncation, or on platforms without any vsnprintf that
35
PyMem_Malloc couldn't obtain space for a temp buffer.
37
37
CAUTION: Unlike C99, str != NULL and size > 0 are required.
41
41
PyOS_snprintf(char *str, size_t size, const char *format, ...)
47
rc = PyOS_vsnprintf(str, size, format, va);
47
rc = PyOS_vsnprintf(str, size, format, va);
53
53
PyOS_vsnprintf(char *str, size_t size, const char *format, va_list va)
55
int len; /* # bytes written, excluding \0 */
55
int len; /* # bytes written, excluding \0 */
56
56
#ifdef HAVE_SNPRINTF
57
57
#define _PyOS_vsnprintf_EXTRA_SPACE 1
59
59
#define _PyOS_vsnprintf_EXTRA_SPACE 512
64
assert(format != NULL);
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
67
* vsnprintf return value or the buffer malloc size. */
68
if (size > INT_MAX - _PyOS_vsnprintf_EXTRA_SPACE) {
64
assert(format != NULL);
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
67
* vsnprintf return value or the buffer malloc size. */
68
if (size > INT_MAX - _PyOS_vsnprintf_EXTRA_SPACE) {
73
73
#ifdef HAVE_SNPRINTF
74
len = vsnprintf(str, size, format, va);
74
len = vsnprintf(str, size, format, va);
77
buffer = PyMem_MALLOC(size + _PyOS_vsnprintf_EXTRA_SPACE);
83
len = vsprintf(buffer, format, va);
85
/* ignore the error */;
87
else if ((size_t)len >= size + _PyOS_vsnprintf_EXTRA_SPACE)
88
Py_FatalError("Buffer overflow in PyOS_snprintf/PyOS_vsnprintf");
91
const size_t to_copy = (size_t)len < size ?
92
(size_t)len : size - 1;
93
assert(to_copy < size);
94
memcpy(str, buffer, to_copy);
77
buffer = PyMem_MALLOC(size + _PyOS_vsnprintf_EXTRA_SPACE);
83
len = vsprintf(buffer, format, va);
85
/* ignore the error */;
87
else if ((size_t)len >= size + _PyOS_vsnprintf_EXTRA_SPACE)
88
Py_FatalError("Buffer overflow in PyOS_snprintf/PyOS_vsnprintf");
91
const size_t to_copy = (size_t)len < size ?
92
(size_t)len : size - 1;
93
assert(to_copy < size);
94
memcpy(str, buffer, to_copy);
103
103
#undef _PyOS_vsnprintf_EXTRA_SPACE