LCOV - code coverage report
Current view: top level - Python - mysnprintf.c (source / functions) Hit Total Coverage
Test: CPython 3.12 LCOV report [commit acb105a7c1f] Lines: 12 14 85.7 %
Date: 2022-07-20 13:12:14 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                 :            : 
      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                 :    1373702 : PyOS_snprintf(char *str, size_t size, const  char  *format, ...)
      41                 :            : {
      42                 :            :     int rc;
      43                 :            :     va_list va;
      44                 :            : 
      45                 :    1373702 :     va_start(va, format);
      46                 :    1373702 :     rc = PyOS_vsnprintf(str, size, format, va);
      47                 :    1373702 :     va_end(va);
      48                 :    1373702 :     return rc;
      49                 :            : }
      50                 :            : 
      51                 :            : int
      52                 :    1378060 : 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         [ -  + ]:    1378060 :     if (size > INT_MAX - 1) {
      64                 :          0 :         len = -666;
      65                 :          0 :         goto Done;
      66                 :            :     }
      67                 :            : 
      68                 :            : #if defined(_MSC_VER)
      69                 :            :     len = _vsnprintf(str, size, format, va);
      70                 :            : #else
      71                 :    1378060 :     len = vsnprintf(str, size, format, va);
      72                 :            : #endif
      73                 :            : 
      74                 :    1378060 : Done:
      75         [ +  - ]:    1378060 :     if (size > 0) {
      76                 :    1378060 :         str[size-1] = '\0';
      77                 :            :     }
      78                 :    1378060 :     return len;
      79                 :            : }

Generated by: LCOV version 1.14