LCOV - code coverage report
Current view: top level - libreoffice/workdir/unxlngi6.pro/UnpackedTarball/python3/Python - mysnprintf.c (source / functions) Hit Total Coverage
Test: libreoffice_filtered.info Lines: 11 13 84.6 %
Date: 2012-12-17 Functions: 2 2 100.0 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.10