summaryrefslogtreecommitdiff
path: root/Objects
diff options
context:
space:
mode:
authorTim Peters <tim.peters@gmail.com>2006-10-09 20:24:45 +0000
committerTim Peters <tim.peters@gmail.com>2006-10-09 20:24:45 +0000
commit2b37ea40871ec45cb1fb6d98a2696bcaf4cf6583 (patch)
treec613bfebac501d6a94b922da81cba5070be00ab1 /Objects
parentb8f82e6febddbd534e0f08ab480367561daa0717 (diff)
downloadcpython-git-2b37ea40871ec45cb1fb6d98a2696bcaf4cf6583.tar.gz
Backport of the pieces of trunk rev 46589 relevant to
fixing an unlikely crash bug in dict resizing, SF bug 1456209. The rest of rev 46589 changes whether Python suppresses exceptions during some dict-related comparisons. While I think that's a good idea, it does change visible behavior at times, and there was already some complaining about that on the trunk. Not a good idea for backporting. The part of 46589 checked in here can at worst stop segfaults, and I doubt anyone will gripe about that ;-)
Diffstat (limited to 'Objects')
-rw-r--r--Objects/dictobject.c32
1 files changed, 31 insertions, 1 deletions
diff --git a/Objects/dictobject.c b/Objects/dictobject.c
index 18d8d5c1af..b466abdcf0 100644
--- a/Objects/dictobject.c
+++ b/Objects/dictobject.c
@@ -418,6 +418,35 @@ insertdict(register dictobject *mp, PyObject *key, long hash, PyObject *value)
}
/*
+Internal routine used by dictresize() to insert an item which is
+known to be absent from the dict. This routine also assumes that
+the dict contains no deleted entries. Besides the performance benefit,
+using insertdict() in dictresize() is dangerous (SF bug #1456209).
+*/
+static void
+insertdict_clean(register dictobject *mp, PyObject *key, long hash,
+ PyObject *value)
+{
+ register unsigned int i;
+ register unsigned int perturb;
+ register unsigned int mask = mp->ma_mask;
+ dictentry *ep0 = mp->ma_table;
+ register dictentry *ep;
+
+ i = hash & mask;
+ ep = &ep0[i];
+ for (perturb = hash; ep->me_key != NULL; perturb >>= PERTURB_SHIFT) {
+ i = (i << 2) + i + perturb + 1;
+ ep = &ep0[i & mask];
+ }
+ mp->ma_fill++;
+ ep->me_key = key;
+ ep->me_hash = hash;
+ ep->me_value = value;
+ mp->ma_used++;
+}
+
+/*
Restructure the table by allocating a new table and reinserting all
items again. When entries have been deleted, the new table may
actually be smaller than the old one.
@@ -489,7 +518,8 @@ dictresize(dictobject *mp, int minused)
for (ep = oldtable; i > 0; ep++) {
if (ep->me_value != NULL) { /* active entry */
--i;
- insertdict(mp, ep->me_key, ep->me_hash, ep->me_value);
+ insertdict_clean(mp, ep->me_key, ep->me_hash,
+ ep->me_value);
}
else if (ep->me_key != NULL) { /* dummy entry */
--i;