summaryrefslogtreecommitdiff
path: root/Modules
diff options
context:
space:
mode:
authorZackery Spytz <zspytz@gmail.com>2018-07-21 02:27:44 -0600
committerSerhiy Storchaka <storchaka@gmail.com>2018-07-21 11:27:44 +0300
commit32522050773c257a5c3c0c8929ba5c64123b53ed (patch)
tree06a2ac5cf99f2cd7e9b862425a7ece47532259ac /Modules
parentc5bc6e477e659e95ab8837cea85c1e52ae916e02 (diff)
downloadcpython-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.c93
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 {