Issue #24583: Fix crash when set is mutated while being updated.

This commit is contained in:
Raymond Hettinger 2015-07-15 23:54:02 -07:00
parent d702044bcd
commit 061091a7c5

View File

@ -127,7 +127,7 @@ set_lookkey(PySetObject *so, PyObject *key, Py_hash_t hash)
static int set_table_resize(PySetObject *, Py_ssize_t); static int set_table_resize(PySetObject *, Py_ssize_t);
static int static int
set_add_entry(PySetObject *so, PyObject *key, Py_hash_t hash) _set_add_entry(PySetObject *so, PyObject *key, Py_hash_t hash)
{ {
setentry *table = so->table; setentry *table = so->table;
setentry *freeslot; setentry *freeslot;
@ -162,7 +162,7 @@ set_add_entry(PySetObject *so, PyObject *key, Py_hash_t hash)
if (cmp < 0) /* unlikely */ if (cmp < 0) /* unlikely */
return -1; return -1;
if (table != so->table || entry->key != startkey) /* unlikely */ if (table != so->table || entry->key != startkey) /* unlikely */
return set_add_entry(so, key, hash); return _set_add_entry(so, key, hash);
if (cmp > 0) /* likely */ if (cmp > 0) /* likely */
goto found_active; goto found_active;
mask = so->mask; /* help avoid a register spill */ mask = so->mask; /* help avoid a register spill */
@ -190,7 +190,7 @@ set_add_entry(PySetObject *so, PyObject *key, Py_hash_t hash)
if (cmp < 0) if (cmp < 0)
return -1; return -1;
if (table != so->table || entry->key != startkey) if (table != so->table || entry->key != startkey)
return set_add_entry(so, key, hash); return _set_add_entry(so, key, hash);
if (cmp > 0) if (cmp > 0)
goto found_active; goto found_active;
mask = so->mask; mask = so->mask;
@ -211,14 +211,12 @@ set_add_entry(PySetObject *so, PyObject *key, Py_hash_t hash)
found_unused_or_dummy: found_unused_or_dummy:
if (freeslot == NULL) if (freeslot == NULL)
goto found_unused; goto found_unused;
Py_INCREF(key);
so->used++; so->used++;
freeslot->key = key; freeslot->key = key;
freeslot->hash = hash; freeslot->hash = hash;
return 0; return 0;
found_unused: found_unused:
Py_INCREF(key);
so->fill++; so->fill++;
so->used++; so->used++;
entry->key = key; entry->key = key;
@ -231,6 +229,16 @@ set_add_entry(PySetObject *so, PyObject *key, Py_hash_t hash)
return 0; return 0;
} }
static int
set_add_entry(PySetObject *so, PyObject *key, Py_hash_t hash)
{
Py_INCREF(key);
if (!_set_add_entry(so, key, hash))
return 0;
Py_DECREF(key);
return -1;
}
/* /*
Internal routine used by set_table_resize() to insert an item which is 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 known to be absent from the set. This routine also assumes that