Coverage Report

Created: 2022-07-08 09:39

/home/mdboom/Work/builds/cpython/Python/mysnprintf.c
Line
Count
Source (jump to first uncovered line)
1
#include "Python.h"
2
3
/* snprintf() and vsnprintf() wrappers.
4
5
   If the platform has vsnprintf, we use it, else we
6
   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
18
   Return value (rv):
19
20
    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]).
23
24
    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.
27
28
    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.
34
35
   CAUTION:  Unlike C99, str != NULL and size > 0 are required.
36
   Also, size must be smaller than INT_MAX.
37
*/
38
39
int
40
PyOS_snprintf(char *str, size_t size, const  char  *format, ...)
41
{
42
    int rc;
43
    va_list va;
44
45
    va_start(va, format);
46
    rc = PyOS_vsnprintf(str, size, format, va);
47
    va_end(va);
48
    return rc;
49
}
50
51
int
52
PyOS_vsnprintf(char *str, size_t size, const char  *format, va_list va)
53
{
54
    assert(str != NULL);
55
    assert(size > 0);
56
    assert(size <= (INT_MAX - 1));
57
    assert(format != NULL);
58
59
    int len;  /* # bytes written, excluding \0 */
60
    /* 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
62
     * vsnprintf return value.  */
63
    if (size > INT_MAX - 1) {
  Branch (63:9): [True: 0, False: 1.33M]
64
        len = -666;
65
        goto Done;
66
    }
67
68
#if defined(_MSC_VER)
69
    len = _vsnprintf(str, size, format, va);
70
#else
71
    len = vsnprintf(str, size, format, va);
72
#endif
73
74
Done:
75
    if (size > 0) {
  Branch (75:9): [True: 1.33M, False: 0]
76
        str[size-1] = '\0';
77
    }
78
    return len;
79
}