bpo-36020: Remove snprintf macro in pyerrors.h (GH-20889)

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().
This commit is contained in:
Victor Stinner 2020-06-15 21:59:47 +02:00 committed by GitHub
parent 5f79f46612
commit e822e37946
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 27 additions and 32 deletions

View file

@ -4,6 +4,8 @@
extern "C" { extern "C" {
#endif #endif
#include <stdarg.h> // va_list
/* Error handling definitions */ /* Error handling definitions */
PyAPI_FUNC(void) PyErr_SetNone(PyObject *); PyAPI_FUNC(void) PyErr_SetNone(PyObject *);
@ -307,21 +309,6 @@ PyAPI_FUNC(int) PyUnicodeTranslateError_SetReason(
const char *reason /* UTF-8 encoded string */ 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, ...) PyAPI_FUNC(int) PyOS_snprintf(char *str, size_t size, const char *format, ...)
Py_GCC_ATTRIBUTE((format(printf, 3, 4))); Py_GCC_ATTRIBUTE((format(printf, 3, 4)));
PyAPI_FUNC(int) PyOS_vsnprintf(char *str, size_t size, const char *format, va_list va) PyAPI_FUNC(int) PyOS_vsnprintf(char *str, size_t size, const char *format, va_list va)

View file

@ -0,0 +1,2 @@
On Windows, ``#include "pyerrors.h"`` no longer defines ``snprintf`` and
``vsnprintf`` macros.

View file

@ -84,7 +84,7 @@ PrintError(const char *msg, ...)
va_list marker; va_list marker;
va_start(marker, msg); va_start(marker, msg);
vsnprintf(buf, sizeof(buf), msg, marker); PyOS_vsnprintf(buf, sizeof(buf), msg, marker);
va_end(marker); va_end(marker);
if (f != NULL && f != Py_None) if (f != NULL && f != Py_None)
PyFile_WriteString(buf, f); PyFile_WriteString(buf, f);

View file

@ -436,13 +436,12 @@ remove_unusable_flags(PyObject *m)
#endif #endif
#ifdef MS_WIN32 #ifdef MS_WIN32
#undef EAFNOSUPPORT # undef EAFNOSUPPORT
#define EAFNOSUPPORT WSAEAFNOSUPPORT # define EAFNOSUPPORT WSAEAFNOSUPPORT
#define snprintf _snprintf
#endif #endif
#ifndef SOCKETCLOSE #ifndef SOCKETCLOSE
#define SOCKETCLOSE close # define SOCKETCLOSE close
#endif #endif
#if (defined(HAVE_BLUETOOTH_H) || defined(HAVE_BLUETOOTH_BLUETOOTH_H)) && !defined(__NetBSD__) && !defined(__DragonFly__) #if (defined(HAVE_BLUETOOTH_H) || defined(HAVE_BLUETOOTH_BLUETOOTH_H)) && !defined(__NetBSD__) && !defined(__DragonFly__)

View file

@ -1133,7 +1133,7 @@ verify_identifier(struct tok_state *tok)
Py_DECREF(s); Py_DECREF(s);
// PyUnicode_FromFormatV() does not support %X // PyUnicode_FromFormatV() does not support %X
char hex[9]; char hex[9];
snprintf(hex, sizeof(hex), "%04X", ch); (void)PyOS_snprintf(hex, sizeof(hex), "%04X", ch);
if (Py_UNICODE_ISPRINTABLE(ch)) { if (Py_UNICODE_ISPRINTABLE(ch)) {
syntaxerror(tok, "invalid character '%c' (U+%s)", ch, hex); syntaxerror(tok, "invalid character '%c' (U+%s)", ch, hex);
} }

View file

@ -1,6 +1,8 @@
#include "Python.h" #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 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 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 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 int
PyOS_vsnprintf(char *str, size_t size, const char *format, va_list va) PyOS_vsnprintf(char *str, size_t size, const char *format, va_list va)
{ {
int len; /* # bytes written, excluding \0 */
#ifdef HAVE_SNPRINTF
#define _PyOS_vsnprintf_EXTRA_SPACE 1
#else
#define _PyOS_vsnprintf_EXTRA_SPACE 512
char *buffer;
#endif
assert(str != NULL); assert(str != NULL);
assert(size > 0); assert(size > 0);
assert(format != NULL); assert(format != NULL);
int len; /* # bytes written, excluding \0 */
#if defined(_MSC_VER) || defined(HAVE_SNPRINTF)
# define _PyOS_vsnprintf_EXTRA_SPACE 1
#else
# define _PyOS_vsnprintf_EXTRA_SPACE 512
char *buffer;
#endif
/* We take a size_t as input but return an int. Sanity check /* 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 * our input so that it won't cause an overflow in the
* vsnprintf return value or the buffer malloc size. */ * 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; 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); len = vsnprintf(str, size, format, va);
#else #else
/* Emulate it. */ /* Emulate vsnprintf(). */
buffer = PyMem_MALLOC(size + _PyOS_vsnprintf_EXTRA_SPACE); buffer = PyMem_MALLOC(size + _PyOS_vsnprintf_EXTRA_SPACE);
if (buffer == NULL) { if (buffer == NULL) {
len = -666; len = -666;
@ -96,9 +101,11 @@ PyOS_vsnprintf(char *str, size_t size, const char *format, va_list va)
} }
PyMem_FREE(buffer); PyMem_FREE(buffer);
#endif #endif
Done: Done:
if (size > 0) if (size > 0) {
str[size-1] = '\0'; str[size-1] = '\0';
}
return len; return len;
#undef _PyOS_vsnprintf_EXTRA_SPACE #undef _PyOS_vsnprintf_EXTRA_SPACE
} }