From dc56f5f48866bf3c5412642bba00890d9a090cfb Mon Sep 17 00:00:00 2001 From: "Miss Islington (bot)" <31488909+miss-islington@users.noreply.github.com> Date: Sun, 9 Feb 2020 00:39:28 -0800 Subject: [PATCH] bpo-39590: make deque.__contains__ and deque.count hold strong references (GH-18421) (GH-18423) (cherry picked from commit c6dedde160a9fce5d049e860f586ad8f93aec822) Co-authored-by: sweeneyde <36520290+sweeneyde@users.noreply.github.com> Co-authored-by: sweeneyde <36520290+sweeneyde@users.noreply.github.com> --- Lib/test/test_deque.py | 12 ++++++++++++ .../Library/2020-02-09-05-51-05.bpo-39590.rf98GU.rst | 1 + Modules/_collectionsmodule.c | 4 ++++ 3 files changed, 17 insertions(+) create mode 100644 Misc/NEWS.d/next/Library/2020-02-09-05-51-05.bpo-39590.rf98GU.rst diff --git a/Lib/test/test_deque.py b/Lib/test/test_deque.py index 51b66b76aca..c0f7138254f 100644 --- a/Lib/test/test_deque.py +++ b/Lib/test/test_deque.py @@ -183,6 +183,18 @@ class TestBasic(unittest.TestCase): with self.assertRaises(RuntimeError): n in d + def test_contains_count_stop_crashes(self): + class A: + def __eq__(self, other): + d.clear() + return NotImplemented + d = deque([A(), A()]) + with self.assertRaises(RuntimeError): + _ = 3 in d + d = deque([A(), A()]) + with self.assertRaises(RuntimeError): + _ = d.count(3) + def test_extend(self): d = deque('a') self.assertRaises(TypeError, d.extend, 1) diff --git a/Misc/NEWS.d/next/Library/2020-02-09-05-51-05.bpo-39590.rf98GU.rst b/Misc/NEWS.d/next/Library/2020-02-09-05-51-05.bpo-39590.rf98GU.rst new file mode 100644 index 00000000000..68625028fb7 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2020-02-09-05-51-05.bpo-39590.rf98GU.rst @@ -0,0 +1 @@ +Collections.deque now holds strong references during deque.__contains__ and deque.count, fixing crashes. \ No newline at end of file diff --git a/Modules/_collectionsmodule.c b/Modules/_collectionsmodule.c index 45169ecd11a..cc2b90eaa28 100644 --- a/Modules/_collectionsmodule.c +++ b/Modules/_collectionsmodule.c @@ -966,7 +966,9 @@ deque_count(dequeobject *deque, PyObject *v) while (--n >= 0) { CHECK_NOT_END(b); item = b->data[index]; + Py_INCREF(item); cmp = PyObject_RichCompareBool(item, v, Py_EQ); + Py_DECREF(item); if (cmp < 0) return NULL; count += cmp; @@ -1003,7 +1005,9 @@ deque_contains(dequeobject *deque, PyObject *v) while (--n >= 0) { CHECK_NOT_END(b); item = b->data[index]; + Py_INCREF(item); cmp = PyObject_RichCompareBool(item, v, Py_EQ); + Py_DECREF(item); if (cmp) { return cmp; }