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.
This commit is contained in:
Victor Stinner 2018-10-26 18:47:15 +02:00 committed by GitHub
parent 0862505a03
commit 50fe3f8913
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 64 additions and 52 deletions

View File

@ -439,6 +439,8 @@ static PyObject *empty_values[1] = { NULL };
static int static int
_PyDict_CheckConsistency(PyDictObject *mp) _PyDict_CheckConsistency(PyDictObject *mp)
{ {
#define ASSERT(expr) _PyObject_ASSERT((PyObject *)mp, (expr))
PyDictKeysObject *keys = mp->ma_keys; PyDictKeysObject *keys = mp->ma_keys;
int splitted = _PyDict_HasSplitTable(mp); int splitted = _PyDict_HasSplitTable(mp);
Py_ssize_t usable = USABLE_FRACTION(keys->dk_size); Py_ssize_t usable = USABLE_FRACTION(keys->dk_size);
@ -447,23 +449,23 @@ _PyDict_CheckConsistency(PyDictObject *mp)
Py_ssize_t i; Py_ssize_t i;
#endif #endif
assert(0 <= mp->ma_used && mp->ma_used <= usable); ASSERT(0 <= mp->ma_used && mp->ma_used <= usable);
assert(IS_POWER_OF_2(keys->dk_size)); ASSERT(IS_POWER_OF_2(keys->dk_size));
assert(0 <= keys->dk_usable ASSERT(0 <= keys->dk_usable
&& keys->dk_usable <= usable); && keys->dk_usable <= usable);
assert(0 <= keys->dk_nentries ASSERT(0 <= keys->dk_nentries
&& keys->dk_nentries <= usable); && keys->dk_nentries <= usable);
assert(keys->dk_usable + keys->dk_nentries <= usable); ASSERT(keys->dk_usable + keys->dk_nentries <= usable);
if (!splitted) { if (!splitted) {
/* combined table */ /* combined table */
assert(keys->dk_refcnt == 1); ASSERT(keys->dk_refcnt == 1);
} }
#ifdef DEBUG_PYDICT #ifdef DEBUG_PYDICT
for (i=0; i < keys->dk_size; i++) { for (i=0; i < keys->dk_size; i++) {
Py_ssize_t ix = dk_get_index(keys, 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++) { for (i=0; i < usable; i++) {
@ -473,32 +475,34 @@ _PyDict_CheckConsistency(PyDictObject *mp)
if (key != NULL) { if (key != NULL) {
if (PyUnicode_CheckExact(key)) { if (PyUnicode_CheckExact(key)) {
Py_hash_t hash = ((PyASCIIObject *)key)->hash; Py_hash_t hash = ((PyASCIIObject *)key)->hash;
assert(hash != -1); ASSERT(hash != -1);
assert(entry->me_hash == hash); ASSERT(entry->me_hash == hash);
} }
else { else {
/* test_dict fails if PyObject_Hash() is called again */ /* test_dict fails if PyObject_Hash() is called again */
assert(entry->me_hash != -1); ASSERT(entry->me_hash != -1);
} }
if (!splitted) { if (!splitted) {
assert(entry->me_value != NULL); ASSERT(entry->me_value != NULL);
} }
} }
if (splitted) { if (splitted) {
assert(entry->me_value == NULL); ASSERT(entry->me_value == NULL);
} }
} }
if (splitted) { if (splitted) {
/* splitted table */ /* splitted table */
for (i=0; i < mp->ma_used; i++) { for (i=0; i < mp->ma_used; i++) {
assert(mp->ma_values[i] != NULL); ASSERT(mp->ma_values[i] != NULL);
} }
} }
#endif #endif
return 1; return 1;
#undef ASSERT
} }
#endif #endif

View File

@ -134,15 +134,19 @@ skip_signature(const char *doc)
static int static int
_PyType_CheckConsistency(PyTypeObject *type) _PyType_CheckConsistency(PyTypeObject *type)
{ {
#define ASSERT(expr) _PyObject_ASSERT((PyObject *)type, (expr))
if (!(type->tp_flags & Py_TPFLAGS_READY)) { if (!(type->tp_flags & Py_TPFLAGS_READY)) {
/* don't check types before PyType_Ready() */ /* don't check types before PyType_Ready() */
return 1; return 1;
} }
assert(!(type->tp_flags & Py_TPFLAGS_READYING)); ASSERT(!(type->tp_flags & Py_TPFLAGS_READYING));
assert(type->tp_mro != NULL && PyTuple_Check(type->tp_mro)); ASSERT(type->tp_mro != NULL && PyTuple_Check(type->tp_mro));
assert(type->tp_dict != NULL); ASSERT(type->tp_dict != NULL);
return 1; return 1;
#undef ASSERT
} }
#endif #endif

View File

@ -363,17 +363,19 @@ PyUnicode_GetMax(void)
int int
_PyUnicode_CheckConsistency(PyObject *op, int check_content) _PyUnicode_CheckConsistency(PyObject *op, int check_content)
{ {
#define ASSERT(expr) _PyObject_ASSERT(op, (expr))
PyASCIIObject *ascii; PyASCIIObject *ascii;
unsigned int kind; unsigned int kind;
assert(PyUnicode_Check(op)); ASSERT(PyUnicode_Check(op));
ascii = (PyASCIIObject *)op; ascii = (PyASCIIObject *)op;
kind = ascii->state.kind; kind = ascii->state.kind;
if (ascii->state.ascii == 1 && ascii->state.compact == 1) { if (ascii->state.ascii == 1 && ascii->state.compact == 1) {
assert(kind == PyUnicode_1BYTE_KIND); ASSERT(kind == PyUnicode_1BYTE_KIND);
assert(ascii->state.ready == 1); ASSERT(ascii->state.ready == 1);
} }
else { else {
PyCompactUnicodeObject *compact = (PyCompactUnicodeObject *)op; PyCompactUnicodeObject *compact = (PyCompactUnicodeObject *)op;
@ -381,41 +383,41 @@ _PyUnicode_CheckConsistency(PyObject *op, int check_content)
if (ascii->state.compact == 1) { if (ascii->state.compact == 1) {
data = compact + 1; data = compact + 1;
assert(kind == PyUnicode_1BYTE_KIND ASSERT(kind == PyUnicode_1BYTE_KIND
|| kind == PyUnicode_2BYTE_KIND || kind == PyUnicode_2BYTE_KIND
|| kind == PyUnicode_4BYTE_KIND); || kind == PyUnicode_4BYTE_KIND);
assert(ascii->state.ascii == 0); ASSERT(ascii->state.ascii == 0);
assert(ascii->state.ready == 1); ASSERT(ascii->state.ready == 1);
assert (compact->utf8 != data); ASSERT (compact->utf8 != data);
} }
else { else {
PyUnicodeObject *unicode = (PyUnicodeObject *)op; PyUnicodeObject *unicode = (PyUnicodeObject *)op;
data = unicode->data.any; data = unicode->data.any;
if (kind == PyUnicode_WCHAR_KIND) { if (kind == PyUnicode_WCHAR_KIND) {
assert(ascii->length == 0); ASSERT(ascii->length == 0);
assert(ascii->hash == -1); ASSERT(ascii->hash == -1);
assert(ascii->state.compact == 0); ASSERT(ascii->state.compact == 0);
assert(ascii->state.ascii == 0); ASSERT(ascii->state.ascii == 0);
assert(ascii->state.ready == 0); ASSERT(ascii->state.ready == 0);
assert(ascii->state.interned == SSTATE_NOT_INTERNED); ASSERT(ascii->state.interned == SSTATE_NOT_INTERNED);
assert(ascii->wstr != NULL); ASSERT(ascii->wstr != NULL);
assert(data == NULL); ASSERT(data == NULL);
assert(compact->utf8 == NULL); ASSERT(compact->utf8 == NULL);
} }
else { else {
assert(kind == PyUnicode_1BYTE_KIND ASSERT(kind == PyUnicode_1BYTE_KIND
|| kind == PyUnicode_2BYTE_KIND || kind == PyUnicode_2BYTE_KIND
|| kind == PyUnicode_4BYTE_KIND); || kind == PyUnicode_4BYTE_KIND);
assert(ascii->state.compact == 0); ASSERT(ascii->state.compact == 0);
assert(ascii->state.ready == 1); ASSERT(ascii->state.ready == 1);
assert(data != NULL); ASSERT(data != NULL);
if (ascii->state.ascii) { if (ascii->state.ascii) {
assert (compact->utf8 == data); ASSERT (compact->utf8 == data);
assert (compact->utf8_length == ascii->length); ASSERT (compact->utf8_length == ascii->length);
} }
else else
assert (compact->utf8 != data); ASSERT (compact->utf8 != data);
} }
} }
if (kind != PyUnicode_WCHAR_KIND) { if (kind != PyUnicode_WCHAR_KIND) {
@ -427,16 +429,16 @@ _PyUnicode_CheckConsistency(PyObject *op, int check_content)
#endif #endif
) )
{ {
assert(ascii->wstr == data); ASSERT(ascii->wstr == data);
assert(compact->wstr_length == ascii->length); ASSERT(compact->wstr_length == ascii->length);
} else } else
assert(ascii->wstr != data); ASSERT(ascii->wstr != data);
} }
if (compact->utf8 == NULL) if (compact->utf8 == NULL)
assert(compact->utf8_length == 0); ASSERT(compact->utf8_length == 0);
if (ascii->wstr == NULL) if (ascii->wstr == NULL)
assert(compact->wstr_length == 0); ASSERT(compact->wstr_length == 0);
} }
/* check that the best kind is used */ /* check that the best kind is used */
if (check_content && kind != PyUnicode_WCHAR_KIND) if (check_content && kind != PyUnicode_WCHAR_KIND)
@ -455,23 +457,25 @@ _PyUnicode_CheckConsistency(PyObject *op, int check_content)
} }
if (kind == PyUnicode_1BYTE_KIND) { if (kind == PyUnicode_1BYTE_KIND) {
if (ascii->state.ascii == 0) { if (ascii->state.ascii == 0) {
assert(maxchar >= 128); ASSERT(maxchar >= 128);
assert(maxchar <= 255); ASSERT(maxchar <= 255);
} }
else else
assert(maxchar < 128); ASSERT(maxchar < 128);
} }
else if (kind == PyUnicode_2BYTE_KIND) { else if (kind == PyUnicode_2BYTE_KIND) {
assert(maxchar >= 0x100); ASSERT(maxchar >= 0x100);
assert(maxchar <= 0xFFFF); ASSERT(maxchar <= 0xFFFF);
} }
else { else {
assert(maxchar >= 0x10000); ASSERT(maxchar >= 0x10000);
assert(maxchar <= MAX_UNICODE); ASSERT(maxchar <= MAX_UNICODE);
} }
assert(PyUnicode_READ(kind, data, ascii->length) == 0); ASSERT(PyUnicode_READ(kind, data, ascii->length) == 0);
} }
return 1; return 1;
#undef ASSERT
} }
#endif #endif