diff --git a/Lib/test/test_set.py b/Lib/test/test_set.py index 9f96f875c5d2..54de508a832d 100644 --- a/Lib/test/test_set.py +++ b/Lib/test/test_set.py @@ -1742,6 +1742,19 @@ def test_iter_and_mutate(self): s.update(range(100)) list(si) + def test_merge_and_mutate(self): + class X: + def __hash__(self): + return hash(0) + def __eq__(self, o): + other.clear() + return False + + other = set() + other = {X() for i in range(10)} + s = {0} + s.update(other) + # Application tests (based on David Eppstein's graph recipes ==================================== def powerset(U): diff --git a/Misc/NEWS b/Misc/NEWS index 601b6e23fe3a..550435f0b7b3 100644 --- a/Misc/NEWS +++ b/Misc/NEWS @@ -34,6 +34,8 @@ Core and Builtins - Issue #24569: Make PEP 448 dictionary evaluation more consistent. +- Issue #24583: Fix crash when set is mutated while being updated. + - Issue #24407: Fix crash when dict is mutated while being updated. Library diff --git a/Objects/setobject.c b/Objects/setobject.c index e6fb46e6e24d..922c61968ef3 100644 --- a/Objects/setobject.c +++ b/Objects/setobject.c @@ -668,7 +668,8 @@ set_merge(PySetObject *so, PyObject *otherset) } /* We can't assure there are no duplicates, so do normal insertions */ - for (i = 0; i <= other->mask; i++, other_entry++) { + for (i = 0; i <= other->mask; i++) { + other_entry = &other->table[i]; key = other_entry->key; if (key != NULL && key != dummy) { if (set_add_entry(so, key, other_entry->hash))