bpo-9263: _PyXXX_CheckConsistency() use _PyObject_ASSERT() (GH-10108)

Use _PyObject_ASSERT() in:

* _PyDict_CheckConsistency()
* _PyType_CheckConsistency()
* _PyUnicode_CheckConsistency()

_PyObject_ASSERT() dumps the faulty object if the assertion fails
to help debugging.
diff --git a/Objects/dictobject.c b/Objects/dictobject.c
index 370895d..ee65695 100644
--- a/Objects/dictobject.c
+++ b/Objects/dictobject.c
@@ -439,6 +439,8 @@
 static int
 _PyDict_CheckConsistency(PyDictObject *mp)
 {
+#define ASSERT(expr) _PyObject_ASSERT((PyObject *)mp, (expr))
+
     PyDictKeysObject *keys = mp->ma_keys;
     int splitted = _PyDict_HasSplitTable(mp);
     Py_ssize_t usable = USABLE_FRACTION(keys->dk_size);
@@ -447,23 +449,23 @@
     Py_ssize_t i;
 #endif
 
-    assert(0 <= mp->ma_used && mp->ma_used <= usable);
-    assert(IS_POWER_OF_2(keys->dk_size));
-    assert(0 <= keys->dk_usable
+    ASSERT(0 <= mp->ma_used && mp->ma_used <= usable);
+    ASSERT(IS_POWER_OF_2(keys->dk_size));
+    ASSERT(0 <= keys->dk_usable
            && keys->dk_usable <= usable);
-    assert(0 <= keys->dk_nentries
+    ASSERT(0 <= keys->dk_nentries
            && keys->dk_nentries <= usable);
-    assert(keys->dk_usable + keys->dk_nentries <= usable);
+    ASSERT(keys->dk_usable + keys->dk_nentries <= usable);
 
     if (!splitted) {
         /* combined table */
-        assert(keys->dk_refcnt == 1);
+        ASSERT(keys->dk_refcnt == 1);
     }
 
 #ifdef DEBUG_PYDICT
     for (i=0; i < keys->dk_size; i++) {
         Py_ssize_t ix = dk_get_index(keys, i);
-        assert(DKIX_DUMMY <= ix && ix <= usable);
+        ASSERT(DKIX_DUMMY <= ix && ix <= usable);
     }
 
     for (i=0; i < usable; i++) {
@@ -473,32 +475,34 @@
         if (key != NULL) {
             if (PyUnicode_CheckExact(key)) {
                 Py_hash_t hash = ((PyASCIIObject *)key)->hash;
-                assert(hash != -1);
-                assert(entry->me_hash == hash);
+                ASSERT(hash != -1);
+                ASSERT(entry->me_hash == hash);
             }
             else {
                 /* test_dict fails if PyObject_Hash() is called again */
-                assert(entry->me_hash != -1);
+                ASSERT(entry->me_hash != -1);
             }
             if (!splitted) {
-                assert(entry->me_value != NULL);
+                ASSERT(entry->me_value != NULL);
             }
         }
 
         if (splitted) {
-            assert(entry->me_value == NULL);
+            ASSERT(entry->me_value == NULL);
         }
     }
 
     if (splitted) {
         /* splitted table */
         for (i=0; i < mp->ma_used; i++) {
-            assert(mp->ma_values[i] != NULL);
+            ASSERT(mp->ma_values[i] != NULL);
         }
     }
 #endif
 
     return 1;
+
+#undef ASSERT
 }
 #endif
 
diff --git a/Objects/typeobject.c b/Objects/typeobject.c
index 3b70e69..8e91e33 100644
--- a/Objects/typeobject.c
+++ b/Objects/typeobject.c
@@ -134,15 +134,19 @@
 static int
 _PyType_CheckConsistency(PyTypeObject *type)
 {
+#define ASSERT(expr) _PyObject_ASSERT((PyObject *)type, (expr))
+
     if (!(type->tp_flags & Py_TPFLAGS_READY)) {
         /* don't check types before PyType_Ready() */
         return 1;
     }
 
-    assert(!(type->tp_flags & Py_TPFLAGS_READYING));
-    assert(type->tp_mro != NULL && PyTuple_Check(type->tp_mro));
-    assert(type->tp_dict != NULL);
+    ASSERT(!(type->tp_flags & Py_TPFLAGS_READYING));
+    ASSERT(type->tp_mro != NULL && PyTuple_Check(type->tp_mro));
+    ASSERT(type->tp_dict != NULL);
     return 1;
+
+#undef ASSERT
 }
 #endif
 
diff --git a/Objects/unicodeobject.c b/Objects/unicodeobject.c
index 31703d3..f3f940a 100644
--- a/Objects/unicodeobject.c
+++ b/Objects/unicodeobject.c
@@ -363,17 +363,19 @@
 int
 _PyUnicode_CheckConsistency(PyObject *op, int check_content)
 {
+#define ASSERT(expr) _PyObject_ASSERT(op, (expr))
+
     PyASCIIObject *ascii;
     unsigned int kind;
 
-    assert(PyUnicode_Check(op));
+    ASSERT(PyUnicode_Check(op));
 
     ascii = (PyASCIIObject *)op;
     kind = ascii->state.kind;
 
     if (ascii->state.ascii == 1 && ascii->state.compact == 1) {
-        assert(kind == PyUnicode_1BYTE_KIND);
-        assert(ascii->state.ready == 1);
+        ASSERT(kind == PyUnicode_1BYTE_KIND);
+        ASSERT(ascii->state.ready == 1);
     }
     else {
         PyCompactUnicodeObject *compact = (PyCompactUnicodeObject *)op;
@@ -381,41 +383,41 @@
 
         if (ascii->state.compact == 1) {
             data = compact + 1;
-            assert(kind == PyUnicode_1BYTE_KIND
+            ASSERT(kind == PyUnicode_1BYTE_KIND
                    || kind == PyUnicode_2BYTE_KIND
                    || kind == PyUnicode_4BYTE_KIND);
-            assert(ascii->state.ascii == 0);
-            assert(ascii->state.ready == 1);
-            assert (compact->utf8 != data);
+            ASSERT(ascii->state.ascii == 0);
+            ASSERT(ascii->state.ready == 1);
+            ASSERT (compact->utf8 != data);
         }
         else {
             PyUnicodeObject *unicode = (PyUnicodeObject *)op;
 
             data = unicode->data.any;
             if (kind == PyUnicode_WCHAR_KIND) {
-                assert(ascii->length == 0);
-                assert(ascii->hash == -1);
-                assert(ascii->state.compact == 0);
-                assert(ascii->state.ascii == 0);
-                assert(ascii->state.ready == 0);
-                assert(ascii->state.interned == SSTATE_NOT_INTERNED);
-                assert(ascii->wstr != NULL);
-                assert(data == NULL);
-                assert(compact->utf8 == NULL);
+                ASSERT(ascii->length == 0);
+                ASSERT(ascii->hash == -1);
+                ASSERT(ascii->state.compact == 0);
+                ASSERT(ascii->state.ascii == 0);
+                ASSERT(ascii->state.ready == 0);
+                ASSERT(ascii->state.interned == SSTATE_NOT_INTERNED);
+                ASSERT(ascii->wstr != NULL);
+                ASSERT(data == NULL);
+                ASSERT(compact->utf8 == NULL);
             }
             else {
-                assert(kind == PyUnicode_1BYTE_KIND
+                ASSERT(kind == PyUnicode_1BYTE_KIND
                        || kind == PyUnicode_2BYTE_KIND
                        || kind == PyUnicode_4BYTE_KIND);
-                assert(ascii->state.compact == 0);
-                assert(ascii->state.ready == 1);
-                assert(data != NULL);
+                ASSERT(ascii->state.compact == 0);
+                ASSERT(ascii->state.ready == 1);
+                ASSERT(data != NULL);
                 if (ascii->state.ascii) {
-                    assert (compact->utf8 == data);
-                    assert (compact->utf8_length == ascii->length);
+                    ASSERT (compact->utf8 == data);
+                    ASSERT (compact->utf8_length == ascii->length);
                 }
                 else
-                    assert (compact->utf8 != data);
+                    ASSERT (compact->utf8 != data);
             }
         }
         if (kind != PyUnicode_WCHAR_KIND) {
@@ -427,16 +429,16 @@
 #endif
                )
             {
-                assert(ascii->wstr == data);
-                assert(compact->wstr_length == ascii->length);
+                ASSERT(ascii->wstr == data);
+                ASSERT(compact->wstr_length == ascii->length);
             } else
-                assert(ascii->wstr != data);
+                ASSERT(ascii->wstr != data);
         }
 
         if (compact->utf8 == NULL)
-            assert(compact->utf8_length == 0);
+            ASSERT(compact->utf8_length == 0);
         if (ascii->wstr == NULL)
-            assert(compact->wstr_length == 0);
+            ASSERT(compact->wstr_length == 0);
     }
     /* check that the best kind is used */
     if (check_content && kind != PyUnicode_WCHAR_KIND)
@@ -455,23 +457,25 @@
         }
         if (kind == PyUnicode_1BYTE_KIND) {
             if (ascii->state.ascii == 0) {
-                assert(maxchar >= 128);
-                assert(maxchar <= 255);
+                ASSERT(maxchar >= 128);
+                ASSERT(maxchar <= 255);
             }
             else
-                assert(maxchar < 128);
+                ASSERT(maxchar < 128);
         }
         else if (kind == PyUnicode_2BYTE_KIND) {
-            assert(maxchar >= 0x100);
-            assert(maxchar <= 0xFFFF);
+            ASSERT(maxchar >= 0x100);
+            ASSERT(maxchar <= 0xFFFF);
         }
         else {
-            assert(maxchar >= 0x10000);
-            assert(maxchar <= MAX_UNICODE);
+            ASSERT(maxchar >= 0x10000);
+            ASSERT(maxchar <= MAX_UNICODE);
         }
-        assert(PyUnicode_READ(kind, data, ascii->length) == 0);
+        ASSERT(PyUnicode_READ(kind, data, ascii->length) == 0);
     }
     return 1;
+
+#undef ASSERT
 }
 #endif