Skip to content

Commit a13d6db

Browse files
gh-148268: Avoid debug assertion in specialized list compares (#148309)
Co-authored-by: Stan Ulbrych <stan@python.org>
1 parent 65b7e94 commit a13d6db

1 file changed

Lines changed: 23 additions & 3 deletions

File tree

‎Objects/listobject.c‎

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2863,6 +2863,26 @@ unsafe_object_compare(PyObject *v, PyObject *w, MergeState *ms)
28632863
return res;
28642864
}
28652865

2866+
#ifndef NDEBUG
2867+
static void
2868+
assert_compare_consistent(PyObject *v, PyObject *w, int res)
2869+
{
2870+
int cmp = PyObject_RichCompareBool(v, w, Py_LT);
2871+
if (cmp < 0) {
2872+
/* This debug-only cross-check can hit the C stack guard even when
2873+
* the specialized comparison itself is safe. Keep the optimized path
2874+
* side-effect free by discarding that exception.
2875+
*/
2876+
assert(PyErr_ExceptionMatches(PyExc_RecursionError));
2877+
PyErr_Clear();
2878+
return;
2879+
}
2880+
assert(res == cmp);
2881+
}
2882+
#else
2883+
# define assert_compare_consistent(v, w, res) ((void)0)
2884+
#endif
2885+
28662886
/* Latin string compare: safe for any two latin (one byte per char) strings. */
28672887
static int
28682888
unsafe_latin_compare(PyObject *v, PyObject *w, MergeState *ms)
@@ -2883,7 +2903,7 @@ unsafe_latin_compare(PyObject *v, PyObject *w, MergeState *ms)
28832903
res < 0 :
28842904
PyUnicode_GET_LENGTH(v) < PyUnicode_GET_LENGTH(w));
28852905

2886-
assert(res == PyObject_RichCompareBool(v, w, Py_LT));;
2906+
assert_compare_consistent(v, w, res);
28872907
return res;
28882908
}
28892909

@@ -2908,7 +2928,7 @@ unsafe_long_compare(PyObject *v, PyObject *w, MergeState *ms)
29082928
w0 = _PyLong_CompactValue(wl);
29092929

29102930
res = v0 < w0;
2911-
assert(res == PyObject_RichCompareBool(v, w, Py_LT));
2931+
assert_compare_consistent(v, w, res);
29122932
return res;
29132933
}
29142934

@@ -2923,7 +2943,7 @@ unsafe_float_compare(PyObject *v, PyObject *w, MergeState *ms)
29232943
assert(Py_IS_TYPE(w, &PyFloat_Type));
29242944

29252945
res = PyFloat_AS_DOUBLE(v) < PyFloat_AS_DOUBLE(w);
2926-
assert(res == PyObject_RichCompareBool(v, w, Py_LT));
2946+
assert_compare_consistent(v, w, res);
29272947
return res;
29282948
}
29292949

0 commit comments

Comments
 (0)