Skip to content

Commit 5d12abe

Browse files
committed
Patch #1075: Use wide API to format error messages.
1 parent c76473d commit 5d12abe

1 file changed

Lines changed: 57 additions & 32 deletions

File tree

Python/errors.c

Lines changed: 57 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,8 @@ extern char *strerror(int);
1010
#endif
1111

1212
#ifdef MS_WINDOWS
13-
#include "windows.h"
14-
#include "winbase.h"
13+
#include <windows.h>
14+
#include <winbase.h>
1515
#endif
1616

1717
#include <ctype.h>
@@ -270,41 +270,49 @@ PyErr_NoMemory(void)
270270
PyObject *
271271
PyErr_SetFromErrnoWithFilenameObject(PyObject *exc, PyObject *filenameObject)
272272
{
273+
PyObject *message;
273274
PyObject *v;
274-
char *s;
275275
int i = errno;
276276
#ifdef PLAN9
277277
char errbuf[ERRMAX];
278-
#endif
279-
#ifdef MS_WINDOWS
280-
char *s_buf = NULL;
281-
char s_small_buf[28]; /* Room for "Windows Error 0xFFFFFFFF" */
282-
#endif
278+
#else
279+
#ifndef MS_WINDOWS
280+
char *s;
281+
#else
282+
WCHAR *s_buf = NULL;
283+
#endif /* Unix/Windows */
284+
#endif /* PLAN 9*/
285+
283286
#ifdef EINTR
284287
if (i == EINTR && PyErr_CheckSignals())
285288
return NULL;
286289
#endif
290+
287291
#ifdef PLAN9
288292
rerrstr(errbuf, sizeof errbuf);
289-
s = errbuf;
293+
message = PyUnicode_DecodeUTF8(errbuf, strlen(errbuf), "ignore");
290294
#else
295+
#ifndef MS_WINDOWS
291296
if (i == 0)
292297
s = "Error"; /* Sometimes errno didn't get set */
293298
else
294-
#ifndef MS_WINDOWS
295299
s = strerror(i);
300+
message = PyUnicode_DecodeUTF8(s, strlen(s), "ignore");
296301
#else
302+
if (i == 0)
303+
message = PyUnicode_FromString("Error"); /* Sometimes errno didn't get set */
304+
else
297305
{
298306
/* Note that the Win32 errors do not lineup with the
299307
errno error. So if the error is in the MSVC error
300308
table, we use it, otherwise we assume it really _is_
301309
a Win32 error code
302310
*/
303311
if (i > 0 && i < _sys_nerr) {
304-
s = _sys_errlist[i];
312+
message = PyUnicode_FromString(_sys_errlist[i]);
305313
}
306314
else {
307-
int len = FormatMessage(
315+
int len = FormatMessageW(
308316
FORMAT_MESSAGE_ALLOCATE_BUFFER |
309317
FORMAT_MESSAGE_FROM_SYSTEM |
310318
FORMAT_MESSAGE_IGNORE_INSERTS,
@@ -313,29 +321,39 @@ PyErr_SetFromErrnoWithFilenameObject(PyObject *exc, PyObject *filenameObject)
313321
MAKELANGID(LANG_NEUTRAL,
314322
SUBLANG_DEFAULT),
315323
/* Default language */
316-
(LPTSTR) &s_buf,
324+
(LPWSTR) &s_buf,
317325
0, /* size not used */
318326
NULL); /* no args */
319327
if (len==0) {
320328
/* Only ever seen this in out-of-mem
321329
situations */
322-
sprintf(s_small_buf, "Windows Error 0x%X", i);
323-
s = s_small_buf;
324330
s_buf = NULL;
331+
message = PyUnicode_FromFormat("Windows Error 0x%X", i);
325332
} else {
326-
s = s_buf;
327333
/* remove trailing cr/lf and dots */
328-
while (len > 0 && (s[len-1] <= ' ' || s[len-1] == '.'))
329-
s[--len] = '\0';
334+
while (len > 0 && (s_buf[len-1] <= L' ' || s_buf[len-1] == L'.'))
335+
s_buf[--len] = L'\0';
336+
message = PyUnicode_FromUnicode(s_buf, len);
330337
}
331338
}
332339
}
333340
#endif /* Unix/Windows */
334341
#endif /* PLAN 9*/
342+
343+
if (message == NULL)
344+
{
345+
#ifdef MS_WINDOWS
346+
LocalFree(s_buf);
347+
#endif
348+
return NULL;
349+
}
350+
335351
if (filenameObject != NULL)
336-
v = Py_BuildValue("(iUO)", i, s, filenameObject);
352+
v = Py_BuildValue("(iOO)", i, message, filenameObject);
337353
else
338-
v = Py_BuildValue("(iU)", i, s);
354+
v = Py_BuildValue("(iO)", i, message);
355+
Py_DECREF(message);
356+
339357
if (v != NULL) {
340358
PyErr_SetObject(exc, v);
341359
Py_DECREF(v);
@@ -383,13 +401,12 @@ PyObject *PyErr_SetExcFromWindowsErrWithFilenameObject(
383401
PyObject *filenameObject)
384402
{
385403
int len;
386-
char *s;
387-
char *s_buf = NULL; /* Free via LocalFree */
388-
char s_small_buf[28]; /* Room for "Windows Error 0xFFFFFFFF" */
404+
WCHAR *s_buf = NULL; /* Free via LocalFree */
405+
PyObject *message;
389406
PyObject *v;
390407
DWORD err = (DWORD)ierr;
391408
if (err==0) err = GetLastError();
392-
len = FormatMessage(
409+
len = FormatMessageW(
393410
/* Error API error */
394411
FORMAT_MESSAGE_ALLOCATE_BUFFER |
395412
FORMAT_MESSAGE_FROM_SYSTEM |
@@ -398,24 +415,32 @@ PyObject *PyErr_SetExcFromWindowsErrWithFilenameObject(
398415
err,
399416
MAKELANGID(LANG_NEUTRAL,
400417
SUBLANG_DEFAULT), /* Default language */
401-
(LPTSTR) &s_buf,
418+
(LPWSTR) &s_buf,
402419
0, /* size not used */
403420
NULL); /* no args */
404421
if (len==0) {
405422
/* Only seen this in out of mem situations */
406-
sprintf(s_small_buf, "Windows Error 0x%X", err);
407-
s = s_small_buf;
423+
message = PyUnicode_FromFormat("Windows Error 0x%X", err);
408424
s_buf = NULL;
409425
} else {
410-
s = s_buf;
411426
/* remove trailing cr/lf and dots */
412-
while (len > 0 && (s[len-1] <= ' ' || s[len-1] == '.'))
413-
s[--len] = '\0';
427+
while (len > 0 && (s_buf[len-1] <= L' ' || s_buf[len-1] == L'.'))
428+
s_buf[--len] = L'\0';
429+
message = PyUnicode_FromUnicode(s_buf, len);
414430
}
431+
432+
if (message == NULL)
433+
{
434+
LocalFree(s_buf);
435+
return NULL;
436+
}
437+
415438
if (filenameObject != NULL)
416-
v = Py_BuildValue("(iUO)", err, s, filenameObject);
439+
v = Py_BuildValue("(iOO)", err, message, filenameObject);
417440
else
418-
v = Py_BuildValue("(iU)", err, s);
441+
v = Py_BuildValue("(iO)", err, message);
442+
Py_DECREF(message);
443+
419444
if (v != NULL) {
420445
PyErr_SetObject(exc, v);
421446
Py_DECREF(v);

0 commit comments

Comments
 (0)