Skip to content

Commit dd5417a

Browse files
Rémi Lapeyrerhettinger
authored andcommitted
bpo-36218: Fix handling of heterogeneous values in list.sort (GH-12209)
1 parent 9dcc095 commit dd5417a

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
@@ -2306,19 +2306,28 @@ list_sort_impl(PyListObject *self, PyObject *keyfunc, int reverse)
23062306

23072307
if (key->ob_type != key_type) {
23082308
keys_are_all_same_type = 0;
2309-
break;
2309+
/* If keys are in tuple we must loop over the whole list to make
2310+
sure all items are tuples */
2311+
if (!keys_are_in_tuples) {
2312+
break;
2313+
}
23102314
}
23112315

2312-
if (key_type == &PyLong_Type) {
2313-
if (ints_are_bounded && Py_ABS(Py_SIZE(key)) > 1)
2316+
if (keys_are_all_same_type) {
2317+
if (key_type == &PyLong_Type &&
2318+
ints_are_bounded &&
2319+
Py_ABS(Py_SIZE(key)) > 1) {
2320+
23142321
ints_are_bounded = 0;
2322+
}
2323+
else if (key_type == &PyUnicode_Type &&
2324+
strings_are_latin &&
2325+
PyUnicode_KIND(key) != PyUnicode_1BYTE_KIND) {
2326+
2327+
strings_are_latin = 0;
2328+
}
2329+
}
23152330
}
2316-
else if (key_type == &PyUnicode_Type){
2317-
if (strings_are_latin &&
2318-
PyUnicode_KIND(key) != PyUnicode_1BYTE_KIND)
2319-
strings_are_latin = 0;
2320-
}
2321-
}
23222331

23232332
/* Choose the best compare, given what we now know about the keys. */
23242333
if (keys_are_all_same_type) {
@@ -2346,10 +2355,12 @@ list_sort_impl(PyListObject *self, PyObject *keyfunc, int reverse)
23462355
if (keys_are_in_tuples) {
23472356
/* Make sure we're not dealing with tuples of tuples
23482357
* (remember: here, key_type refers list [key[0] for key in keys]) */
2349-
if (key_type == &PyTuple_Type)
2358+
if (key_type == &PyTuple_Type) {
23502359
ms.tuple_elem_compare = safe_object_compare;
2351-
else
2360+
}
2361+
else {
23522362
ms.tuple_elem_compare = ms.key_compare;
2363+
}
23532364

23542365
ms.key_compare = unsafe_tuple_compare;
23552366
}

0 commit comments

Comments
 (0)