[Python-checkins] cpython (merge 3.5 -> default): Issue #25449: Fixed a crash and leaking NULL in repr() of OrderedDict that

serhiy.storchaka python-checkins at python.org
Wed Nov 4 15:34:03 EST 2015


https://hg.python.org/cpython/rev/76e848554b5d
changeset: 98963:76e848554b5d
parent: 98961:9db4191723eb
parent: 98962:59c7615ea921
user: Serhiy Storchaka <storchaka at gmail.com>
date: Wed Nov 04 22:33:33 2015 +0200
summary:
 Issue #25449: Fixed a crash and leaking NULL in repr() of OrderedDict that
was mutated by direct calls of dict methods.
files:
 Lib/test/test_collections.py | 54 ++++++++++++++++++++++++
 Misc/NEWS | 3 +
 Objects/odictobject.c | 15 +++++-
 3 files changed, 70 insertions(+), 2 deletions(-)
diff --git a/Lib/test/test_collections.py b/Lib/test/test_collections.py
--- a/Lib/test/test_collections.py
+++ b/Lib/test/test_collections.py
@@ -2153,6 +2153,60 @@
 key = c0 + c1
 od[key] = key
 
+ # Direct use of dict methods
+
+ def test_dict_setitem(self):
+ OrderedDict = self.OrderedDict
+ od = OrderedDict()
+ dict.__setitem__(od, 'spam', 1)
+ self.assertNotIn('NULL', repr(od))
+
+ def test_dict_delitem(self):
+ OrderedDict = self.OrderedDict
+ od = OrderedDict()
+ od['spam'] = 1
+ od['ham'] = 2
+ dict.__delitem__(od, 'spam')
+ with self.assertRaises(KeyError):
+ repr(od)
+
+ def test_dict_clear(self):
+ OrderedDict = self.OrderedDict
+ od = OrderedDict()
+ od['spam'] = 1
+ od['ham'] = 2
+ dict.clear(od)
+ self.assertNotIn('NULL', repr(od))
+
+ def test_dict_pop(self):
+ OrderedDict = self.OrderedDict
+ od = OrderedDict()
+ od['spam'] = 1
+ od['ham'] = 2
+ dict.pop(od, 'spam')
+ with self.assertRaises(KeyError):
+ repr(od)
+
+ def test_dict_popitem(self):
+ OrderedDict = self.OrderedDict
+ od = OrderedDict()
+ od['spam'] = 1
+ od['ham'] = 2
+ dict.popitem(od)
+ with self.assertRaises(KeyError):
+ repr(od)
+
+ def test_dict_setdefault(self):
+ OrderedDict = self.OrderedDict
+ od = OrderedDict()
+ dict.setdefault(od, 'spam', 1)
+ self.assertNotIn('NULL', repr(od))
+
+ def test_dict_update(self):
+ od = OrderedDict()
+ dict.update(od, [('spam', 1)])
+ self.assertNotIn('NULL', repr(od))
+
 
 class PurePythonOrderedDictTests(OrderedDictTests, unittest.TestCase):
 
diff --git a/Misc/NEWS b/Misc/NEWS
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -10,6 +10,9 @@
 Core and Builtins
 -----------------
 
+- Issue #25449: Fixed a crash and leaking NULL in repr() of OrderedDict that
+ was mutated by direct calls of dict methods.
+
 - Issue #25449: Iterating OrderedDict with keys with unstable hash now raises
 KeyError in C implementations as well as in Python implementation.
 
diff --git a/Objects/odictobject.c b/Objects/odictobject.c
--- a/Objects/odictobject.c
+++ b/Objects/odictobject.c
@@ -1462,7 +1462,6 @@
 {
 int i;
 _Py_IDENTIFIER(items);
- Py_ssize_t count = -1;
 PyObject *pieces = NULL, *result = NULL;
 const char *classname;
 
@@ -1481,6 +1480,7 @@
 }
 
 if (PyODict_CheckExact(self)) {
+ Py_ssize_t count = 0;
 _ODictNode *node;
 pieces = PyList_New(PyODict_SIZE(self));
 if (pieces == NULL)
@@ -1499,8 +1499,19 @@
 if (pair == NULL)
 goto Done;
 
- PyList_SET_ITEM(pieces, ++count, pair); /* steals reference */
+ if (count < PyList_GET_SIZE(pieces))
+ PyList_SET_ITEM(pieces, count, pair); /* steals reference */
+ else {
+ if (PyList_Append(pieces, pair) < 0) {
+ Py_DECREF(pair);
+ goto Done;
+ }
+ Py_DECREF(pair);
+ }
+ count++;
 }
+ if (count < PyList_GET_SIZE(pieces))
+ PyList_GET_SIZE(pieces) = count;
 }
 else {
 PyObject *items = _PyObject_CallMethodIdObjArgs((PyObject *)self,
-- 
Repository URL: https://hg.python.org/cpython


More information about the Python-checkins mailing list

AltStyle によって変換されたページ (->オリジナル) /