]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
bpo-36020: Remove snprintf macro in pyerrors.h (GH-20889)
authorVictor Stinner <vstinner@python.org>
Mon, 15 Jun 2020 19:59:47 +0000 (21:59 +0200)
committerGitHub <noreply@github.com>
Mon, 15 Jun 2020 19:59:47 +0000 (21:59 +0200)
On Windows, #include "pyerrors.h" no longer defines "snprintf" and
"vsnprintf" macros.

PyOS_snprintf() and PyOS_vsnprintf() should be used to get portable
behavior.

Replace snprintf() calls with PyOS_snprintf() and replace vsnprintf()
calls with PyOS_vsnprintf().

Include/pyerrors.h
Misc/NEWS.d/next/C API/2020-06-15-16-46-01.bpo-36020.djI6jw.rst [new file with mode: 0644]
Modules/_ctypes/callbacks.c
Modules/socketmodule.c
Parser/tokenizer.c
Python/mysnprintf.c

index 399bb7c3a6fac03567bf9d68b1e17e93d6323bf8..979a26ba68a0335b760756e08ba55bb311353ea6 100644 (file)
@@ -4,6 +4,8 @@
 extern "C" {
 #endif
 
+#include <stdarg.h>               // va_list
+
 /* Error handling definitions */
 
 PyAPI_FUNC(void) PyErr_SetNone(PyObject *);
@@ -307,21 +309,6 @@ PyAPI_FUNC(int) PyUnicodeTranslateError_SetReason(
     const char *reason          /* UTF-8 encoded string */
     );
 
-/* These APIs aren't really part of the error implementation, but
-   often needed to format error messages; the native C lib APIs are
-   not available on all platforms, which is why we provide emulations
-   for those platforms in Python/mysnprintf.c,
-   WARNING:  The return value of snprintf varies across platforms; do
-   not rely on any particular behavior; eventually the C99 defn may
-   be reliable.
-*/
-#if defined(MS_WIN32) && !defined(HAVE_SNPRINTF)
-# define HAVE_SNPRINTF
-# define snprintf _snprintf
-# define vsnprintf _vsnprintf
-#endif
-
-#include <stdarg.h>
 PyAPI_FUNC(int) PyOS_snprintf(char *str, size_t size, const char  *format, ...)
                         Py_GCC_ATTRIBUTE((format(printf, 3, 4)));
 PyAPI_FUNC(int) PyOS_vsnprintf(char *str, size_t size, const char  *format, va_list va)
diff --git a/Misc/NEWS.d/next/C API/2020-06-15-16-46-01.bpo-36020.djI6jw.rst b/Misc/NEWS.d/next/C API/2020-06-15-16-46-01.bpo-36020.djI6jw.rst
new file mode 100644 (file)
index 0000000..1f91dce
--- /dev/null
@@ -0,0 +1,2 @@
+On Windows, ``#include "pyerrors.h"`` no longer defines ``snprintf`` and
+``vsnprintf`` macros.
index 29e8fac8c9496c43750fff077266902e162c2f1f..2abfa67cdc06bf76f795ebb12df4dc0ab1b6b65e 100644 (file)
@@ -84,7 +84,7 @@ PrintError(const char *msg, ...)
     va_list marker;
 
     va_start(marker, msg);
-    vsnprintf(buf, sizeof(buf), msg, marker);
+    PyOS_vsnprintf(buf, sizeof(buf), msg, marker);
     va_end(marker);
     if (f != NULL && f != Py_None)
         PyFile_WriteString(buf, f);
index f60a27ebe408c9ad3f15033667bdc384bd40236b..db0eeaafeec27c143ce9b6182339663533c61882 100644 (file)
@@ -436,13 +436,12 @@ remove_unusable_flags(PyObject *m)
 #endif
 
 #ifdef MS_WIN32
-#undef EAFNOSUPPORT
-#define EAFNOSUPPORT WSAEAFNOSUPPORT
-#define snprintf _snprintf
+#  undef EAFNOSUPPORT
+#  define EAFNOSUPPORT WSAEAFNOSUPPORT
 #endif
 
 #ifndef SOCKETCLOSE
-#define SOCKETCLOSE close
+#  define SOCKETCLOSE close
 #endif
 
 #if (defined(HAVE_BLUETOOTH_H) || defined(HAVE_BLUETOOTH_BLUETOOTH_H)) && !defined(__NetBSD__) && !defined(__DragonFly__)
index d461e4e24e721cd3e3161d84a21bd00096d63515..f3c1d9b20ade112743ec005d9e0c6b0bf0ef8b92 100644 (file)
@@ -1133,7 +1133,7 @@ verify_identifier(struct tok_state *tok)
         Py_DECREF(s);
         // PyUnicode_FromFormatV() does not support %X
         char hex[9];
-        snprintf(hex, sizeof(hex), "%04X", ch);
+        (void)PyOS_snprintf(hex, sizeof(hex), "%04X", ch);
         if (Py_UNICODE_ISPRINTABLE(ch)) {
             syntaxerror(tok, "invalid character '%c' (U+%s)", ch, hex);
         }
index 945a81abb01c20d65fc9ae05d94a8790e964222f..458ca14d5c611e08401640dc2d196935437b9b67 100644 (file)
@@ -1,6 +1,8 @@
 #include "Python.h"
 
-/* snprintf() wrappers.  If the platform has vsnprintf, we use it, else we
+/* snprintf() and vsnprintf() wrappers.
+
+   If the platform has vsnprintf, we use it, else we
    emulate it in a half-hearted way.  Even if the platform has it, we wrap
    it because platforms differ in what vsnprintf does in case the buffer
    is too small:  C99 behavior is to return the number of characters that
@@ -52,16 +54,17 @@ PyOS_snprintf(char *str, size_t size, const  char  *format, ...)
 int
 PyOS_vsnprintf(char *str, size_t size, const char  *format, va_list va)
 {
+    assert(str != NULL);
+    assert(size > 0);
+    assert(format != NULL);
+
     int len;  /* # bytes written, excluding \0 */
-#ifdef HAVE_SNPRINTF
-#define _PyOS_vsnprintf_EXTRA_SPACE 1
+#if defined(_MSC_VER) || defined(HAVE_SNPRINTF)
+#  define _PyOS_vsnprintf_EXTRA_SPACE 1
 #else
-#define _PyOS_vsnprintf_EXTRA_SPACE 512
+#  define _PyOS_vsnprintf_EXTRA_SPACE 512
     char *buffer;
 #endif
-    assert(str != NULL);
-    assert(size > 0);
-    assert(format != NULL);
     /* We take a size_t as input but return an int.  Sanity check
      * our input so that it won't cause an overflow in the
      * vsnprintf return value or the buffer malloc size.  */
@@ -70,10 +73,12 @@ PyOS_vsnprintf(char *str, size_t size, const char  *format, va_list va)
         goto Done;
     }
 
-#ifdef HAVE_SNPRINTF
+#if defined(_MSC_VER)
+    len = _vsnprintf(str, size, format, va);
+#elif defined(HAVE_SNPRINTF)
     len = vsnprintf(str, size, format, va);
 #else
-    /* Emulate it. */
+    /* Emulate vsnprintf(). */
     buffer = PyMem_MALLOC(size + _PyOS_vsnprintf_EXTRA_SPACE);
     if (buffer == NULL) {
         len = -666;
@@ -96,9 +101,11 @@ PyOS_vsnprintf(char *str, size_t size, const char  *format, va_list va)
     }
     PyMem_FREE(buffer);
 #endif
+
 Done:
-    if (size > 0)
+    if (size > 0) {
         str[size-1] = '\0';
+    }
     return len;
 #undef _PyOS_vsnprintf_EXTRA_SPACE
 }