(root)/
Python-3.12.0/
Python/
mysnprintf.c
       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  PyOS_snprintf(char *str, size_t size, const  char  *format, ...)
      42  {
      43      int rc;
      44      va_list va;
      45  
      46      va_start(va, format);
      47      rc = PyOS_vsnprintf(str, size, format, va);
      48      va_end(va);
      49      return rc;
      50  }
      51  
      52  int
      53  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      if (size > INT_MAX - 1) {
      65          len = -666;
      66          goto Done;
      67      }
      68  
      69  #if defined(_MSC_VER)
      70      len = _vsnprintf(str, size, format, va);
      71  #else
      72      len = vsnprintf(str, size, format, va);
      73  #endif
      74  
      75  Done:
      76      if (size > 0) {
      77          str[size-1] = '\0';
      78      }
      79      return len;
      80  }