[Python-checkins] cpython (3.4): Issue #22653: Fix an assertion failure in debug mode when doing a reentrant

antoine.pitrou python-checkins at python.org
Sat Oct 18 00:35:56 CEST 2014


https://hg.python.org/cpython/rev/9ec84f9b61c6
changeset:   93115:9ec84f9b61c6
branch:      3.4
parent:      93113:6ad0299fa279
user:        Antoine Pitrou <solipsis at pitrou.net>
date:        Sat Oct 18 00:35:00 2014 +0200
summary:
  Issue #22653: Fix an assertion failure in debug mode when doing a reentrant dict insertion in debug mode.

files:
  Lib/test/test_dict.py |  29 +++++++++++++++++++++++++++++
  Misc/NEWS             |   3 +++
  Objects/dictobject.c  |   6 +++---
  3 files changed, 35 insertions(+), 3 deletions(-)


diff --git a/Lib/test/test_dict.py b/Lib/test/test_dict.py
--- a/Lib/test/test_dict.py
+++ b/Lib/test/test_dict.py
@@ -906,6 +906,35 @@
         f.a = 'a'
         self.assertEqual(f.__dict__, {1:1, 'a':'a'})
 
+    def check_reentrant_insertion(self, mutate):
+        # This object will trigger mutation of the dict when replaced
+        # by another value.  Note this relies on refcounting: the test
+        # won't achieve its purpose on fully-GCed Python implementations.
+        class Mutating:
+            def __del__(self):
+                mutate(d)
+
+        d = {k: Mutating() for k in 'abcdefghijklmnopqr'}
+        for k in list(d):
+            d[k] = k
+
+    def test_reentrant_insertion(self):
+        # Reentrant insertion shouldn't crash (see issue #22653)
+        def mutate(d):
+            d['b'] = 5
+        self.check_reentrant_insertion(mutate)
+
+        def mutate(d):
+            d.update(self.__dict__)
+            d.clear()
+        self.check_reentrant_insertion(mutate)
+
+        def mutate(d):
+            while d:
+                d.popitem()
+        self.check_reentrant_insertion(mutate)
+
+
 from test import mapping_tests
 
 class GeneralMappingTests(mapping_tests.BasicTestMappingProtocol):
diff --git a/Misc/NEWS b/Misc/NEWS
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -11,6 +11,9 @@
 Core and Builtins
 -----------------
 
+- Issue #22653: Fix an assertion failure in debug mode when doing a reentrant
+  dict insertion in debug mode.
+
 - Issue #22643: Fix integer overflow in Unicode case operations (upper, lower,
   title, swapcase, casefold).
 
diff --git a/Objects/dictobject.c b/Objects/dictobject.c
--- a/Objects/dictobject.c
+++ b/Objects/dictobject.c
@@ -814,13 +814,14 @@
     if (ep == NULL) {
         return -1;
     }
+    assert(PyUnicode_CheckExact(key) || mp->ma_keys->dk_lookup == lookdict);
     Py_INCREF(value);
     MAINTAIN_TRACKING(mp, key, value);
     old_value = *value_addr;
     if (old_value != NULL) {
         assert(ep->me_key != NULL && ep->me_key != dummy);
         *value_addr = value;
-        Py_DECREF(old_value); /* which **CAN** re-enter */
+        Py_DECREF(old_value); /* which **CAN** re-enter (see issue #22653) */
     }
     else {
         if (ep->me_key == NULL) {
@@ -851,9 +852,8 @@
         }
         mp->ma_used++;
         *value_addr = value;
+        assert(ep->me_key != NULL && ep->me_key != dummy);
     }
-    assert(ep->me_key != NULL && ep->me_key != dummy);
-    assert(PyUnicode_CheckExact(key) || mp->ma_keys->dk_lookup == lookdict);
     return 0;
 }
 

-- 
Repository URL: https://hg.python.org/cpython


More information about the Python-checkins mailing list