Skip to content

Commit 14077db

Browse files
committed
gh-154817: Fix OrderedDict.pop() crash with inconsistent equality
1 parent 2ffab08 commit 14077db

2 files changed

Lines changed: 28 additions & 1 deletion

File tree

Lib/test/test_ordered_dict.py

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -281,6 +281,28 @@ def __missing__(self, key):
281281
with self.assertRaises(KeyError):
282282
m.pop('a')
283283

284+
def test_pop_inconsistent_eq(self):
285+
class K:
286+
def __init__(self):
287+
self.calls = 0
288+
289+
def __hash__(self):
290+
return 12345
291+
292+
# Behave inconsistently across repeated equality checks.
293+
def __eq__(self, other):
294+
self.calls += 1
295+
return self.calls == 1
296+
297+
k1 = K()
298+
k2 = K()
299+
300+
od = self.OrderedDict()
301+
od[k1] = "value"
302+
303+
with self.assertRaises(KeyError):
304+
od.pop(k2)
305+
284306
def test_equality(self):
285307
OrderedDict = self.OrderedDict
286308
pairs = [('c', 1), ('b', 2), ('a', 3), ('d', 4), ('e', 5), ('f', 6)]

Objects/odictobject.c

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1095,7 +1095,12 @@ _odict_popkey_hash(PyObject *od, PyObject *key, PyObject *failobj,
10951095
/* Now delete the value from the dict. */
10961096
if (_PyDict_Pop_KnownHash((PyDictObject *)od, key, hash,
10971097
&value) == 0) {
1098-
value = Py_NewRef(failobj);
1098+
if (failobj) {
1099+
value = Py_NewRef(failobj);
1100+
}
1101+
else {
1102+
PyErr_SetObject(PyExc_KeyError, key);
1103+
}
10991104
}
11001105
}
11011106
else if (value == NULL && !PyErr_Occurred()) {

0 commit comments

Comments
 (0)