diff options
author | Zackery Spytz <zspytz@gmail.com> | 2018-07-21 02:27:44 -0600 |
---|---|---|
committer | Serhiy Storchaka <storchaka@gmail.com> | 2018-07-21 11:27:44 +0300 |
commit | 32522050773c257a5c3c0c8929ba5c64123b53ed (patch) | |
tree | 06a2ac5cf99f2cd7e9b862425a7ece47532259ac /Modules | |
parent | c5bc6e477e659e95ab8837cea85c1e52ae916e02 (diff) | |
download | cpython-git-32522050773c257a5c3c0c8929ba5c64123b53ed.tar.gz |
bpo-25943: Fix potential heap corruption in bsddb's _db_associateCallback() (GH-8337)
There was a missing check for integer overflow, several function calls
were not checked for failure, and allocated memory was not freed if an
error occurred.
Diffstat (limited to 'Modules')
-rw-r--r-- | Modules/_bsddb.c | 93 |
1 files changed, 54 insertions, 39 deletions
diff --git a/Modules/_bsddb.c b/Modules/_bsddb.c index 9c81ec5217..a8867942b1 100644 --- a/Modules/_bsddb.c +++ b/Modules/_bsddb.c @@ -1503,56 +1503,71 @@ _db_associateCallback(DB* db, const DBT* priKey, const DBT* priData, else if (PyList_Check(result)) { char* data; - Py_ssize_t size; - int i, listlen; + Py_ssize_t size, listlen, i; DBT* dbts; listlen = PyList_Size(result); - dbts = (DBT *)malloc(sizeof(DBT) * listlen); - - for (i=0; i<listlen; i++) - { - if (!PyBytes_Check(PyList_GetItem(result, i))) - { - PyErr_SetString( - PyExc_TypeError, + if (listlen > PY_SIZE_MAX / sizeof(DBT)) { + PyErr_NoMemory(); + PyErr_Print(); + } + else { + dbts = (DBT *)malloc(sizeof(DBT) * listlen); + if (dbts == NULL) { + PyErr_NoMemory(); + PyErr_Print(); + } + else { + for (i = 0; i < listlen; i++) { + if (!PyBytes_Check(PyList_GetItem(result, i))) { + PyErr_SetString(PyExc_TypeError, #if (PY_VERSION_HEX < 0x03000000) "The list returned by DB->associate callback should be a list of strings."); #else "The list returned by DB->associate callback should be a list of bytes."); #endif - PyErr_Print(); - } - - PyBytes_AsStringAndSize( - PyList_GetItem(result, i), - &data, &size); - - CLEAR_DBT(dbts[i]); - dbts[i].data = malloc(size); /* TODO, check this */ - - if (dbts[i].data) - { - memcpy(dbts[i].data, data, size); - dbts[i].size = size; - dbts[i].ulen = dbts[i].size; - dbts[i].flags = DB_DBT_APPMALLOC; /* DB will free */ - } - else - { - PyErr_SetString(PyExc_MemoryError, - "malloc failed in _db_associateCallback (list)"); - PyErr_Print(); + break; + } + + if (PyBytes_AsStringAndSize(PyList_GetItem(result, i), + &data, &size) < 0) { + break; + } + + CLEAR_DBT(dbts[i]); + dbts[i].data = malloc(size); + if (dbts[i].data) { + memcpy(dbts[i].data, data, size); + dbts[i].size = size; + dbts[i].ulen = dbts[i].size; + /* DB will free. */ + dbts[i].flags = DB_DBT_APPMALLOC; + } + else { + PyErr_SetString(PyExc_MemoryError, + "malloc failed in " + "_db_associateCallback (list)"); + break; + } + } + if (PyErr_Occurred()) { + PyErr_Print(); + while (i--) { + free(dbts[i].data); + } + free(dbts); + } + else { + CLEAR_DBT(*secKey); + + secKey->data = dbts; + secKey->size = listlen; + secKey->flags = DB_DBT_APPMALLOC | DB_DBT_MULTIPLE; + retval = 0; + } } } - - CLEAR_DBT(*secKey); - - secKey->data = dbts; - secKey->size = listlen; - secKey->flags = DB_DBT_APPMALLOC | DB_DBT_MULTIPLE; - retval = 0; } #endif else { |