Author: Armin Rigo <ar...@tunes.org> Branch: Changeset: r90062:943aa7094f15 Date: 2017-02-12 09:46 +0100 http://bitbucket.org/pypy/pypy/changeset/943aa7094f15/
Log: dict.pop() on a key with a strange __eq__ could crash pypy diff --git a/pypy/objspace/std/dictmultiobject.py b/pypy/objspace/std/dictmultiobject.py --- a/pypy/objspace/std/dictmultiobject.py +++ b/pypy/objspace/std/dictmultiobject.py @@ -237,6 +237,14 @@ except KeyError: space.raise_key_error(w_key) + def internal_delitem(self, w_key): + try: + self.delitem(w_key) + except KeyError: + raise oefmt(self.space.w_RuntimeError, + "an internal 'del' on the dictionary failed to find " + "the key") + def descr_reversed(self, space): raise oefmt(space.w_TypeError, "argument to reversed() must be a sequence") @@ -369,7 +377,7 @@ else: space.raise_key_error(w_key) else: - self.delitem(w_key) + self.internal_delitem(w_key) return w_item def descr_popitem(self, space): diff --git a/pypy/objspace/std/test/test_dictmultiobject.py b/pypy/objspace/std/test/test_dictmultiobject.py --- a/pypy/objspace/std/test/test_dictmultiobject.py +++ b/pypy/objspace/std/test/test_dictmultiobject.py @@ -735,6 +735,31 @@ setattr(a, s, 123) assert holder.seen is s + def test_internal_delitem(self): + class K: + def __hash__(self): + return 42 + def __eq__(self, other): + if is_equal[0]: + is_equal[0] -= 1 + return True + return False + is_equal = [0] + k1 = K() + k2 = K() + d = {k1: 1, k2: 2} + k3 = K() + is_equal = [1] + try: + x = d.pop(k3) + except RuntimeError: + # This used to give a Fatal RPython error: KeyError. + # Now at least it should raise an app-level RuntimeError, + # or just work. + assert len(d) == 2 + else: + assert (x == 1 or x == 2) and len(d) == 1 + class AppTestDictViews: def test_dictview(self): _______________________________________________ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit