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:
parent
5f79f46612
commit
e822e37946
|
@ -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)
|
||||||
|
|
|
@ -0,0 +1,2 @@
|
||||||
|
On Windows, ``#include "pyerrors.h"`` no longer defines ``snprintf`` and
|
||||||
|
``vsnprintf`` macros.
|
|
@ -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);
|
||||||
|
|
|
@ -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__)
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue