Skip to content

Commit 9dbb09f

Browse files
miss-islingtonRémi Lapeyre
authored andcommitted
bpo-36218: Fix handling of heterogeneous values in list.sort (GH-12209) GH-12532)
(cherry picked from commit dd5417a) Co-authored-by: Rémi Lapeyre <remi.lapeyre@henki.fr>
1 parent 0e05d8a commit 9dbb09f

File tree

3 files changed

+29
-11
lines changed

3 files changed

+29
-11
lines changed

Lib/test/test_sort.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -373,6 +373,11 @@ def test_unsafe_tuple_compare(self):
373373
check_against_PyObject_RichCompareBool(self, [float('nan')]*100)
374374
check_against_PyObject_RichCompareBool(self, [float('nan') for
375375
_ in range(100)])
376+
377+
def test_not_all_tuples(self):
378+
self.assertRaises(TypeError, [(1.0, 1.0), (False, "A"), 6].sort)
379+
self.assertRaises(TypeError, [('a', 1), (1, 'a')].sort)
380+
self.assertRaises(TypeError, [(1, 'a'), ('a', 1)].sort)
376381
#==============================================================================
377382

378383
if __name__ == "__main__":
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Fix a segfault occuring when sorting a list of heterogeneous values. Patch
2+
contributed by Rémi Lapeyre and Elliot Gorokhovsky.

Objects/listobject.c

Lines changed: 22 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -2250,19 +2250,28 @@ list_sort_impl(PyListObject *self, PyObject *keyfunc, int reverse)
22502250

22512251
if (key->ob_type != key_type) {
22522252
keys_are_all_same_type = 0;
2253-
break;
2253+
/* If keys are in tuple we must loop over the whole list to make
2254+
sure all items are tuples */
2255+
if (!keys_are_in_tuples) {
2256+
break;
2257+
}
22542258
}
22552259

2256-
if (key_type == &PyLong_Type) {
2257-
if (ints_are_bounded && Py_ABS(Py_SIZE(key)) > 1)
2260+
if (keys_are_all_same_type) {
2261+
if (key_type == &PyLong_Type &&
2262+
ints_are_bounded &&
2263+
Py_ABS(Py_SIZE(key)) > 1) {
2264+
22582265
ints_are_bounded = 0;
2266+
}
2267+
else if (key_type == &PyUnicode_Type &&
2268+
strings_are_latin &&
2269+
PyUnicode_KIND(key) != PyUnicode_1BYTE_KIND) {
2270+
2271+
strings_are_latin = 0;
2272+
}
2273+
}
22592274
}
2260-
else if (key_type == &PyUnicode_Type){
2261-
if (strings_are_latin &&
2262-
PyUnicode_KIND(key) != PyUnicode_1BYTE_KIND)
2263-
strings_are_latin = 0;
2264-
}
2265-
}
22662275

22672276
/* Choose the best compare, given what we now know about the keys. */
22682277
if (keys_are_all_same_type) {
@@ -2290,10 +2299,12 @@ list_sort_impl(PyListObject *self, PyObject *keyfunc, int reverse)
22902299
if (keys_are_in_tuples) {
22912300
/* Make sure we're not dealing with tuples of tuples
22922301
* (remember: here, key_type refers list [key[0] for key in keys]) */
2293-
if (key_type == &PyTuple_Type)
2302+
if (key_type == &PyTuple_Type) {
22942303
ms.tuple_elem_compare = safe_object_compare;
2295-
else
2304+
}
2305+
else {
22962306
ms.tuple_elem_compare = ms.key_compare;
2307+
}
22972308

22982309
ms.key_compare = unsafe_tuple_compare;
22992310
}

0 commit comments

Comments
 (0)