https://github.com/python/cpython/commit/6026791c977a1df2ff8a427aad294388992ae078
commit: 6026791c977a1df2ff8a427aad294388992ae078
branch: main
author: sobolevn <[email protected]>
committer: sobolevn <[email protected]>
date: 2026-11-07T11:04:46Z
summary:
gh-161388: [tkinter] Fix crash on raising `__str__` method passed to `setvar`
(#161397)
files:
M Lib/test/test_tcl.py
M Modules/_tkinter.c
diff --git a/Lib/test/test_tcl.py b/Lib/test/test_tcl.py
index 31ef1457ef3944..9f749b4ec9c345 100644
--- a/Lib/test/test_tcl.py
+++ b/Lib/test/test_tcl.py
@@ -601,6 +601,29 @@ def test_returning_deeply_nested(self):
# event handle on Windows when test_tcl is run with -R 3:3 option.
_tkinter._finalize_thread()
+ def test_setvar_evil(self):
+ # gh-161388
+ class StrRaises:
+ def __str__(self):
+ raise RuntimeError("setvar evil")
+
+ value = StrRaises()
+ tk = self.interp.tk
+
+ with self.assertRaisesRegex(RuntimeError, "setvar evil"):
+ tk.setvar("local_name1", value)
+ self.assertRaises(TclError, tk.getvar, "local_name1")
+ with self.assertRaisesRegex(RuntimeError, "setvar evil"):
+ tk.setvar("local_name2", "local_name3", value)
+ self.assertRaises(TclError, tk.getvar, "local_name2", "local_name3")
+
+ with self.assertRaisesRegex(RuntimeError, "setvar evil"):
+ tk.globalsetvar("global_name1", value)
+ self.assertRaises(TclError, tk.globalgetvar, "global_name1")
+ with self.assertRaisesRegex(RuntimeError, "setvar evil"):
+ tk.globalsetvar("global_name2", "global_name3", value)
+ self.assertRaises(TclError, tk.globalgetvar, "global_name2",
"global_name3")
+
def test_user_command(self):
result = None
def testfunc(arg):
diff --git a/Modules/_tkinter.c b/Modules/_tkinter.c
index 9540839b9682bc..d0a03953a80d92 100644
--- a/Modules/_tkinter.c
+++ b/Modules/_tkinter.c
@@ -1234,8 +1234,9 @@ AsObjNested(PyObject *value, int depth)
{
PyObject *v = PyObject_Str(value);
- if (!v)
- return 0;
+ if (!v) {
+ return NULL;
+ }
result = AsObjNested(v, depth);
Py_DECREF(v);
return result;
@@ -2101,6 +2102,9 @@ SetVar(TkappObject *self, PyObject *args, int flags)
/* XXX must hold tcl lock already??? */
newval = AsObj(newValue);
+ if (newval == NULL) {
+ return NULL;
+ }
if (self->trace) {
if (flags & TCL_GLOBAL_ONLY) {
TRACE(self, ("((sssNO))", "uplevel", "#0", "set",
_______________________________________________
Python-checkins mailing list -- [email protected]
To unsubscribe send an email to [email protected]
https://mail.python.org/mailman3//lists/python-checkins.python.org
Member address: [email protected]