Skip to content

Commit 80f20f5

Browse files
authored
gh-125434: Fix non-ASCII thread names in faulthandler on Windows (#140700)
Add _Py_DumpWideString() function to dump a wide string as ASCII. It supports surrogate pairs. Replace _Py_EncodeLocaleRaw() with _Py_DumpWideString() in write_thread_name().
1 parent 2cefa70 commit 80f20f5

File tree

1 file changed

+53
-12
lines changed

1 file changed

+53
-12
lines changed

Python/traceback.c

Lines changed: 53 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -980,6 +980,52 @@ _Py_DumpASCII(int fd, PyObject *text)
980980
}
981981
}
982982

983+
984+
#ifdef MS_WINDOWS
985+
static void
986+
_Py_DumpWideString(int fd, wchar_t *str)
987+
{
988+
Py_ssize_t size = wcslen(str);
989+
int truncated;
990+
if (MAX_STRING_LENGTH < size) {
991+
size = MAX_STRING_LENGTH;
992+
truncated = 1;
993+
}
994+
else {
995+
truncated = 0;
996+
}
997+
998+
for (Py_ssize_t i=0; i < size; i++) {
999+
Py_UCS4 ch = str[i];
1000+
if (' ' <= ch && ch <= 126) {
1001+
/* printable ASCII character */
1002+
dump_char(fd, (char)ch);
1003+
}
1004+
else if (ch <= 0xff) {
1005+
PUTS(fd, "\\x");
1006+
_Py_DumpHexadecimal(fd, ch, 2);
1007+
}
1008+
else if (Py_UNICODE_IS_HIGH_SURROGATE(ch)
1009+
&& Py_UNICODE_IS_LOW_SURROGATE(str[i+1])) {
1010+
ch = Py_UNICODE_JOIN_SURROGATES(ch, str[i+1]);
1011+
i++; // Skip the low surrogate character
1012+
PUTS(fd, "\\U");
1013+
_Py_DumpHexadecimal(fd, ch, 8);
1014+
}
1015+
else {
1016+
Py_BUILD_ASSERT(sizeof(wchar_t) == 2);
1017+
PUTS(fd, "\\u");
1018+
_Py_DumpHexadecimal(fd, ch, 4);
1019+
}
1020+
}
1021+
1022+
if (truncated) {
1023+
PUTS(fd, "...");
1024+
}
1025+
}
1026+
#endif
1027+
1028+
9831029
/* Write a frame into the file fd: "File "xxx", line xxx in xxx".
9841030
9851031
This function is signal safe. */
@@ -1149,20 +1195,15 @@ write_thread_name(int fd, PyThreadState *tstate)
11491195
return;
11501196
}
11511197

1152-
wchar_t *wname;
1153-
HRESULT hr = pGetThreadDescription(thread, &wname);
1198+
wchar_t *name;
1199+
HRESULT hr = pGetThreadDescription(thread, &name);
11541200
if (!FAILED(hr)) {
1155-
char *name = _Py_EncodeLocaleRaw(wname, NULL);
1156-
if (name != NULL) {
1157-
size_t len = strlen(name);
1158-
if (len) {
1159-
PUTS(fd, " [");
1160-
(void)_Py_write_noraise(fd, name, len);
1161-
PUTS(fd, "]");
1162-
}
1163-
PyMem_RawFree(name);
1201+
if (name[0] != 0) {
1202+
PUTS(fd, " [");
1203+
_Py_DumpWideString(fd, name);
1204+
PUTS(fd, "]");
11641205
}
1165-
LocalFree(wname);
1206+
LocalFree(name);
11661207
}
11671208
CloseHandle(thread);
11681209
#endif

0 commit comments

Comments
 (0)