Issue #9979: Use PyUnicode_AsWideCharString() in time.strftime()

Allocate memory with PyMem_Alloc() instead of the PyBytes API. Prepare the
surrogates support.
This commit is contained in:
Victor Stinner 2010-09-29 10:34:19 +00:00
parent 449057f2fa
commit b29047876d
1 changed files with 20 additions and 21 deletions

View File

@ -394,10 +394,15 @@ time_strftime(PyObject *self, PyObject *args)
PyObject *tup = NULL; PyObject *tup = NULL;
struct tm buf; struct tm buf;
const time_char *fmt; const time_char *fmt;
PyObject *format, *tmpfmt; #ifdef HAVE_WCSFTIME
wchar_t *format;
#else
PyObject *format;
#endif
size_t fmtlen, buflen; size_t fmtlen, buflen;
time_char *outbuf = 0; time_char *outbuf = NULL;
size_t i; size_t i;
PyObject *ret = NULL;
memset((void *) &buf, '\0', sizeof(buf)); memset((void *) &buf, '\0', sizeof(buf));
@ -482,19 +487,10 @@ time_strftime(PyObject *self, PyObject *args)
buf.tm_isdst = 1; buf.tm_isdst = 1;
#ifdef HAVE_WCSFTIME #ifdef HAVE_WCSFTIME
tmpfmt = PyBytes_FromStringAndSize(NULL, format = PyUnicode_AsWideCharString((PyUnicodeObject*)format, NULL);
sizeof(wchar_t) * (PyUnicode_GetSize(format)+1)); if (format == NULL)
if (!tmpfmt)
return NULL; return NULL;
/* This assumes that PyUnicode_AsWideChar doesn't do any UTF-16 fmt = format;
expansion. */
if (PyUnicode_AsWideChar((PyUnicodeObject*)format,
(wchar_t*)PyBytes_AS_STRING(tmpfmt),
PyUnicode_GetSize(format)+1) == (size_t)-1)
/* This shouldn't fail. */
Py_FatalError("PyUnicode_AsWideChar failed");
format = tmpfmt;
fmt = (wchar_t*)PyBytes_AS_STRING(format);
#else #else
/* Convert the unicode string to an ascii one */ /* Convert the unicode string to an ascii one */
format = PyUnicode_AsEncodedString(format, TZNAME_ENCODING, NULL); format = PyUnicode_AsEncodedString(format, TZNAME_ENCODING, NULL);
@ -528,8 +524,8 @@ time_strftime(PyObject *self, PyObject *args)
for (i = 1024; ; i += i) { for (i = 1024; ; i += i) {
outbuf = (time_char *)PyMem_Malloc(i*sizeof(time_char)); outbuf = (time_char *)PyMem_Malloc(i*sizeof(time_char));
if (outbuf == NULL) { if (outbuf == NULL) {
Py_DECREF(format); PyErr_NoMemory();
return PyErr_NoMemory(); break;
} }
buflen = format_time(outbuf, i, fmt, &buf); buflen = format_time(outbuf, i, fmt, &buf);
if (buflen > 0 || i >= 256 * fmtlen) { if (buflen > 0 || i >= 256 * fmtlen) {
@ -538,7 +534,6 @@ time_strftime(PyObject *self, PyObject *args)
More likely, the format yields an empty result, More likely, the format yields an empty result,
e.g. an empty format, or %Z when the timezone e.g. an empty format, or %Z when the timezone
is unknown. */ is unknown. */
PyObject *ret;
#ifdef HAVE_WCSFTIME #ifdef HAVE_WCSFTIME
ret = PyUnicode_FromWideChar(outbuf, buflen); ret = PyUnicode_FromWideChar(outbuf, buflen);
#else #else
@ -546,19 +541,23 @@ time_strftime(PyObject *self, PyObject *args)
TZNAME_ENCODING, NULL); TZNAME_ENCODING, NULL);
#endif #endif
PyMem_Free(outbuf); PyMem_Free(outbuf);
Py_DECREF(format); break;
return ret;
} }
PyMem_Free(outbuf); PyMem_Free(outbuf);
#if defined _MSC_VER && _MSC_VER >= 1400 && defined(__STDC_SECURE_LIB__) #if defined _MSC_VER && _MSC_VER >= 1400 && defined(__STDC_SECURE_LIB__)
/* VisualStudio .NET 2005 does this properly */ /* VisualStudio .NET 2005 does this properly */
if (buflen == 0 && errno == EINVAL) { if (buflen == 0 && errno == EINVAL) {
PyErr_SetString(PyExc_ValueError, "Invalid format string"); PyErr_SetString(PyExc_ValueError, "Invalid format string");
Py_DECREF(format); break;
return 0;
} }
#endif #endif
} }
#ifdef HAVE_WCSFTIME
PyMem_Free(format);
#else
Py_DECREF(format);
#endif
return ret;
} }
#undef time_char #undef time_char