https://github.com/python/cpython/commit/a13d6dbe0375670941fa5830aa44fc1df4986947
commit: a13d6dbe0375670941fa5830aa44fc1df4986947
branch: main
author: Asish Kumar <[email protected]>
committer: StanFromIreland <[email protected]>
date: 2026-10-21T18:12:42Z
summary:

gh-148268: Avoid debug assertion in specialized list compares (#148309)

Co-authored-by: Stan Ulbrych <[email protected]>

files:
M Objects/listobject.c

diff --git a/Objects/listobject.c b/Objects/listobject.c
index 37744b6972039f..fa251923dfd495 100644
--- a/Objects/listobject.c
+++ b/Objects/listobject.c
@@ -2863,6 +2863,26 @@ unsafe_object_compare(PyObject *v, PyObject *w, 
MergeState *ms)
     return res;
 }
 
+#ifndef NDEBUG
+static void
+assert_compare_consistent(PyObject *v, PyObject *w, int res)
+{
+    int cmp = PyObject_RichCompareBool(v, w, Py_LT);
+    if (cmp < 0) {
+        /* This debug-only cross-check can hit the C stack guard even when
+         * the specialized comparison itself is safe. Keep the optimized path
+         * side-effect free by discarding that exception.
+         */
+        assert(PyErr_ExceptionMatches(PyExc_RecursionError));
+        PyErr_Clear();
+        return;
+    }
+    assert(res == cmp);
+}
+#else
+#  define assert_compare_consistent(v, w, res) ((void)0)
+#endif
+
 /* Latin string compare: safe for any two latin (one byte per char) strings. */
 static int
 unsafe_latin_compare(PyObject *v, PyObject *w, MergeState *ms)
@@ -2883,7 +2903,7 @@ unsafe_latin_compare(PyObject *v, PyObject *w, MergeState 
*ms)
            res < 0 :
            PyUnicode_GET_LENGTH(v) < PyUnicode_GET_LENGTH(w));
 
-    assert(res == PyObject_RichCompareBool(v, w, Py_LT));;
+    assert_compare_consistent(v, w, res);
     return res;
 }
 
@@ -2908,7 +2928,7 @@ unsafe_long_compare(PyObject *v, PyObject *w, MergeState 
*ms)
     w0 = _PyLong_CompactValue(wl);
 
     res = v0 < w0;
-    assert(res == PyObject_RichCompareBool(v, w, Py_LT));
+    assert_compare_consistent(v, w, res);
     return res;
 }
 
@@ -2923,7 +2943,7 @@ unsafe_float_compare(PyObject *v, PyObject *w, MergeState 
*ms)
     assert(Py_IS_TYPE(w, &PyFloat_Type));
 
     res = PyFloat_AS_DOUBLE(v) < PyFloat_AS_DOUBLE(w);
-    assert(res == PyObject_RichCompareBool(v, w, Py_LT));
+    assert_compare_consistent(v, w, res);
     return res;
 }
 

_______________________________________________
Python-checkins mailing list -- [email protected]
To unsubscribe send an email to [email protected]
https://mail.python.org/mailman3//lists/python-checkins.python.org
Member address: [email protected]

Reply via email to