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" {
#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)

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_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);

View File

@ -438,7 +438,6 @@ remove_unusable_flags(PyObject *m)
#ifdef MS_WIN32
# undef EAFNOSUPPORT
# define EAFNOSUPPORT WSAEAFNOSUPPORT
#define snprintf _snprintf
#endif
#ifndef SOCKETCLOSE

View 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);
}

View 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
#if defined(_MSC_VER) || defined(HAVE_SNPRINTF)
# define _PyOS_vsnprintf_EXTRA_SPACE 1
#else
# 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
}