]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
Issue #25406: Fixed a bug in C implementation of OrderedDict.move_to_end()
authorSerhiy Storchaka <storchaka@gmail.com>
Wed, 14 Oct 2015 16:21:24 +0000 (19:21 +0300)
committerSerhiy Storchaka <storchaka@gmail.com>
Wed, 14 Oct 2015 16:21:24 +0000 (19:21 +0300)
that caused segmentation fault or hang in iterating after moving several
items to the start of ordered dict.

Lib/test/test_collections.py
Misc/NEWS
Objects/odictobject.c

index 4124f91e15a7c52967a703967e0d7e49c9251581..3ed3abdf2fe3dc4f47d02ff5e56a25946077e0e2 100644 (file)
@@ -1995,6 +1995,20 @@ class OrderedDictTests:
         with self.assertRaises(KeyError):
             od.move_to_end('x', 0)
 
+    def test_move_to_end_issue25406(self):
+        OrderedDict = self.module.OrderedDict
+        od = OrderedDict.fromkeys('abc')
+        od.move_to_end('c', last=False)
+        self.assertEqual(list(od), list('cab'))
+        od.move_to_end('a', last=False)
+        self.assertEqual(list(od), list('acb'))
+
+        od = OrderedDict.fromkeys('abc')
+        od.move_to_end('a')
+        self.assertEqual(list(od), list('bca'))
+        od.move_to_end('c')
+        self.assertEqual(list(od), list('bac'))
+
     def test_sizeof(self):
         OrderedDict = self.module.OrderedDict
         # Wimpy test: Just verify the reported size is larger than a regular dict
index cb8d36da639c57cc29631ba25f5a55f0270b9465..c0ea6e5d2015435a69c344dce1338d5f445d3478 100644 (file)
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -45,6 +45,10 @@ Core and Builtins
 Library
 -------
 
+- Issue #25406: Fixed a bug in C implementation of OrderedDict.move_to_end()
+  that caused segmentation fault or hang in iterating after moving several
+  items to the start of ordered dict.
+
 - Issue #25364: zipfile now works in threads disabled builds.
 
 - Issue #25328: smtpd's SMTPChannel now correctly raises a ValueError if both
index 7df419e0ff67bad63825658719377b988a441792..8fe838ae0c98796227041869e7a1c4636851d6fb 100644 (file)
@@ -618,37 +618,26 @@ _odict_find_node(PyODictObject *od, PyObject *key)
 static void
 _odict_add_head(PyODictObject *od, _ODictNode *node)
 {
-    if (_odict_FIRST(od) == NULL) {
-        _odictnode_PREV(node) = NULL;
-        _odictnode_NEXT(node) = NULL;
-        _odict_FIRST(od) = node;
+    _odictnode_PREV(node) = NULL;
+    _odictnode_NEXT(node) = _odict_FIRST(od);
+    if (_odict_FIRST(od) == NULL)
         _odict_LAST(od) = node;
-    }
-    else {
-        _odictnode_PREV(node) = NULL;
-        _odictnode_NEXT(node) = _odict_FIRST(od);
-        _odict_FIRST(od) = node;
+    else
         _odictnode_PREV(_odict_FIRST(od)) = node;
-    }
+    _odict_FIRST(od) = node;
     od->od_state++;
 }
 
 static void
 _odict_add_tail(PyODictObject *od, _ODictNode *node)
 {
-    if (_odict_LAST(od) == NULL) {
-        _odictnode_PREV(node) = NULL;
-        _odictnode_NEXT(node) = NULL;
+    _odictnode_PREV(node) = _odict_LAST(od);
+    _odictnode_NEXT(node) = NULL;
+    if (_odict_LAST(od) == NULL)
         _odict_FIRST(od) = node;
-        _odict_LAST(od) = node;
-    }
-    else {
-        _odictnode_PREV(node) = _odict_LAST(od);
-        _odictnode_NEXT(node) = NULL;
+    else
         _odictnode_NEXT(_odict_LAST(od)) = node;
-        _odict_LAST(od) = node;
-    }
-
+    _odict_LAST(od) = node;
     od->od_state++;
 }