@@ -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. */
28672887static int
28682888unsafe_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