Skip to content

Commit 27c623c

Browse files
bpo-31675: Fix memory leaks in Tkinter's methods splitlist() and split() (python#3866)
when pass a string larger than 2 GiB. Decrease memory requirements for Tcl's bigmem tests.
1 parent 929b40a commit 27c623c

File tree

3 files changed

+45
-23
lines changed

3 files changed

+45
-23
lines changed

Lib/test/test_tcl.py

Lines changed: 33 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -662,32 +662,44 @@ def setUp(self):
662662
@support.bigmemtest(size=INT_MAX + 1, memuse=5, dry_run=False)
663663
def test_huge_string_call(self, size):
664664
value = ' ' * size
665-
self.assertRaises(OverflowError, self.interp.call, 'set', '_', value)
665+
self.assertRaises(OverflowError, self.interp.call, 'string', 'index', value, 0)
666666

667667
@support.cpython_only
668668
@unittest.skipUnless(INT_MAX < PY_SSIZE_T_MAX, "needs UINT_MAX < SIZE_MAX")
669-
@support.bigmemtest(size=INT_MAX + 1, memuse=9, dry_run=False)
669+
@support.bigmemtest(size=INT_MAX + 1, memuse=2, dry_run=False)
670670
def test_huge_string_builtins(self, size):
671+
tk = self.interp.tk
671672
value = '1' + ' ' * size
672-
self.assertRaises(OverflowError, self.interp.tk.getint, value)
673-
self.assertRaises(OverflowError, self.interp.tk.getdouble, value)
674-
self.assertRaises(OverflowError, self.interp.tk.getboolean, value)
675-
self.assertRaises(OverflowError, self.interp.eval, value)
676-
self.assertRaises(OverflowError, self.interp.evalfile, value)
677-
self.assertRaises(OverflowError, self.interp.record, value)
678-
self.assertRaises(OverflowError, self.interp.adderrorinfo, value)
679-
self.assertRaises(OverflowError, self.interp.setvar, value, 'x', 'a')
680-
self.assertRaises(OverflowError, self.interp.setvar, 'x', value, 'a')
681-
self.assertRaises(OverflowError, self.interp.unsetvar, value)
682-
self.assertRaises(OverflowError, self.interp.unsetvar, 'x', value)
683-
self.assertRaises(OverflowError, self.interp.adderrorinfo, value)
684-
self.assertRaises(OverflowError, self.interp.exprstring, value)
685-
self.assertRaises(OverflowError, self.interp.exprlong, value)
686-
self.assertRaises(OverflowError, self.interp.exprboolean, value)
687-
self.assertRaises(OverflowError, self.interp.splitlist, value)
688-
self.assertRaises(OverflowError, self.interp.split, value)
689-
self.assertRaises(OverflowError, self.interp.createcommand, value, max)
690-
self.assertRaises(OverflowError, self.interp.deletecommand, value)
673+
self.assertRaises(OverflowError, tk.getint, value)
674+
self.assertRaises(OverflowError, tk.getdouble, value)
675+
self.assertRaises(OverflowError, tk.getboolean, value)
676+
self.assertRaises(OverflowError, tk.eval, value)
677+
self.assertRaises(OverflowError, tk.evalfile, value)
678+
self.assertRaises(OverflowError, tk.record, value)
679+
self.assertRaises(OverflowError, tk.adderrorinfo, value)
680+
self.assertRaises(OverflowError, tk.setvar, value, 'x', 'a')
681+
self.assertRaises(OverflowError, tk.setvar, 'x', value, 'a')
682+
self.assertRaises(OverflowError, tk.unsetvar, value)
683+
self.assertRaises(OverflowError, tk.unsetvar, 'x', value)
684+
self.assertRaises(OverflowError, tk.adderrorinfo, value)
685+
self.assertRaises(OverflowError, tk.exprstring, value)
686+
self.assertRaises(OverflowError, tk.exprlong, value)
687+
self.assertRaises(OverflowError, tk.exprboolean, value)
688+
self.assertRaises(OverflowError, tk.splitlist, value)
689+
self.assertRaises(OverflowError, tk.split, value)
690+
self.assertRaises(OverflowError, tk.createcommand, value, max)
691+
self.assertRaises(OverflowError, tk.deletecommand, value)
692+
693+
@support.cpython_only
694+
@unittest.skipUnless(INT_MAX < PY_SSIZE_T_MAX, "needs UINT_MAX < SIZE_MAX")
695+
@support.bigmemtest(size=INT_MAX + 1, memuse=6, dry_run=False)
696+
def test_huge_string_builtins2(self, size):
697+
# These commands require larger memory for possible error messages
698+
tk = self.interp.tk
699+
value = '1' + ' ' * size
700+
self.assertRaises(OverflowError, tk.evalfile, value)
701+
self.assertRaises(OverflowError, tk.unsetvar, value)
702+
self.assertRaises(OverflowError, tk.unsetvar, 'x', value)
691703

692704

693705
def setUpModule():
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Fixed memory leaks in Tkinter's methods splitlist() and split() when pass a
2+
string larger than 2 GiB.

Modules/_tkinter.c

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2257,7 +2257,11 @@ _tkinter_tkapp_splitlist(TkappObject *self, PyObject *arg)
22572257
if (!PyArg_Parse(arg, "et:splitlist", "utf-8", &list))
22582258
return NULL;
22592259

2260-
CHECK_STRING_LENGTH(list);
2260+
if (strlen(list) >= INT_MAX) {
2261+
PyErr_SetString(PyExc_OverflowError, "string is too long");
2262+
PyMem_Free(list);
2263+
return NULL;
2264+
}
22612265
if (Tcl_SplitList(Tkapp_Interp(self), list,
22622266
&argc, &argv) == TCL_ERROR) {
22632267
PyMem_Free(list);
@@ -2328,7 +2332,11 @@ _tkinter_tkapp_split(TkappObject *self, PyObject *arg)
23282332

23292333
if (!PyArg_Parse(arg, "et:split", "utf-8", &list))
23302334
return NULL;
2331-
CHECK_STRING_LENGTH(list);
2335+
if (strlen(list) >= INT_MAX) {
2336+
PyErr_SetString(PyExc_OverflowError, "string is too long");
2337+
PyMem_Free(list);
2338+
return NULL;
2339+
}
23322340
v = Split(list);
23332341
PyMem_Free(list);
23342342
return v;

0 commit comments

Comments
 (0)