New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Coverity Scan defects in new dict code #72229
Comments
Coverity Scan complains about 30 defects in the new code. Inada, I sent you an invite. 30 new defect(s) introduced to Python found with Coverity Scan. New defect(s) Reported-by: Coverity Scan ** CID 1372734: Memory - corruptions (OVERRUN) ________________________________________________________________________________________________________
*** CID 1372734: Memory - corruptions (OVERRUN)
/Objects/dictobject.c: 1133 in insertdict_clean()
1127 insertdict_clean(PyDictObject *mp, PyObject *key, Py_hash_t hash,
1128 PyObject *value)
1129 {
1130 size_t i, perturb;
1131 PyDictKeysObject *k = mp->ma_keys;
1132 size_t mask = (size_t)DK_SIZE(k)-1;
>>> CID 1372734: Memory - corruptions (OVERRUN)
>>> "&mp->ma_keys->dk_indices.as_1[mp->ma_keys->dk_size * ((mp->ma_keys->dk_size <= 255L) ? 1UL : ((mp->ma_keys->dk_size <= 65535L) ? 2UL : ((mp->ma_keys->dk_size <= 4294967295L) ? 4UL : 8UL)))]" evaluates to an address that is at byte offset 255 of an array of 8 bytes.
1133 PyDictKeyEntry *ep0 = DK_ENTRIES(mp->ma_keys);
1134 PyDictKeyEntry *ep;
1135
1136 assert(k->dk_lookup != NULL);
1137 assert(value != NULL);
1138 assert(key != NULL); ** CID 1372733: Memory - corruptions (OVERRUN) ________________________________________________________________________________________________________
*** CID 1372733: Memory - corruptions (OVERRUN)
/Objects/dictobject.c: 1557 in _PyDict_DelItem_KnownHash()
1551 mp->ma_used--;
1552 mp->ma_version_tag = DICT_NEXT_VERSION();
1553 if (_PyDict_HasSplitTable(mp)) {
1554 mp->ma_keys->dk_usable = 0;
1555 }
1556 else {
>>> CID 1372733: Memory - corruptions (OVERRUN)
>>> "&mp->ma_keys->dk_indices.as_1[mp->ma_keys->dk_size * ((mp->ma_keys->dk_size <= 255L) ? 1UL : ((mp->ma_keys->dk_size <= 65535L) ? 2UL : ((mp->ma_keys->dk_size <= 4294967295L) ? 4UL : 8UL)))]" evaluates to an address that is at byte offset 255 of an array of 8 bytes.
1557 ep = &DK_ENTRIES(mp->ma_keys)[ix];
1558 dk_set_index(mp->ma_keys, hashpos, DKIX_DUMMY);
1559 ENSURE_ALLOWS_DELETIONS(mp);
1560 old_key = ep->me_key;
1561 ep->me_key = NULL;
1562 Py_DECREF(old_key); ** CID 1372732: Memory - corruptions (OVERRUN) ________________________________________________________________________________________________________
*** CID 1372732: Memory - corruptions (OVERRUN)
/Objects/dictobject.c: 871 in lookdict_split()
865 lookdict_split(PyDictObject *mp, PyObject *key,
866 Py_hash_t hash, PyObject ***value_addr, Py_ssize_t *hashpos)
867 {
868 size_t i, perturb;
869 size_t mask = DK_MASK(mp->ma_keys);
870 Py_ssize_t ix;
>>> CID 1372732: Memory - corruptions (OVERRUN)
>>> "&mp->ma_keys->dk_indices.as_1[mp->ma_keys->dk_size * ((mp->ma_keys->dk_size <= 255L) ? 1UL : ((mp->ma_keys->dk_size <= 65535L) ? 2UL : ((mp->ma_keys->dk_size <= 4294967295L) ? 4UL : 8UL)))]" evaluates to an address that is at byte offset 255 of an array of 8 bytes.
871 PyDictKeyEntry *ep, *ep0 = DK_ENTRIES(mp->ma_keys);
872
873 /* mp must split table */
874 assert(mp->ma_values != NULL);
875 if (!PyUnicode_CheckExact(key)) {
876 ix = lookdict(mp, key, hash, value_addr, hashpos); ** CID 1372731: Memory - corruptions (OVERRUN) ________________________________________________________________________________________________________
*** CID 1372731: Memory - corruptions (OVERRUN)
/Objects/dictobject.c: 3433 in dictiter_iternextitem()
3427 } else {
3428 result = PyTuple_New(2);
3429 if (result == NULL)
3430 return NULL;
3431 }
3432 di->len--;
>>> CID 1372731: Memory - corruptions (OVERRUN)
>>> "&d->ma_keys->dk_indices.as_1[d->ma_keys->dk_size * ((d->ma_keys->dk_size <= 255L) ? 1UL : ((d->ma_keys->dk_size <= 65535L) ? 2UL : ((d->ma_keys->dk_size <= 4294967295L) ? 4UL : 8UL)))]" evaluates to an address that is at byte offset 255 of an array of 8 bytes.
3433 key = DK_ENTRIES(d->ma_keys)[i].me_key;
3434 value = *value_ptr;
3435 Py_INCREF(key);
3436 Py_INCREF(value);
3437 PyTuple_SET_ITEM(result, 0, key); /* steals reference */
3438 PyTuple_SET_ITEM(result, 1, value); /* steals reference */ ** CID 1372730: Memory - illegal accesses (OVERRUN) ________________________________________________________________________________________________________
*** CID 1372730: Memory - illegal accesses (OVERRUN)
/Objects/dictobject.c: 2333 in PyDict_Merge()
2327 return -1;
2328 ep0 = DK_ENTRIES(other->ma_keys);
2329 for (i = 0, n = other->ma_keys->dk_nentries; i < n; i++) {
2330 PyObject *key, *value;
2331 Py_hash_t hash;
2332 entry = &ep0[i];
>>> CID 1372730: Memory - illegal accesses (OVERRUN)
>>> Overrunning array of 8 bytes at byte offset 255 by dereferencing pointer "entry".
2333 key = entry->me_key;
2334 hash = entry->me_hash;
2335 if (other->ma_values)
2336 value = other->ma_values[i];
2337 else
2338 value = entry->me_value; ** CID 1372729: Memory - corruptions (OVERRUN) ________________________________________________________________________________________________________
*** CID 1372729: Memory - corruptions (OVERRUN)
/Objects/dictobject.c: 2756 in dict_popitem()
2750 return NULL;
2751 }
2752 }
2753 ENSURE_ALLOWS_DELETIONS(mp);
2754
2755 /* Pop last item */
>>> CID 1372729: Memory - corruptions (OVERRUN)
>>> "&mp->ma_keys->dk_indices.as_1[mp->ma_keys->dk_size * ((mp->ma_keys->dk_size <= 255L) ? 1UL : ((mp->ma_keys->dk_size <= 65535L) ? 2UL : ((mp->ma_keys->dk_size <= 4294967295L) ? 4UL : 8UL)))]" evaluates to an address that is at byte offset 255 of an array of 8 bytes.
2756 ep0 = DK_ENTRIES(mp->ma_keys);
2757 i = mp->ma_keys->dk_nentries - 1;
2758 while (i >= 0 && ep0[i].me_value == NULL) {
2759 i--;
2760 }
2761 assert(i >= 0); ** CID 1372728: Memory - corruptions (OVERRUN) ________________________________________________________________________________________________________
*** CID 1372728: Memory - corruptions (OVERRUN)
/Objects/dictobject.c: 1734 in _PyDict_Pop()
1728 old_value = *value_addr;
1729 *value_addr = NULL;
1730 mp->ma_used--;
1731 mp->ma_version_tag = DICT_NEXT_VERSION();
1732 if (!_PyDict_HasSplitTable(mp)) {
1733 dk_set_index(mp->ma_keys, hashpos, DKIX_DUMMY);
>>> CID 1372728: Memory - corruptions (OVERRUN)
>>> "&mp->ma_keys->dk_indices.as_1[mp->ma_keys->dk_size * ((mp->ma_keys->dk_size <= 255L) ? 1UL : ((mp->ma_keys->dk_size <= 65535L) ? 2UL : ((mp->ma_keys->dk_size <= 4294967295L) ? 4UL : 8UL)))]" evaluates to an address that is at byte offset 255 of an array of 8 bytes.
1734 ep = &DK_ENTRIES(mp->ma_keys)[ix];
1735 ENSURE_ALLOWS_DELETIONS(mp);
1736 old_key = ep->me_key;
1737 ep->me_key = NULL;
1738 Py_DECREF(old_key);
1739 } ** CID 1372727: Memory - illegal accesses (OVERRUN) ________________________________________________________________________________________________________
*** CID 1372727: Memory - illegal accesses (OVERRUN)
/Objects/dictobject.c: 1200 in dictresize()
1194 * and that value is stored in me_value.
1195 * Increment ref-counts and copy values here to compensate
1196 * This (resizing a split table) should be relatively rare */
1197 if (oldvalues != NULL) {
1198 for (i = 0; i < oldkeys->dk_nentries; i++) {
1199 if (oldvalues[i] != NULL) {
>>> CID 1372727: Memory - illegal accesses (OVERRUN)
>>> Overrunning array of 8 bytes at byte offset 255 by dereferencing pointer "ep0 + i".
1200 Py_INCREF(ep0[i].me_key);
1201 ep0[i].me_value = oldvalues[i];
1202 }
1203 }
1204 }
1205 /* Main loop */ ** CID 1372726: Memory - corruptions (OVERRUN) ________________________________________________________________________________________________________
*** CID 1372726: Memory - corruptions (OVERRUN)
/Objects/dictobject.c: 479 in new_keys_object()
473 DK_DEBUG_INCREF dk->dk_refcnt = 1;
474 dk->dk_size = size;
475 dk->dk_usable = usable;
476 dk->dk_lookup = lookdict_unicode_nodummy;
477 dk->dk_nentries = 0;
478 memset(&dk->dk_indices.as_1[0], 0xff, es * size);
>>> CID 1372726: Memory - corruptions (OVERRUN)
>>> Overrunning buffer pointed to by "(PyDictKeyEntry *)&dk->dk_indices.as_1[dk->dk_size * ((dk->dk_size <= 255L) ? 1UL : ((dk->dk_size <= 65535L) ? 2UL : ((dk->dk_size <= 4294967295L) ? 4UL : 8UL)))]" of 8 bytes by passing it to a function which accesses it at byte offset 8. [Note: The source code implementation of the function has been overridden by a builtin model.]
479 memset(DK_ENTRIES(dk), 0, sizeof(PyDictKeyEntry) * usable);
480 return dk;
481 }
482
483 static void
484 free_keys_object(PyDictKeysObject *keys) ** CID 1372725: Memory - illegal accesses (OVERRUN) ________________________________________________________________________________________________________
*** CID 1372725: Memory - illegal accesses (OVERRUN)
/Objects/dictobject.c: 2039 in dict_keys()
2033 else {
2034 value_ptr = &ep[0].me_value;
2035 offset = sizeof(PyDictKeyEntry);
2036 }
2037 for (i = 0, j = 0; i < size; i++) {
2038 if (*value_ptr != NULL) {
>>> CID 1372725: Memory - illegal accesses (OVERRUN)
>>> Overrunning array of 8 bytes at byte offset 255 by dereferencing pointer "ep + i".
2039 PyObject *key = ep[i].me_key;
2040 Py_INCREF(key);
2041 PyList_SET_ITEM(v, j, key);
2042 j++;
2043 }
2044 value_ptr = (PyObject **)(((char *)value_ptr) + offset); ** CID 1372724: Memory - corruptions (OVERRUN) ________________________________________________________________________________________________________
*** CID 1372724: Memory - corruptions (OVERRUN)
/Objects/dictobject.c: 1684 in _PyDict_Next()
1678 PyDictObject *mp;
1679 PyDictKeyEntry *ep0;
1680 Py_ssize_t i = dict_next(op, *ppos, pvalue);
1681 if (i < 0)
1682 return 0;
1683 mp = (PyDictObject *)op;
>>> CID 1372724: Memory - corruptions (OVERRUN)
>>> "&mp->ma_keys->dk_indices.as_1[mp->ma_keys->dk_size * ((mp->ma_keys->dk_size <= 255L) ? 1UL : ((mp->ma_keys->dk_size <= 65535L) ? 2UL : ((mp->ma_keys->dk_size <= 4294967295L) ? 4UL : 8UL)))]" evaluates to an address that is at byte offset 255 of an array of 8 bytes.
1684 ep0 = DK_ENTRIES(mp->ma_keys);
1685 *ppos = i+1;
1686 *phash = ep0[i].me_hash;
1687 if (pkey)
1688 *pkey = ep0[i].me_key;
1689 return 1; ** CID 1372723: Memory - illegal accesses (OVERRUN) ________________________________________________________________________________________________________
*** CID 1372723: Memory - illegal accesses (OVERRUN)
/Objects/dictobject.c: 2790 in dict_traverse()
2784 PyDictKeysObject *keys = mp->ma_keys;
2785 PyDictKeyEntry *entries = DK_ENTRIES(mp->ma_keys);
2786 Py_ssize_t i, n = keys->dk_nentries;
2787
2788 if (keys->dk_lookup == lookdict) {
2789 for (i = 0; i < n; i++) {
>>> CID 1372723: Memory - illegal accesses (OVERRUN)
>>> Overrunning array of 8 bytes at byte offset 255 by dereferencing pointer "entries + i".
2790 if (entries[i].me_value != NULL) {
2791 Py_VISIT(entries[i].me_value);
2792 Py_VISIT(entries[i].me_key);
2793 }
2794 }
2795 } ** CID 1372722: Memory - corruptions (OVERRUN) ________________________________________________________________________________________________________
*** CID 1372722: Memory - corruptions (OVERRUN)
/Objects/dictobject.c: 3261 in dictiter_iternextkey()
3255 i++;
3256 }
3257 di->di_pos = i+1;
3258 if (i > n)
3259 goto fail;
3260 di->len--;
>>> CID 1372722: Memory - corruptions (OVERRUN)
>>> "&k->dk_indices.as_1[k->dk_size * ((k->dk_size <= 255L) ? 1UL : ((k->dk_size <= 65535L) ? 2UL : ((k->dk_size <= 4294967295L) ? 4UL : 8UL)))]" evaluates to an address that is at byte offset 255 of an array of 8 bytes.
3261 key = DK_ENTRIES(k)[i].me_key;
3262 Py_INCREF(key);
3263 return key;
3264
3265 fail:
3266 di->di_dict = NULL; ** CID 1372721: Memory - corruptions (OVERRUN) ________________________________________________________________________________________________________
*** CID 1372721: Memory - corruptions (OVERRUN)
/Objects/dictobject.c: 626 in lookdict()
620 PyDictKeyEntry *ep0, *ep;
621 PyObject *startkey;
622
623 top:
624 dk = mp->ma_keys;
625 mask = DK_MASK(dk);
>>> CID 1372721: Memory - corruptions (OVERRUN)
>>> "&dk->dk_indices.as_1[dk->dk_size * ((dk->dk_size <= 255L) ? 1UL : ((dk->dk_size <= 65535L) ? 2UL : ((dk->dk_size <= 4294967295L) ? 4UL : 8UL)))]" evaluates to an address that is at byte offset 255 of an array of 8 bytes.
626 ep0 = DK_ENTRIES(dk);
627 i = (size_t)hash & mask;
628
629 ix = dk_get_index(dk, i);
630 if (ix == DKIX_EMPTY) {
631 if (hashpos != NULL) ** CID 1372720: Memory - corruptions (OVERRUN) ________________________________________________________________________________________________________
*** CID 1372720: Memory - corruptions (OVERRUN)
/Objects/dictobject.c: 996 in find_empty_slot()
990 find_empty_slot(PyDictObject *mp, PyObject *key, Py_hash_t hash,
991 PyObject ***value_addr, Py_ssize_t *hashpos)
992 {
993 size_t i, perturb;
994 size_t mask = DK_MASK(mp->ma_keys);
995 Py_ssize_t ix;
>>> CID 1372720: Memory - corruptions (OVERRUN)
>>> "&mp->ma_keys->dk_indices.as_1[mp->ma_keys->dk_size * ((mp->ma_keys->dk_size <= 255L) ? 1UL : ((mp->ma_keys->dk_size <= 65535L) ? 2UL : ((mp->ma_keys->dk_size <= 4294967295L) ? 4UL : 8UL)))]" evaluates to an address that is at byte offset 255 of an array of 8 bytes.
996 PyDictKeyEntry *ep, *ep0 = DK_ENTRIES(mp->ma_keys);
997
998 assert(hashpos != NULL);
999 assert(key != NULL);
1000 if (!PyUnicode_CheckExact(key))
1001 mp->ma_keys->dk_lookup = lookdict; ** CID 1372719: Memory - illegal accesses (OVERRUN) ________________________________________________________________________________________________________
*** CID 1372719: Memory - illegal accesses (OVERRUN)
/Objects/dictobject.c: 2522 in dict_equal()
2516 else
2517 aval = ep->me_value;
2518 if (aval != NULL) {
2519 int cmp;
2520 PyObject *bval;
2521 PyObject **vaddr;
>>> CID 1372719: Memory - illegal accesses (OVERRUN)
>>> Overrunning array of 8 bytes at byte offset 255 by dereferencing pointer "ep".
2522 PyObject *key = ep->me_key;
2523 /* temporarily bump aval's refcount to ensure it stays
2524 alive until we're done with it */
2525 Py_INCREF(aval);
2526 /* ditto for key */
2527 Py_INCREF(key); ** CID 1372718: Memory - corruptions (OVERRUN) ________________________________________________________________________________________________________
*** CID 1372718: Memory - corruptions (OVERRUN)
/Objects/dictobject.c: 1667 in PyDict_Next()
1661 Py_ssize_t i = dict_next(op, *ppos, pvalue);
1662 if (i < 0)
1663 return 0;
1664 mp = (PyDictObject *)op;
1665 *ppos = i+1;
1666 if (pkey)
>>> CID 1372718: Memory - corruptions (OVERRUN)
>>> "&mp->ma_keys->dk_indices.as_1[mp->ma_keys->dk_size * ((mp->ma_keys->dk_size <= 255L) ? 1UL : ((mp->ma_keys->dk_size <= 65535L) ? 2UL : ((mp->ma_keys->dk_size <= 4294967295L) ? 4UL : 8UL)))]" evaluates to an address that is at byte offset 255 of an array of 8 bytes.
1667 *pkey = DK_ENTRIES(mp->ma_keys)[i].me_key;
1668 return 1;
1669 }
1670
1671 /* Internal version of PyDict_Next that returns a hash value in addition
1672 * to the key and value. ** CID 1372717: Memory - corruptions (OVERRUN) ________________________________________________________________________________________________________
*** CID 1372717: Memory - corruptions (OVERRUN)
/Objects/dictobject.c: 729 in lookdict_unicode()
723 lookdict_unicode(PyDictObject *mp, PyObject *key,
724 Py_hash_t hash, PyObject ***value_addr, Py_ssize_t *hashpos)
725 {
726 size_t i, perturb;
727 size_t mask = DK_MASK(mp->ma_keys);
728 Py_ssize_t ix, freeslot;
>>> CID 1372717: Memory - corruptions (OVERRUN)
>>> "&mp->ma_keys->dk_indices.as_1[mp->ma_keys->dk_size * ((mp->ma_keys->dk_size <= 255L) ? 1UL : ((mp->ma_keys->dk_size <= 65535L) ? 2UL : ((mp->ma_keys->dk_size <= 4294967295L) ? 4UL : 8UL)))]" evaluates to an address that is at byte offset 255 of an array of 8 bytes.
729 PyDictKeyEntry *ep, *ep0 = DK_ENTRIES(mp->ma_keys);
730
731 assert(mp->ma_values == NULL);
732 /* Make sure this function doesn't have to handle non-unicode keys,
733 including subclasses of str; e.g., one reason to subclass
734 unicodes is to override __eq__, and for speed we don't cater to ** CID 1372716: Memory - corruptions (OVERRUN) ________________________________________________________________________________________________________
*** CID 1372716: Memory - corruptions (OVERRUN)
/Objects/dictobject.c: 1255 in make_keys_shared()
1249 /* Remove dummy keys */
1250 if (dictresize(mp, DK_SIZE(mp->ma_keys)))
1251 return NULL;
1252 }
1253 assert(mp->ma_keys->dk_lookup == lookdict_unicode_nodummy);
1254 /* Copy values into a new array */
>>> CID 1372716: Memory - corruptions (OVERRUN)
>>> "&mp->ma_keys->dk_indices.as_1[mp->ma_keys->dk_size * ((mp->ma_keys->dk_size <= 255L) ? 1UL : ((mp->ma_keys->dk_size <= 65535L) ? 2UL : ((mp->ma_keys->dk_size <= 4294967295L) ? 4UL : 8UL)))]" evaluates to an address that is at byte offset 255 of an array of 8 bytes.
1255 ep0 = DK_ENTRIES(mp->ma_keys);
1256 size = USABLE_FRACTION(DK_SIZE(mp->ma_keys));
1257 values = new_values(size);
1258 if (values == NULL) {
1259 PyErr_SetString(PyExc_MemoryError,
1260 "Not enough memory to allocate new values array"); ** CID 1372715: Memory - corruptions (OVERRUN) ________________________________________________________________________________________________________
*** CID 1372715: Memory - corruptions (OVERRUN)
/Objects/dictobject.c: 962 in _PyDict_MaybeUntrack()
956 PyDictKeyEntry *ep0;
957
958 if (!PyDict_CheckExact(op) || !_PyObject_GC_IS_TRACKED(op))
959 return;
960
961 mp = (PyDictObject *) op;
>>> CID 1372715: Memory - corruptions (OVERRUN)
>>> "&mp->ma_keys->dk_indices.as_1[mp->ma_keys->dk_size * ((mp->ma_keys->dk_size <= 255L) ? 1UL : ((mp->ma_keys->dk_size <= 65535L) ? 2UL : ((mp->ma_keys->dk_size <= 4294967295L) ? 4UL : 8UL)))]" evaluates to an address that is at byte offset 255 of an array of 8 bytes.
962 ep0 = DK_ENTRIES(mp->ma_keys);
963 numentries = mp->ma_keys->dk_nentries;
964 if (_PyDict_HasSplitTable(mp)) {
965 for (i = 0; i < numentries; i++) {
966 if ((value = mp->ma_values[i]) == NULL)
967 continue; |
Does the invite sent me by email? |
No problem, you can apply for membership at https://scan.coverity.com/projects/python . I'll approve you later today. |
Oh. That's why dictobject.c uses a trick. The C structure uses a fixed buffer of 8 bytes, but the actual allocated memory block has the right size. All these warnings are false positive, don't worry :-) We might use C99 "buffer[]" syntax, remove dk_indices from the structure, ignore the false alarm, or write a Coverity model for this one. Right now, I would prefer to not touch the C code just for a false alarm ;-) |
The warnings are false positives. Coverity does not understand the relationship between dict size and union members. I have closed all issues related to DK_ENTRIES(). There is still one issue left that seems worth looking into:
|
Thanks. It seems coverity doesn't understand assert(j >= 0); |
Coverity ignores asserts() because they are not in the final code. If you are sure that 'j' can never be < 0, then I can simply ignore the issue. |
OK, I ignored it on Coverity site. |
Perfect :) |
Note: these values reflect the state of the issue at the time it was migrated and might not reflect the current state.
Show more details
GitHub fields:
bugs.python.org fields:
The text was updated successfully, but these errors were encountered: