The following code causes a crash: import sqlite3 cache = sqlite3.Cache.__new__(sqlite3.Cache) cache.get(None) This is because pysqlite_cache_get() (in Modules/_sqlite/cache.c) assumes that the Cache object is initialized, and so it passes self->mapping to PyDict_GetItem(), which assumes it is not NULL, and crashes. Also, the following code causes a SystemError ('null argument to internal routine'), as well as refleaks in the deallocation of the Cache object: import sqlite3 cache = sqlite3.Cache(str) try: cache.__init__() except TypeError: pass cache.get(None) This is because pysqlite_cache_init() first sets self->factory to NULL, and only then parses its arguments, so in case it fails to parse the arguments (e.g. due to a wrong number of arguments) we are left with a partially initialized Cache object. While we are here, we should also fix refleaks that occur when sqlite3.Cache.__init__() is called more than once.
Also, the following code results in a memory leak: import sqlite3 cache = sqlite3.Cache.__new__(sqlite3.Cache) This is because pysqlite_cache_dealloc() just returns in case of an uninitialized Cache object.
Thanks for the PR and for the work you've been doing to fix similar bugs in Python! The Cache class is an implementation detail and it has no practical use for third party users. See issue 30262 for a discussion on making it private. If a user somehow finds the Cache class, wants to do something with it, it's their problem if it crashes the interpreter. So, unless you can demonstrate that these problems can be reproduced without using the Cache class directly, I'm inclined to close this issue as 'wontfix'.