LCOV - code coverage report
Current view: | top level - Python - mysnprintf.c (source / functions) |  |  | Hit | Total | Coverage
Test: | CPython 3.12 LCOV report [commit 5e6661bce9] |  | Lines: | 12 | 14 | 85.7 %
Date: | 2023-03-20 08:15:36 |  | Functions: | 2 | 2 | 100.0 %
|  |  | Branches: | 2 | 4 | 50.0 %

               Branch data     Line data    Source code
           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                 :            :    Unlike C99, our wrappers do not support passing a null buffer.
          13                 :            :
          14                 :            :    The wrappers ensure that str[size-1] is always \0 upon return.
          15                 :            :
          16                 :            :    PyOS_snprintf and PyOS_vsnprintf never write more than size bytes
          17                 :            :    (including the trailing '\0') into str.
          18                 :            :
          19                 :            :    Return value (rv):
          20                 :            :
          21                 :            :     When 0 <= rv < size, the output conversion was unexceptional, and
          22                 :            :     rv characters were written to str (excluding a trailing \0 byte at
          23                 :            :     str[rv]).
          24                 :            :
          25                 :            :     When rv >= size, output conversion was truncated, and a buffer of
          26                 :            :     size rv+1 would have been needed to avoid truncation.  str[size-1]
          27                 :            :     is \0 in this case.
          28                 :            :
          29                 :            :     When rv < 0, "something bad happened".  str[size-1] is \0 in this
          30                 :            :     case too, but the rest of str is unreliable.  It could be that
          31                 :            :     an error in format codes was detected by libc, or on platforms
          32                 :            :     with a non-C99 vsnprintf simply that the buffer wasn't big enough
          33                 :            :     to avoid truncation, or on platforms without any vsnprintf that
          34                 :            :     PyMem_Malloc couldn't obtain space for a temp buffer.
          35                 :            :
          36                 :            :    CAUTION:  Unlike C99, str != NULL and size > 0 are required.
          37                 :            :    Also, size must be smaller than INT_MAX.
          38                 :            : */
          39                 :            :
          40                 :            : int
          41                 :        179 : PyOS_snprintf(char *str, size_t size, const  char  *format, ...)
          42                 :            : {
          43                 :            :     int rc;
          44                 :            :     va_list va;
          45                 :            :
          46                 :        179 :     va_start(va, format);
          47                 :        179 :     rc = PyOS_vsnprintf(str, size, format, va);
          48                 :        179 :     va_end(va);
          49                 :        179 :     return rc;
          50                 :            : }
          51                 :            :
          52                 :            : int
          53                 :        179 : PyOS_vsnprintf(char *str, size_t size, const char  *format, va_list va)
          54                 :            : {
          55                 :            :     assert(str != NULL);
          56                 :            :     assert(size > 0);
          57                 :            :     assert(size <= (INT_MAX - 1));
          58                 :            :     assert(format != NULL);
          59                 :            :
          60                 :            :     int len;  /* # bytes written, excluding \0 */
          61                 :            :     /* We take a size_t as input but return an int.  Sanity check
          62                 :            :      * our input so that it won't cause an overflow in the
          63                 :            :      * vsnprintf return value.  */
          64         [ -  + ]:        179 :     if (size > INT_MAX - 1) {
          65                 :          0 :         len = -666;
          66                 :          0 :         goto Done;
          67                 :            :     }
          68                 :            :
          69                 :            : #if defined(_MSC_VER)
          70                 :            :     len = _vsnprintf(str, size, format, va);
          71                 :            : #else
          72                 :        179 :     len = vsnprintf(str, size, format, va);
          73                 :            : #endif
          74                 :            :
          75                 :        179 : Done:
          76         [ +  - ]:        179 :     if (size > 0) {
          77                 :        179 :         str[size-1] = '\0';
          78                 :            :     }
          79                 :        179 :     return len;
          80                 :            : }

Generated by: LCOV version 1.14