blob: cd69198011e3c9baba693200c6ddecd46cc8a395 [file] [log] [blame]
Marc-André Lemburge5006eb2001-07-31 13:24:44 +00001#include "Python.h"
Marc-André Lemburge5006eb2001-07-31 13:24:44 +00002
Victor Stinnere822e372020-06-15 21:59:47 +02003/* snprintf() and vsnprintf() wrappers.
4
5 If the platform has vsnprintf, we use it, else we
Tim Petersfaad5ad2001-12-03 00:43:33 +00006 emulate it in a half-hearted way. Even if the platform has it, we wrap
7 it because platforms differ in what vsnprintf does in case the buffer
8 is too small: C99 behavior is to return the number of characters that
9 would have been written had the buffer not been too small, and to set
10 the last byte of the buffer to \0. At least MS _vsnprintf returns a
11 negative value instead, and fills the entire buffer with non-\0 data.
12
13 The wrappers ensure that str[size-1] is always \0 upon return.
14
15 PyOS_snprintf and PyOS_vsnprintf never write more than size bytes
16 (including the trailing '\0') into str.
17
Tim Petersfaad5ad2001-12-03 00:43:33 +000018 Return value (rv):
19
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000020 When 0 <= rv < size, the output conversion was unexceptional, and
21 rv characters were written to str (excluding a trailing \0 byte at
22 str[rv]).
Tim Petersfaad5ad2001-12-03 00:43:33 +000023
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000024 When rv >= size, output conversion was truncated, and a buffer of
25 size rv+1 would have been needed to avoid truncation. str[size-1]
26 is \0 in this case.
Tim Petersfaad5ad2001-12-03 00:43:33 +000027
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000028 When rv < 0, "something bad happened". str[size-1] is \0 in this
29 case too, but the rest of str is unreliable. It could be that
30 an error in format codes was detected by libc, or on platforms
31 with a non-C99 vsnprintf simply that the buffer wasn't big enough
32 to avoid truncation, or on platforms without any vsnprintf that
33 PyMem_Malloc couldn't obtain space for a temp buffer.
Tim Petersfaad5ad2001-12-03 00:43:33 +000034
35 CAUTION: Unlike C99, str != NULL and size > 0 are required.
Victor Stinner7ab92d52020-06-16 00:54:44 +020036 Also, size must be smaller than INT_MAX.
Tim Petersfaad5ad2001-12-03 00:43:33 +000037*/
38
39int
40PyOS_snprintf(char *str, size_t size, const char *format, ...)
41{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000042 int rc;
43 va_list va;
Tim Petersfaad5ad2001-12-03 00:43:33 +000044
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000045 va_start(va, format);
46 rc = PyOS_vsnprintf(str, size, format, va);
47 va_end(va);
48 return rc;
Tim Petersfaad5ad2001-12-03 00:43:33 +000049}
50
51int
52PyOS_vsnprintf(char *str, size_t size, const char *format, va_list va)
53{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000054 assert(str != NULL);
55 assert(size > 0);
Victor Stinner7ab92d52020-06-16 00:54:44 +020056 assert(size <= (INT_MAX - 1));
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000057 assert(format != NULL);
Victor Stinnere822e372020-06-15 21:59:47 +020058
59 int len; /* # bytes written, excluding \0 */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000060 /* We take a size_t as input but return an int. Sanity check
61 * our input so that it won't cause an overflow in the
Victor Stinner7ab92d52020-06-16 00:54:44 +020062 * vsnprintf return value. */
63 if (size > INT_MAX - 1) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000064 len = -666;
65 goto Done;
66 }
Marc-André Lemburge5006eb2001-07-31 13:24:44 +000067
Victor Stinnere822e372020-06-15 21:59:47 +020068#if defined(_MSC_VER)
69 len = _vsnprintf(str, size, format, va);
Marc-André Lemburge5006eb2001-07-31 13:24:44 +000070#else
Victor Stinner7ab92d52020-06-16 00:54:44 +020071 len = vsnprintf(str, size, format, va);
Marc-André Lemburge5006eb2001-07-31 13:24:44 +000072#endif
Victor Stinnere822e372020-06-15 21:59:47 +020073
Georg Brandlf78e02b2008-06-10 17:40:04 +000074Done:
Victor Stinnere822e372020-06-15 21:59:47 +020075 if (size > 0) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000076 str[size-1] = '\0';
Victor Stinnere822e372020-06-15 21:59:47 +020077 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000078 return len;
Marc-André Lemburge5006eb2001-07-31 13:24:44 +000079}