[Python-checkins] bpo-25943: Fix potential heap corruption in bsddb's _db_associateCallback() (GH-8337)
Serhiy Storchaka
webhook-mailer at python.org
Sat Jul 21 04:27:49 EDT 2018
https://github.com/python/cpython/commit/32522050773c257a5c3c0c8929ba5c64123b53ed
commit: 32522050773c257a5c3c0c8929ba5c64123b53ed
branch: 2.7
author: Zackery Spytz <zspytz at gmail.com>
committer: Serhiy Storchaka <storchaka at gmail.com>
date: 2018-07-21T11:27:44+03:00
summary:
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.
files:
A Misc/NEWS.d/next/Core and Builtins/2018-07-18-23-40-32.bpo-25943.Zgf99y.rst
M Lib/bsddb/test/test_associate.py
M Modules/_bsddb.c
diff --git a/Lib/bsddb/test/test_associate.py b/Lib/bsddb/test/test_associate.py
index f0eadaaf66f1..4a8d2aed990b 100644
--- a/Lib/bsddb/test/test_associate.py
+++ b/Lib/bsddb/test/test_associate.py
@@ -114,6 +114,22 @@ def f(a,b): return a+b
dupDB.close()
self.fail("DBError exception was expected")
+ @unittest.skipUnless(db.version() >= (4, 6), 'Needs 4.6+')
+ def test_associateListError(self):
+ db1 = db.DB(self.env)
+ db1.open('bad.db', "a.db", db.DB_BTREE, db.DB_CREATE)
+ db2 = db.DB(self.env)
+ db2.open('bad.db', "b.db", db.DB_BTREE, db.DB_CREATE)
+
+ db1.associate(db2, lambda a, b: [0])
+
+ msg = "TypeError: The list returned by DB->associate callback" \
+ " should be a list of strings."
+ with test_support.captured_output("stderr") as s:
+ db1.put("0", "1")
+ db1.close()
+ db2.close()
+ self.assertEquals(s.getvalue().strip(), msg)
#----------------------------------------------------------------------
diff --git a/Misc/NEWS.d/next/Core and Builtins/2018-07-18-23-40-32.bpo-25943.Zgf99y.rst b/Misc/NEWS.d/next/Core and Builtins/2018-07-18-23-40-32.bpo-25943.Zgf99y.rst
new file mode 100644
index 000000000000..264e65c65517
--- /dev/null
+++ b/Misc/NEWS.d/next/Core and Builtins/2018-07-18-23-40-32.bpo-25943.Zgf99y.rst
@@ -0,0 +1,2 @@
+Fix potential heap corruption in the :mod:`bsddb` module. Patch by Zackery
+Spytz.
diff --git a/Modules/_bsddb.c b/Modules/_bsddb.c
index 9c81ec5217f3..a8867942b1fe 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 {
More information about the Python-checkins
mailing list