bpo-38588: Fix possible crashes in dict and list when calling PyObject_RichCompareBool (GH-17734)
Take strong references before calling PyObject_RichCompareBool to protect against the case where the object dies during the call.
This commit is contained in:
parent
ee9ff05ec2
commit
2d5bf568ea
|
@ -1221,7 +1221,7 @@ class DictTest(unittest.TestCase):
|
||||||
support.check_free_after_iterating(self, lambda d: iter(d.items()), dict)
|
support.check_free_after_iterating(self, lambda d: iter(d.items()), dict)
|
||||||
|
|
||||||
def test_equal_operator_modifying_operand(self):
|
def test_equal_operator_modifying_operand(self):
|
||||||
# test fix for seg fault reported in issue 27945 part 3.
|
# test fix for seg fault reported in bpo-27945 part 3.
|
||||||
class X():
|
class X():
|
||||||
def __del__(self):
|
def __del__(self):
|
||||||
dict_b.clear()
|
dict_b.clear()
|
||||||
|
@ -1237,6 +1237,16 @@ class DictTest(unittest.TestCase):
|
||||||
dict_b = {X(): X()}
|
dict_b = {X(): X()}
|
||||||
self.assertTrue(dict_a == dict_b)
|
self.assertTrue(dict_a == dict_b)
|
||||||
|
|
||||||
|
# test fix for seg fault reported in bpo-38588 part 1.
|
||||||
|
class Y:
|
||||||
|
def __eq__(self, other):
|
||||||
|
dict_d.clear()
|
||||||
|
return True
|
||||||
|
|
||||||
|
dict_c = {0: Y()}
|
||||||
|
dict_d = {0: set()}
|
||||||
|
self.assertTrue(dict_c == dict_d)
|
||||||
|
|
||||||
def test_fromkeys_operator_modifying_dict_operand(self):
|
def test_fromkeys_operator_modifying_dict_operand(self):
|
||||||
# test fix for seg fault reported in issue 27945 part 4a.
|
# test fix for seg fault reported in issue 27945 part 4a.
|
||||||
class X(int):
|
class X(int):
|
||||||
|
|
|
@ -163,6 +163,31 @@ class ListTest(list_tests.CommonTest):
|
||||||
with self.assertRaises(TypeError):
|
with self.assertRaises(TypeError):
|
||||||
(3,) + L([1,2])
|
(3,) + L([1,2])
|
||||||
|
|
||||||
|
def test_equal_operator_modifying_operand(self):
|
||||||
|
# test fix for seg fault reported in bpo-38588 part 2.
|
||||||
|
class X:
|
||||||
|
def __eq__(self,other) :
|
||||||
|
list2.clear()
|
||||||
|
return NotImplemented
|
||||||
|
|
||||||
|
class Y:
|
||||||
|
def __eq__(self, other):
|
||||||
|
list1.clear()
|
||||||
|
return NotImplemented
|
||||||
|
|
||||||
|
class Z:
|
||||||
|
def __eq__(self, other):
|
||||||
|
list3.clear()
|
||||||
|
return NotImplemented
|
||||||
|
|
||||||
|
list1 = [X()]
|
||||||
|
list2 = [Y()]
|
||||||
|
self.assertTrue(list1 == list2)
|
||||||
|
|
||||||
|
list3 = [Z()]
|
||||||
|
list4 = [1]
|
||||||
|
self.assertFalse(list3 == list4)
|
||||||
|
|
||||||
@cpython_only
|
@cpython_only
|
||||||
def test_preallocation(self):
|
def test_preallocation(self):
|
||||||
iterable = [0] * 10
|
iterable = [0] * 10
|
||||||
|
|
|
@ -0,0 +1,2 @@
|
||||||
|
Fix possible crashes in dict and list when calling
|
||||||
|
:c:func:`PyObject_RichCompareBool`.
|
|
@ -2777,9 +2777,11 @@ dict_equal(PyDictObject *a, PyDictObject *b)
|
||||||
return -1;
|
return -1;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
Py_INCREF(bval);
|
||||||
cmp = PyObject_RichCompareBool(aval, bval, Py_EQ);
|
cmp = PyObject_RichCompareBool(aval, bval, Py_EQ);
|
||||||
Py_DECREF(key);
|
Py_DECREF(key);
|
||||||
Py_DECREF(aval);
|
Py_DECREF(aval);
|
||||||
|
Py_DECREF(bval);
|
||||||
if (cmp <= 0) /* error or not equal */
|
if (cmp <= 0) /* error or not equal */
|
||||||
return cmp;
|
return cmp;
|
||||||
}
|
}
|
||||||
|
|
|
@ -2662,8 +2662,15 @@ list_richcompare(PyObject *v, PyObject *w, int op)
|
||||||
|
|
||||||
/* Search for the first index where items are different */
|
/* Search for the first index where items are different */
|
||||||
for (i = 0; i < Py_SIZE(vl) && i < Py_SIZE(wl); i++) {
|
for (i = 0; i < Py_SIZE(vl) && i < Py_SIZE(wl); i++) {
|
||||||
|
PyObject *vitem = vl->ob_item[i];
|
||||||
|
PyObject *witem = wl->ob_item[i];
|
||||||
|
|
||||||
|
Py_INCREF(vitem);
|
||||||
|
Py_INCREF(witem);
|
||||||
int k = PyObject_RichCompareBool(vl->ob_item[i],
|
int k = PyObject_RichCompareBool(vl->ob_item[i],
|
||||||
wl->ob_item[i], Py_EQ);
|
wl->ob_item[i], Py_EQ);
|
||||||
|
Py_DECREF(vitem);
|
||||||
|
Py_DECREF(witem);
|
||||||
if (k < 0)
|
if (k < 0)
|
||||||
return NULL;
|
return NULL;
|
||||||
if (!k)
|
if (!k)
|
||||||
|
|
Loading…
Reference in New Issue