From 50fe3f8913c503e63f4cfb8ddcf8641ef7ad0722 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Fri, 26 Oct 2018 18:47:15 +0200 Subject: [PATCH] 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. --- Objects/dictobject.c | 30 +++++++++------- Objects/typeobject.c | 10 ++++-- Objects/unicodeobject.c | 76 ++++++++++++++++++++++------------------- 3 files changed, 64 insertions(+), 52 deletions(-) diff --git a/Objects/dictobject.c b/Objects/dictobject.c index 370895d6bc..ee656953e0 100644 --- a/Objects/dictobject.c +++ b/Objects/dictobject.c @@ -439,6 +439,8 @@ static PyObject *empty_values[1] = { NULL }; 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 @@ _PyDict_CheckConsistency(PyDictObject *mp) 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 @@ _PyDict_CheckConsistency(PyDictObject *mp) 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 3b70e6952e..8e91e33d2d 100644 --- a/Objects/typeobject.c +++ b/Objects/typeobject.c @@ -134,15 +134,19 @@ skip_signature(const char *doc) 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 31703d37dd..f3f940ac9e 100644 --- a/Objects/unicodeobject.c +++ b/Objects/unicodeobject.c @@ -363,17 +363,19 @@ PyUnicode_GetMax(void) 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 @@ _PyUnicode_CheckConsistency(PyObject *op, int check_content) 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 @@ _PyUnicode_CheckConsistency(PyObject *op, int check_content) #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 @@ _PyUnicode_CheckConsistency(PyObject *op, int check_content) } 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 -- 2.40.0