Port Armin's fix for a dict resize vulnerability (svn revision 46589, sf bug 1456209).

This commit is contained in:
Raymond Hettinger 2006-12-08 04:24:33 +00:00
parent f31e17509a
commit 0c850863a2
1 changed files with 31 additions and 6 deletions

View File

@ -185,7 +185,7 @@ set_lookkey_string(PySetObject *so, PyObject *key, register long hash)
/* /*
Internal routine to insert a new key into the table. Internal routine to insert a new key into the table.
Used both by the internal resize routine and by the public insert routine. Used by the public insert routine.
Eats a reference to key. Eats a reference to key.
*/ */
static int static int
@ -217,6 +217,35 @@ set_insert_key(register PySetObject *so, PyObject *key, long hash)
return 0; return 0;
} }
/*
Internal routine used by set_table_resize() to insert an item which is
known to be absent from the set. This routine also assumes that
the set contains no deleted entries. Besides the performance benefit,
using set_insert_clean() in set_table_resize() is dangerous (SF bug #1456209).
Note that no refcounts are changed by this routine; if needed, the caller
is responsible for incref'ing `key`.
*/
static void
set_insert_clean(register PySetObject *so, PyObject *key, long hash)
{
register size_t i;
register size_t perturb;
register size_t mask = (size_t)so->mask;
setentry *table = so->table;
register setentry *entry;
i = hash & mask;
entry = &table[i];
for (perturb = hash; entry->key != NULL; perturb >>= PERTURB_SHIFT) {
i = (i << 2) + i + perturb + 1;
entry = &table[i & mask];
}
so->fill++;
entry->key = key;
entry->hash = hash;
so->used++;
}
/* /*
Restructure the table by allocating a new table and reinserting all Restructure the table by allocating a new table and reinserting all
keys again. When entries have been deleted, the new table may keys again. When entries have been deleted, the new table may
@ -298,11 +327,7 @@ set_table_resize(PySetObject *so, Py_ssize_t minused)
} else { } else {
/* ACTIVE */ /* ACTIVE */
--i; --i;
if(set_insert_key(so, entry->key, entry->hash) == -1) { set_insert_clean(so, entry->key, entry->hash);
if (is_oldtable_malloced)
PyMem_DEL(oldtable);
return -1;
}
} }
} }