ยปCore Development>Code coverage>Python/mysnprintf.c

Python code coverage for Python/mysnprintf.c

#countcontent
1n/a#include "Python.h"
2n/a
3n/a/* snprintf() wrappers. If the platform has vsnprintf, we use it, else we
4n/a emulate it in a half-hearted way. Even if the platform has it, we wrap
5n/a it because platforms differ in what vsnprintf does in case the buffer
6n/a is too small: C99 behavior is to return the number of characters that
7n/a would have been written had the buffer not been too small, and to set
8n/a the last byte of the buffer to \0. At least MS _vsnprintf returns a
9n/a negative value instead, and fills the entire buffer with non-\0 data.
10n/a
11n/a The wrappers ensure that str[size-1] is always \0 upon return.
12n/a
13n/a PyOS_snprintf and PyOS_vsnprintf never write more than size bytes
14n/a (including the trailing '\0') into str.
15n/a
16n/a If the platform doesn't have vsnprintf, and the buffer size needed to
17n/a avoid truncation exceeds size by more than 512, Python aborts with a
18n/a Py_FatalError.
19n/a
20n/a Return value (rv):
21n/a
22n/a When 0 <= rv < size, the output conversion was unexceptional, and
23n/a rv characters were written to str (excluding a trailing \0 byte at
24n/a str[rv]).
25n/a
26n/a When rv >= size, output conversion was truncated, and a buffer of
27n/a size rv+1 would have been needed to avoid truncation. str[size-1]
28n/a is \0 in this case.
29n/a
30n/a When rv < 0, "something bad happened". str[size-1] is \0 in this
31n/a case too, but the rest of str is unreliable. It could be that
32n/a an error in format codes was detected by libc, or on platforms
33n/a with a non-C99 vsnprintf simply that the buffer wasn't big enough
34n/a to avoid truncation, or on platforms without any vsnprintf that
35n/a PyMem_Malloc couldn't obtain space for a temp buffer.
36n/a
37n/a CAUTION: Unlike C99, str != NULL and size > 0 are required.
38n/a*/
39n/a
40n/aint
41n/aPyOS_snprintf(char *str, size_t size, const char *format, ...)
42n/a{
43n/a int rc;
44n/a va_list va;
45n/a
46n/a va_start(va, format);
47n/a rc = PyOS_vsnprintf(str, size, format, va);
48n/a va_end(va);
49n/a return rc;
50n/a}
51n/a
52n/aint
53n/aPyOS_vsnprintf(char *str, size_t size, const char *format, va_list va)
54n/a{
55n/a int len; /* # bytes written, excluding \0 */
56n/a#ifdef HAVE_SNPRINTF
57n/a#define _PyOS_vsnprintf_EXTRA_SPACE 1
58n/a#else
59n/a#define _PyOS_vsnprintf_EXTRA_SPACE 512
60n/a char *buffer;
61n/a#endif
62n/a assert(str != NULL);
63n/a assert(size > 0);
64n/a assert(format != NULL);
65n/a /* We take a size_t as input but return an int. Sanity check
66n/a * our input so that it won't cause an overflow in the
67n/a * vsnprintf return value or the buffer malloc size. */
68n/a if (size > INT_MAX - _PyOS_vsnprintf_EXTRA_SPACE) {
69n/a len = -666;
70n/a goto Done;
71n/a }
72n/a
73n/a#ifdef HAVE_SNPRINTF
74n/a len = vsnprintf(str, size, format, va);
75n/a#else
76n/a /* Emulate it. */
77n/a buffer = PyMem_MALLOC(size + _PyOS_vsnprintf_EXTRA_SPACE);
78n/a if (buffer == NULL) {
79n/a len = -666;
80n/a goto Done;
81n/a }
82n/a
83n/a len = vsprintf(buffer, format, va);
84n/a if (len < 0)
85n/a /* ignore the error */;
86n/a
87n/a else if ((size_t)len >= size + _PyOS_vsnprintf_EXTRA_SPACE)
88n/a Py_FatalError("Buffer overflow in PyOS_snprintf/PyOS_vsnprintf");
89n/a
90n/a else {
91n/a const size_t to_copy = (size_t)len < size ?
92n/a (size_t)len : size - 1;
93n/a assert(to_copy < size);
94n/a memcpy(str, buffer, to_copy);
95n/a str[to_copy] = '\0';
96n/a }
97n/a PyMem_FREE(buffer);
98n/a#endif
99n/aDone:
100n/a if (size > 0)
101n/a str[size-1] = '\0';
102n/a return len;
103n/a#undef _PyOS_vsnprintf_EXTRA_SPACE
104n/a}