diff options
| author | Tim Peters <tim.peters@gmail.com> | 2006-10-09 20:24:45 +0000 |
|---|---|---|
| committer | Tim Peters <tim.peters@gmail.com> | 2006-10-09 20:24:45 +0000 |
| commit | 2b37ea40871ec45cb1fb6d98a2696bcaf4cf6583 (patch) | |
| tree | c613bfebac501d6a94b922da81cba5070be00ab1 /Objects | |
| parent | b8f82e6febddbd534e0f08ab480367561daa0717 (diff) | |
| download | cpython-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.c | 32 |
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; |
