From ff0e32d28fcbfe7c768e60b05ea7ad990afbfcdc Mon Sep 17 00:00:00 2001 From: Alexey Izbyshev Date: Sat, 15 Sep 2018 18:07:10 +0300 Subject: [PATCH] bpo-34695: sqlite3: Fix crash if Cache.get() is called before __init__() --- Lib/sqlite3/test/regression.py | 11 +++++++++++ .../2018-09-15-18-58-31.bpo-34695.Ts0-Kt.rst | 1 + Modules/_sqlite/cache.c | 18 ++++++++++++++++++ 3 files changed, 30 insertions(+) create mode 100644 Misc/NEWS.d/next/Library/2018-09-15-18-58-31.bpo-34695.Ts0-Kt.rst diff --git a/Lib/sqlite3/test/regression.py b/Lib/sqlite3/test/regression.py index 34cd233535dc16..fd351afcf3b96e 100644 --- a/Lib/sqlite3/test/regression.py +++ b/Lib/sqlite3/test/regression.py @@ -397,6 +397,17 @@ def callback(*args): del ref support.gc_collect() + def CheckBpo34695(self): + """ + The interpreter shouldn't crash in case Cache.__init__() is not + called. + """ + cache = sqlite.Cache.__new__(sqlite.Cache, lambda x: x) + self.assertRaisesRegex(sqlite.ProgrammingError, r'Cache\.__init__', + cache.get, 42) + self.assertRaisesRegex(sqlite.ProgrammingError, r'Cache\.__init__', + cache.display) + def suite(): regression_suite = unittest.makeSuite(RegressionTests, "Check") diff --git a/Misc/NEWS.d/next/Library/2018-09-15-18-58-31.bpo-34695.Ts0-Kt.rst b/Misc/NEWS.d/next/Library/2018-09-15-18-58-31.bpo-34695.Ts0-Kt.rst new file mode 100644 index 00000000000000..70dfce488287a0 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2018-09-15-18-58-31.bpo-34695.Ts0-Kt.rst @@ -0,0 +1 @@ +Fix crash if :meth:`sqlite3.Cache.get` is called before ``__init__``. diff --git a/Modules/_sqlite/cache.c b/Modules/_sqlite/cache.c index 72b1f2c5614bf4..9d11563e9f1b44 100644 --- a/Modules/_sqlite/cache.c +++ b/Modules/_sqlite/cache.c @@ -22,6 +22,7 @@ */ #include "cache.h" +#include "module.h" #include /* only used internally */ @@ -112,6 +113,15 @@ void pysqlite_cache_dealloc(pysqlite_Cache* self) Py_TYPE(self)->tp_free((PyObject*)self); } +static int pysqlite_check_cache(pysqlite_Cache *self) { + if (self->factory == NULL) { + PyErr_SetString(pysqlite_ProgrammingError, + "Cache.__init__ was not called or failed."); + return 0; + } + return 1; +} + PyObject* pysqlite_cache_get(pysqlite_Cache* self, PyObject* args) { PyObject* key = args; @@ -119,6 +129,10 @@ PyObject* pysqlite_cache_get(pysqlite_Cache* self, PyObject* args) pysqlite_Node* ptr; PyObject* data; + if (!pysqlite_check_cache(self)) { + return NULL; + } + node = (pysqlite_Node*)PyDict_GetItem(self->mapping, key); if (node) { /* an entry for this key already exists in the cache */ @@ -218,6 +232,10 @@ PyObject* pysqlite_cache_display(pysqlite_Cache* self, PyObject* args) PyObject* nextkey; PyObject* display_str; + if (!pysqlite_check_cache(self)) { + return NULL; + } + ptr = self->first; while (ptr) {