Skip to content

Commit a65b242

Browse files
miss-islingtonserhiy-storchaka
authored andcommitted
[3.6] bpo-31675: Fix memory leaks in Tkinter's methods splitlist() and split() (GH-3866) (#3874)
when pass a string larger than 2 GiB. Decrease memory requirements for Tcl's bigmem tests. (cherry picked from commit 27c623c)
1 parent fcc832a commit a65b242

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
@@ -2291,7 +2291,11 @@ _tkinter_tkapp_splitlist(TkappObject *self, PyObject *arg)
22912291
if (!PyArg_Parse(arg, "et:splitlist", "utf-8", &list))
22922292
return NULL;
22932293

2294-
CHECK_STRING_LENGTH(list);
2294+
if (strlen(list) >= INT_MAX) {
2295+
PyErr_SetString(PyExc_OverflowError, "string is too long");
2296+
PyMem_Free(list);
2297+
return NULL;
2298+
}
22952299
if (Tcl_SplitList(Tkapp_Interp(self), list,
22962300
&argc, &argv) == TCL_ERROR) {
22972301
PyMem_Free(list);
@@ -2362,7 +2366,11 @@ _tkinter_tkapp_split(TkappObject *self, PyObject *arg)
23622366

23632367
if (!PyArg_Parse(arg, "et:split", "utf-8", &list))
23642368
return NULL;
2365-
CHECK_STRING_LENGTH(list);
2369+
if (strlen(list) >= INT_MAX) {
2370+
PyErr_SetString(PyExc_OverflowError, "string is too long");
2371+
PyMem_Free(list);
2372+
return NULL;
2373+
}
23662374
v = Split(list);
23672375
PyMem_Free(list);
23682376
return v;

0 commit comments

Comments
 (0)