cpython: 3e3a7d825736 (original) (raw)
Mercurial > cpython
changeset 81989:3e3a7d825736
Issue #6083: Fix multiple segmentation faults occured when PyArg_ParseTuple parses nested mutating sequence. [#6083]
Serhiy Storchaka storchaka@gmail.com | |
---|---|
date | Mon, 04 Feb 2013 12:57:16 +0200 |
parents | 1791304d05c4(current diff)e0ee10f27e5f(diff) |
children | e6d6b860a720 |
files | Lib/test/test_functools.py Lib/test/test_resource.py Misc/NEWS |
diffstat | 7 files changed, 117 insertions(+), 16 deletions(-)[+] [-] Lib/ctypes/test/test_returnfuncptrs.py 28 Lib/test/test_functools.py 22 Lib/test/test_resource.py 17 Misc/NEWS 3 Modules/_ctypes/_ctypes.c 24 Modules/_functoolsmodule.c 6 Modules/resource.c 33 |
line wrap: on
line diff
--- a/Lib/ctypes/test/test_returnfuncptrs.py +++ b/Lib/ctypes/test/test_returnfuncptrs.py @@ -33,5 +33,33 @@ class ReturnFuncPtrTestCase(unittest.Tes self.assertRaises(ArgumentError, strchr, b"abcdef", 3.0) self.assertRaises(TypeError, strchr, b"abcdef")
- def test_from_dll(self):
dll = CDLL(_ctypes_test.__file__)[](#l1.8)
# _CFuncPtr instances are now callable with a tuple argument[](#l1.9)
# which denotes a function name and a dll:[](#l1.10)
strchr = CFUNCTYPE(c_char_p, c_char_p, c_char)(("strchr", dll))[](#l1.11)
self.assertTrue(strchr(b"abcdef", b"b"), "bcdef")[](#l1.12)
self.assertEqual(strchr(b"abcdef", b"x"), None)[](#l1.13)
self.assertRaises(ArgumentError, strchr, b"abcdef", 3.0)[](#l1.14)
self.assertRaises(TypeError, strchr, b"abcdef")[](#l1.15)
Issue 6083: Reference counting bug
- def test_test_from_dll_refcount(self):
class BadSequence(tuple):[](#l1.19)
def __getitem__(self, key):[](#l1.20)
if key == 0:[](#l1.21)
return "strchr"[](#l1.22)
if key == 1:[](#l1.23)
return CDLL(_ctypes_test.__file__)[](#l1.24)
raise IndexError[](#l1.25)
# _CFuncPtr instances are now callable with a tuple argument[](#l1.27)
# which denotes a function name and a dll:[](#l1.28)
strchr = CFUNCTYPE(c_char_p, c_char_p, c_char)(BadSequence(("strchr", CDLL(_ctypes_test.__file__))))[](#l1.29)
self.assertTrue(strchr(b"abcdef", b"b"), "bcdef")[](#l1.30)
self.assertEqual(strchr(b"abcdef", b"x"), None)[](#l1.31)
self.assertRaises(ArgumentError, strchr, b"abcdef", 3.0)[](#l1.32)
self.assertRaises(TypeError, strchr, b"abcdef")[](#l1.33)
+ if name == "main": unittest.main()
--- a/Lib/test/test_functools.py +++ b/Lib/test/test_functools.py @@ -194,7 +194,25 @@ class TestPartial(object): self.assertEqual(signature(f), signature(f_copy)) class TestPartialC(BaseTestC, TestPartial):
Issue 6083: Reference counting bug
- def test_setstate_refcount(self):
class BadSequence:[](#l2.11)
def __len__(self):[](#l2.12)
return 4[](#l2.13)
def __getitem__(self, key):[](#l2.14)
if key == 0:[](#l2.15)
return max[](#l2.16)
elif key == 1:[](#l2.17)
return tuple(range(1000000))[](#l2.18)
elif key in (2, 3):[](#l2.19)
return {}[](#l2.20)
raise IndexError[](#l2.21)
f = self.partial(object)[](#l2.23)
self.assertRaisesRegex(SystemError,[](#l2.24)
"new style getargs format but argument is not a tuple",[](#l2.25)
f.__setstate__, BadSequence())[](#l2.26)
class TestPartialPy(BaseTestPy, TestPartial): @@ -204,7 +222,7 @@ class TestPartialPy(BaseTestPy, TestPart def test_repr(self): raise unittest.SkipTest("Python implementation of partial uses own repr") -class TestPartialCSubclass(BaseTestC, TestPartial): +class TestPartialCSubclass(TestPartialC): class PartialSubclass(c_functools.partial): pass
--- a/Lib/test/test_resource.py +++ b/Lib/test/test_resource.py @@ -107,6 +107,23 @@ class ResourceTest(unittest.TestCase): except (ValueError, AttributeError): pass
Issue 6083: Reference counting bug
- def test_setrusage_refcount(self):
try:[](#l3.9)
limits = resource.getrlimit(resource.RLIMIT_CPU)[](#l3.10)
except AttributeError:[](#l3.11)
pass[](#l3.12)
else:[](#l3.13)
class BadSequence:[](#l3.14)
def __len__(self):[](#l3.15)
return 2[](#l3.16)
def __getitem__(self, key):[](#l3.17)
if key in (0, 1):[](#l3.18)
return len(tuple(range(1000000)))[](#l3.19)
raise IndexError[](#l3.20)
resource.setrlimit(resource.RLIMIT_CPU, BadSequence())[](#l3.22)
+ def test_main(verbose=None): support.run_unittest(ResourceTest)
--- a/Misc/NEWS +++ b/Misc/NEWS @@ -235,6 +235,9 @@ Core and Builtins Library ------- +- Issue #6083: Fix multiple segmentation faults occured when PyArg_ParseTuple
- Issue #5289: Fix ctypes.util.find_library on Solaris.
- Issue #17106: Fix a segmentation fault in io.TextIOWrapper when an underlying
--- a/Modules/_ctypes/_ctypes.c +++ b/Modules/_ctypes/_ctypes.c @@ -3188,23 +3188,37 @@ PyCFuncPtr_FromDll(PyTypeObject *type, P { char name; int ( address)(void);
- PyObject *ftuple; PyObject *dll; PyObject *obj; PyCFuncPtrObject *self; void *handle; PyObject *paramflags = NULL;
- if (!PyArg_ParseTuple(args, "O|O", &ftuple, ¶mflags)) return NULL; if (paramflags == Py_None) paramflags = NULL;
- ftuple = PySequence_Tuple(ftuple);
- if (!ftuple)
/* Here ftuple is a borrowed reference */[](#l5.22)
return NULL;[](#l5.23)
- if (!PyArg_ParseTuple(ftuple, "O&O", _get_name, &name, &dll)) {
Py_DECREF(ftuple);[](#l5.26)
return NULL;[](#l5.27)
- }
+ obj = PyObject_GetAttrString(dll, "_handle");
- if (!obj) {
Py_DECREF(ftuple);[](#l5.33) return NULL;[](#l5.34)
- } if (!PyLong_Check(obj)) { PyErr_SetString(PyExc_TypeError, "the _handle attribute of the second argument must be an integer");
} @@ -3213,6 +3227,7 @@ PyCFuncPtr_FromDll(PyTypeObject *type, P if (PyErr_Occurred()) { PyErr_SetString(PyExc_ValueError, "could not convert the _handle attribute to a pointer");Py_DECREF(ftuple);[](#l5.39) Py_DECREF(obj);[](#l5.40) return NULL;[](#l5.41)
} @@ -3227,6 +3242,7 @@ PyCFuncPtr_FromDll(PyTypeObject *type, P PyErr_Format(PyExc_AttributeError, "function ordinal %d not found", (WORD)(size_t)name);Py_DECREF(ftuple);[](#l5.47) return NULL;[](#l5.48)
}Py_DECREF(ftuple);[](#l5.55) return NULL;[](#l5.56)
#else @@ -3240,9 +3256,12 @@ PyCFuncPtr_FromDll(PyTypeObject *type, P #else PyErr_SetString(PyExc_AttributeError, ctypes_dlerror()); #endif
- Py_INCREF(dll); /* for KeepRef */
- Py_DECREF(ftuple); if (!_validate_paramflags(type, paramflags)) return NULL;
@@ -3255,7 +3274,6 @@ PyCFuncPtr_FromDll(PyTypeObject *type, P *(void **)self->b_ptr = address;
- Py_INCREF((PyObject )dll); / for KeepRef */ if (-1 == KeepRef((CDataObject *)self, 0, dll)) { Py_DECREF((PyObject *)self); return NULL;
--- a/Modules/_functoolsmodule.c +++ b/Modules/_functoolsmodule.c @@ -218,10 +218,10 @@ partial_reduce(partialobject *pto, PyObj } static PyObject * -partial_setstate(partialobject *pto, PyObject *args) +partial_setstate(partialobject *pto, PyObject *state) { PyObject *fn, *fnargs, *kw, *dict;
- if (!PyArg_ParseTuple(state, "OOOO", &fn, &fnargs, &kw, &dict)) return NULL; Py_XDECREF(pto->fn); @@ -245,7 +245,7 @@ partial_setstate(partialobject *pto, PyO static PyMethodDef partial_methods[] = { {"reduce", (PyCFunction)partial_reduce, METH_NOARGS},
--- a/Modules/resource.c +++ b/Modules/resource.c @@ -142,10 +142,9 @@ resource_setrlimit(PyObject *self, PyObj { struct rlimit rl; int resource;
if (resource < 0 || resource >= RLIM_NLIMITS) { @@ -154,21 +153,34 @@ resource_setrlimit(PyObject *self, PyObj return NULL; }
- limits = PySequence_Tuple(limits);
- if (!limits)
/* Here limits is a borrowed reference */[](#l7.22)
return NULL;[](#l7.23)
- if (PyTuple_GET_SIZE(limits) != 2) {
PyErr_SetString(PyExc_ValueError,[](#l7.26)
"expected a tuple of 2 integers");[](#l7.27)
goto error;[](#l7.28)
- }
- curobj = PyTuple_GET_ITEM(limits, 0);
- maxobj = PyTuple_GET_ITEM(limits, 1);
+ #if !defined(HAVE_LARGEFILE_SUPPORT) rl.rlim_cur = PyLong_AsLong(curobj); if (rl.rlim_cur == (rlim_t)-1 && PyErr_Occurred())
return NULL;[](#l7.36)
rl.rlim_max = PyLong_AsLong(maxobj); if (rl.rlim_max == (rlim_t)-1 && PyErr_Occurred())goto error;[](#l7.37)
return NULL;[](#l7.40)
goto error;[](#l7.41)
#else /* The limits are probably bigger than a long */ rl.rlim_cur = PyLong_AsLongLong(curobj); if (rl.rlim_cur == (rlim_t)-1 && PyErr_Occurred())
return NULL;[](#l7.46)
rl.rlim_max = PyLong_AsLongLong(maxobj); if (rl.rlim_max == (rlim_t)-1 && PyErr_Occurred())goto error;[](#l7.47)
return NULL;[](#l7.50)
goto error;[](#l7.51)
#endif rl.rlim_cur = rl.rlim_cur & RLIM_INFINITY; @@ -182,10 +194,15 @@ resource_setrlimit(PyObject *self, PyObj "not allowed to raise maximum limit"); else PyErr_SetFromErrno(PyExc_OSError);
return NULL;[](#l7.59)