[pypy-commit] pypy default: Obviously, adding ll_prepare_dict_update() exposed a latent bug

arigo noreply at buildbot.pypy.org
Sun Dec 14 17:23:09 CET 2014


Author: Armin Rigo <arigo at tunes.org>
Branch: 
Changeset: r74912:ef301ae5ae96
Date: 2014-12-14 17:23 +0100
http://bitbucket.org/pypy/pypy/changeset/ef301ae5ae96/

Log:	Obviously, adding ll_prepare_dict_update() exposed a latent bug

diff --git a/rpython/rtyper/lltypesystem/rordereddict.py b/rpython/rtyper/lltypesystem/rordereddict.py
--- a/rpython/rtyper/lltypesystem/rordereddict.py
+++ b/rpython/rtyper/lltypesystem/rordereddict.py
@@ -600,10 +600,12 @@
     else:
         newitems = d.entries
     #
-    ENTRY = lltype.typeOf(d).TO.entries.TO.OF
+    ENTRIES = lltype.typeOf(d).TO.entries.TO
+    ENTRY = ENTRIES.OF
     isrc = 0
     idst = 0
-    while isrc < len(d.entries):
+    isrclimit = d.num_used_items
+    while isrc < isrclimit:
         if d.entries.valid(isrc):
             src = d.entries[isrc]
             dst = newitems[idst]
@@ -616,9 +618,21 @@
                 dst.f_valid = True
             idst += 1
         isrc += 1
-    d.entries = newitems
     assert d.num_items == idst
     d.num_used_items = idst
+    if ((ENTRIES.must_clear_key or ENTRIES.must_clear_value) and
+            d.entries == newitems):
+        # must clear the extra entries: they may contain valid pointers
+        # which would create a temporary memory leak
+        while idst < isrclimit:
+            entry = newitems[idst]
+            if ENTRIES.must_clear_key:
+                entry.key = lltype.nullptr(ENTRY.key.TO)
+            if ENTRIES.must_clear_value:
+                entry.value = lltype.nullptr(ENTRY.value.TO)
+            idst += 1
+    else:
+        d.entries = newitems
 
     ll_dict_reindex(d, _ll_len_of_d_indexes(d))
 
diff --git a/rpython/rtyper/test/test_rordereddict.py b/rpython/rtyper/test/test_rordereddict.py
--- a/rpython/rtyper/test/test_rordereddict.py
+++ b/rpython/rtyper/test/test_rordereddict.py
@@ -251,6 +251,16 @@
         assert rordereddict.ll_dict_pop_default(ll_d, llstr("k"), 40) == 40
         assert rordereddict.ll_dict_pop_default(ll_d, llstr("j"), 39) == 39
 
+    def test_bug_remove_deleted_items(self):
+        DICT = self._get_str_dict()
+        ll_d = rordereddict.ll_newdict(DICT)
+        for i in range(15):
+            rordereddict.ll_dict_setitem(ll_d, llstr(chr(i)), 5)
+        for i in range(15):
+            rordereddict.ll_dict_delitem(ll_d, llstr(chr(i)))
+        rordereddict.ll_prepare_dict_update(ll_d, 7)
+        # used to get UninitializedMemoryAccess
+
 class TestRDictDirectDummyKey(TestRDictDirect):
     class dummykeyobj:
         ll_dummy_value = llstr("dupa")


More information about the pypy-commit mailing list