[Python-checkins] cpython (merge 3.4 -> default): 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/4ff865976bb9
changeset: 93116:4ff865976bb9
parent: 93114:bcd7fe682095
parent: 93115:9ec84f9b61c6
user: Antoine Pitrou <solipsis at pitrou.net>
date: Sat Oct 18 00:35:44 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
@@ -10,6 +10,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

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