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]

Reply via email to