Skip to content

Commit f5c0917

Browse files
gh-126219: Fix crash in tkinter.Tk with non-BMP className on Tcl/Tk 8.x
Tcl 8.x crashes when title-casing a non-BMP character during Tk initialization, so such a className is now rejected with a ValueError. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
1 parent da99711 commit f5c0917

3 files changed

Lines changed: 28 additions & 1 deletion

File tree

Lib/test/test_tkinter/test_misc.py

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,8 @@
1010
from test.support import os_helper
1111
from test.test_tkinter.support import setUpModule # noqa: F401
1212
from test.test_tkinter.support import (AbstractTkTest, AbstractDefaultRootTest,
13-
requires_tk, get_tk_patchlevel)
13+
requires_tk, get_tk_patchlevel,
14+
tcl_version)
1415

1516
support.requires('gui')
1617

@@ -51,6 +52,15 @@ class Button2(tkinter.Button):
5152
b4 = Button2(f2)
5253
self.assertEqual(len({str(b), str(b2), str(b3), str(b4)}), 4)
5354

55+
def test_nonbmp_className(self):
56+
# gh-126219: a non-BMP character in className crashed Tcl/Tk 8.x while
57+
# title-casing the class name during Tk initialization.
58+
if tcl_version >= (9, 0):
59+
# Tcl 9 supports non-BMP characters.
60+
tkinter.Tk(className='\U0010FFFF').destroy()
61+
else:
62+
self.assertRaises(ValueError, tkinter.Tk, className='\U0010FFFF')
63+
5464
@requires_tk(8, 6, 6)
5565
def test_tk_busy(self):
5666
root = self.root
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
Fixed a crash in :class:`tkinter.Tk` when *className* contains a non-BMP
2+
character and tkinter is built against Tcl/Tk 8.x. Such a name is now
3+
rejected with a :exc:`ValueError`.

Modules/_tkinter.c

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3272,6 +3272,20 @@ _tkinter_create_impl(PyObject *module, const char *screenName,
32723272
CHECK_STRING_LENGTH(className);
32733273
CHECK_STRING_LENGTH(use);
32743274

3275+
#if TCL_MAJOR_VERSION < 9
3276+
/* className is title-cased during Tk initialization. Tcl 8.x does not
3277+
* support non-BMP characters (encoded as 4-byte UTF-8 sequences) there
3278+
* and crashes in Tcl_UtfToTitle (see gh-126219). Reject them up front. */
3279+
for (const unsigned char *p = (const unsigned char *)className; *p; p++) {
3280+
if (*p >= 0xF0) {
3281+
PyErr_SetString(PyExc_ValueError,
3282+
"className must not contain non-BMP characters "
3283+
"with this version of Tcl/Tk");
3284+
return NULL;
3285+
}
3286+
}
3287+
#endif
3288+
32753289
return (PyObject *) Tkapp_New(screenName, className,
32763290
interactive, wantobjects, wantTk,
32773291
sync, use);

0 commit comments

Comments
 (0)