Commit 27c623c8 authored by Serhiy Storchaka's avatar Serhiy Storchaka Committed by GitHub

bpo-31675: Fix memory leaks in Tkinter's methods splitlist() and split() (#3866)

when pass a string larger than 2 GiB.

Decrease memory requirements for Tcl's bigmem tests.
parent 929b40a6
...@@ -662,32 +662,44 @@ class BigmemTclTest(unittest.TestCase): ...@@ -662,32 +662,44 @@ class BigmemTclTest(unittest.TestCase):
@support.bigmemtest(size=INT_MAX + 1, memuse=5, dry_run=False) @support.bigmemtest(size=INT_MAX + 1, memuse=5, dry_run=False)
def test_huge_string_call(self, size): def test_huge_string_call(self, size):
value = ' ' * size value = ' ' * size
self.assertRaises(OverflowError, self.interp.call, 'set', '_', value) self.assertRaises(OverflowError, self.interp.call, 'string', 'index', value, 0)
@support.cpython_only @support.cpython_only
@unittest.skipUnless(INT_MAX < PY_SSIZE_T_MAX, "needs UINT_MAX < SIZE_MAX") @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): def test_huge_string_builtins(self, size):
tk = self.interp.tk
value = '1' + ' ' * size value = '1' + ' ' * size
self.assertRaises(OverflowError, self.interp.tk.getint, value) self.assertRaises(OverflowError, tk.getint, value)
self.assertRaises(OverflowError, self.interp.tk.getdouble, value) self.assertRaises(OverflowError, tk.getdouble, value)
self.assertRaises(OverflowError, self.interp.tk.getboolean, value) self.assertRaises(OverflowError, tk.getboolean, value)
self.assertRaises(OverflowError, self.interp.eval, value) self.assertRaises(OverflowError, tk.eval, value)
self.assertRaises(OverflowError, self.interp.evalfile, value) self.assertRaises(OverflowError, tk.evalfile, value)
self.assertRaises(OverflowError, self.interp.record, value) self.assertRaises(OverflowError, tk.record, value)
self.assertRaises(OverflowError, self.interp.adderrorinfo, value) self.assertRaises(OverflowError, tk.adderrorinfo, value)
self.assertRaises(OverflowError, self.interp.setvar, value, 'x', 'a') self.assertRaises(OverflowError, tk.setvar, value, 'x', 'a')
self.assertRaises(OverflowError, self.interp.setvar, 'x', value, 'a') self.assertRaises(OverflowError, tk.setvar, 'x', value, 'a')
self.assertRaises(OverflowError, self.interp.unsetvar, value) self.assertRaises(OverflowError, tk.unsetvar, value)
self.assertRaises(OverflowError, self.interp.unsetvar, 'x', value) self.assertRaises(OverflowError, tk.unsetvar, 'x', value)
self.assertRaises(OverflowError, self.interp.adderrorinfo, value) self.assertRaises(OverflowError, tk.adderrorinfo, value)
self.assertRaises(OverflowError, self.interp.exprstring, value) self.assertRaises(OverflowError, tk.exprstring, value)
self.assertRaises(OverflowError, self.interp.exprlong, value) self.assertRaises(OverflowError, tk.exprlong, value)
self.assertRaises(OverflowError, self.interp.exprboolean, value) self.assertRaises(OverflowError, tk.exprboolean, value)
self.assertRaises(OverflowError, self.interp.splitlist, value) self.assertRaises(OverflowError, tk.splitlist, value)
self.assertRaises(OverflowError, self.interp.split, value) self.assertRaises(OverflowError, tk.split, value)
self.assertRaises(OverflowError, self.interp.createcommand, value, max) self.assertRaises(OverflowError, tk.createcommand, value, max)
self.assertRaises(OverflowError, self.interp.deletecommand, value) 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(): def setUpModule():
......
Fixed memory leaks in Tkinter's methods splitlist() and split() when pass a
string larger than 2 GiB.
...@@ -2257,7 +2257,11 @@ _tkinter_tkapp_splitlist(TkappObject *self, PyObject *arg) ...@@ -2257,7 +2257,11 @@ _tkinter_tkapp_splitlist(TkappObject *self, PyObject *arg)
if (!PyArg_Parse(arg, "et:splitlist", "utf-8", &list)) if (!PyArg_Parse(arg, "et:splitlist", "utf-8", &list))
return NULL; 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, if (Tcl_SplitList(Tkapp_Interp(self), list,
&argc, &argv) == TCL_ERROR) { &argc, &argv) == TCL_ERROR) {
PyMem_Free(list); PyMem_Free(list);
...@@ -2328,7 +2332,11 @@ _tkinter_tkapp_split(TkappObject *self, PyObject *arg) ...@@ -2328,7 +2332,11 @@ _tkinter_tkapp_split(TkappObject *self, PyObject *arg)
if (!PyArg_Parse(arg, "et:split", "utf-8", &list)) if (!PyArg_Parse(arg, "et:split", "utf-8", &list))
return NULL; 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); v = Split(list);
PyMem_Free(list); PyMem_Free(list);
return v; return v;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment