[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 27c623c845)
This commit is contained in:
Miss Islington (bot) 2017-10-03 13:50:46 -07:00 committed by Serhiy Storchaka
parent fcc832a4fa
commit a65b2420f6
3 changed files with 45 additions and 23 deletions

View file

@ -662,32 +662,44 @@ class BigmemTclTest(unittest.TestCase):
@support.bigmemtest(size=INT_MAX + 1, memuse=5, dry_run=False)
def test_huge_string_call(self, size):
value = ' ' * size
self.assertRaises(OverflowError, self.interp.call, 'set', '_', value)
self.assertRaises(OverflowError, self.interp.call, 'string', 'index', value, 0)
@support.cpython_only
@unittest.skipUnless(INT_MAX < PY_SSIZE_T_MAX, "needs UINT_MAX < SIZE_MAX")
@support.bigmemtest(size=INT_MAX + 1, memuse=9, dry_run=False)
@support.bigmemtest(size=INT_MAX + 1, memuse=2, dry_run=False)
def test_huge_string_builtins(self, size):
tk = self.interp.tk
value = '1' + ' ' * size
self.assertRaises(OverflowError, self.interp.tk.getint, value)
self.assertRaises(OverflowError, self.interp.tk.getdouble, value)
self.assertRaises(OverflowError, self.interp.tk.getboolean, value)
self.assertRaises(OverflowError, self.interp.eval, value)
self.assertRaises(OverflowError, self.interp.evalfile, value)
self.assertRaises(OverflowError, self.interp.record, value)
self.assertRaises(OverflowError, self.interp.adderrorinfo, value)
self.assertRaises(OverflowError, self.interp.setvar, value, 'x', 'a')
self.assertRaises(OverflowError, self.interp.setvar, 'x', value, 'a')
self.assertRaises(OverflowError, self.interp.unsetvar, value)
self.assertRaises(OverflowError, self.interp.unsetvar, 'x', value)
self.assertRaises(OverflowError, self.interp.adderrorinfo, value)
self.assertRaises(OverflowError, self.interp.exprstring, value)
self.assertRaises(OverflowError, self.interp.exprlong, value)
self.assertRaises(OverflowError, self.interp.exprboolean, value)
self.assertRaises(OverflowError, self.interp.splitlist, value)
self.assertRaises(OverflowError, self.interp.split, value)
self.assertRaises(OverflowError, self.interp.createcommand, value, max)
self.assertRaises(OverflowError, self.interp.deletecommand, value)
self.assertRaises(OverflowError, tk.getint, value)
self.assertRaises(OverflowError, tk.getdouble, value)
self.assertRaises(OverflowError, tk.getboolean, value)
self.assertRaises(OverflowError, tk.eval, value)
self.assertRaises(OverflowError, tk.evalfile, value)
self.assertRaises(OverflowError, tk.record, value)
self.assertRaises(OverflowError, tk.adderrorinfo, value)
self.assertRaises(OverflowError, tk.setvar, value, 'x', 'a')
self.assertRaises(OverflowError, tk.setvar, 'x', value, 'a')
self.assertRaises(OverflowError, tk.unsetvar, value)
self.assertRaises(OverflowError, tk.unsetvar, 'x', value)
self.assertRaises(OverflowError, tk.adderrorinfo, value)
self.assertRaises(OverflowError, tk.exprstring, value)
self.assertRaises(OverflowError, tk.exprlong, value)
self.assertRaises(OverflowError, tk.exprboolean, value)
self.assertRaises(OverflowError, tk.splitlist, value)
self.assertRaises(OverflowError, tk.split, value)
self.assertRaises(OverflowError, tk.createcommand, value, max)
self.assertRaises(OverflowError, tk.deletecommand, value)
@support.cpython_only
@unittest.skipUnless(INT_MAX < PY_SSIZE_T_MAX, "needs UINT_MAX < SIZE_MAX")
@support.bigmemtest(size=INT_MAX + 1, memuse=6, dry_run=False)
def test_huge_string_builtins2(self, size):
# These commands require larger memory for possible error messages
tk = self.interp.tk
value = '1' + ' ' * size
self.assertRaises(OverflowError, tk.evalfile, value)
self.assertRaises(OverflowError, tk.unsetvar, value)
self.assertRaises(OverflowError, tk.unsetvar, 'x', value)
def setUpModule():

View file

@ -0,0 +1,2 @@
Fixed memory leaks in Tkinter's methods splitlist() and split() when pass a
string larger than 2 GiB.

View file

@ -2291,7 +2291,11 @@ _tkinter_tkapp_splitlist(TkappObject *self, PyObject *arg)
if (!PyArg_Parse(arg, "et:splitlist", "utf-8", &list))
return NULL;
CHECK_STRING_LENGTH(list);
if (strlen(list) >= INT_MAX) {
PyErr_SetString(PyExc_OverflowError, "string is too long");
PyMem_Free(list);
return NULL;
}
if (Tcl_SplitList(Tkapp_Interp(self), list,
&argc, &argv) == TCL_ERROR) {
PyMem_Free(list);
@ -2362,7 +2366,11 @@ _tkinter_tkapp_split(TkappObject *self, PyObject *arg)
if (!PyArg_Parse(arg, "et:split", "utf-8", &list))
return NULL;
CHECK_STRING_LENGTH(list);
if (strlen(list) >= INT_MAX) {
PyErr_SetString(PyExc_OverflowError, "string is too long");
PyMem_Free(list);
return NULL;
}
v = Split(list);
PyMem_Free(list);
return v;