Skip to content

Commit 41cde91

Browse files
committed
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(). (cherry picked from commit 80f20f5)
1 parent 6ab3b49 commit 41cde91

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
@@ -981,6 +981,52 @@ _Py_DumpASCII(int fd, PyObject *text)
981981
}
982982
}
983983

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

1167-
wchar_t *wname;
1168-
HRESULT hr = pGetThreadDescription(thread, &wname);
1213+
wchar_t *name;
1214+
HRESULT hr = pGetThreadDescription(thread, &name);
11691215
if (!FAILED(hr)) {
1170-
char *name = _Py_EncodeLocaleRaw(wname, NULL);
1171-
if (name != NULL) {
1172-
size_t len = strlen(name);
1173-
if (len) {
1174-
PUTS(fd, " [");
1175-
(void)_Py_write_noraise(fd, name, len);
1176-
PUTS(fd, "]");
1177-
}
1178-
PyMem_RawFree(name);
1216+
if (name[0] != 0) {
1217+
PUTS(fd, " [");
1218+
_Py_DumpWideString(fd, name);
1219+
PUTS(fd, "]");
11791220
}
1180-
LocalFree(wname);
1221+
LocalFree(name);
11811222
}
11821223
CloseHandle(thread);
11831224
#endif

0 commit comments

Comments
 (0)