gh-111178: fix UBSan failures in Modules/_sqlite (GH-129087)

* fix UBSan failures for `pysqlite_Blob`
* fix UBSan failures for `pysqlite_Connection`
* fix UBSan failures for `pysqlite_Cursor`
* fix UBSan failures for `pysqlite_PrepareProtocol`
* fix UBSan failures for `pysqlite_Row`
* fix UBSan failures for `pysqlite_Statement`

* suppress unused return values
This commit is contained in:
Bénédikt Tran 2025-01-31 14:33:30 +01:00 committed by GitHub
parent 9d63ae5fe5
commit 881984b41a
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
7 changed files with 101 additions and 55 deletions

View file

@ -9,6 +9,8 @@
#include "clinic/blob.c.h"
#undef clinic_state
#define _pysqlite_Blob_CAST(op) ((pysqlite_Blob *)(op))
/*[clinic input]
module _sqlite3
class _sqlite3.Blob "pysqlite_Blob *" "clinic_state()->BlobType"
@ -29,32 +31,35 @@ close_blob(pysqlite_Blob *self)
}
static int
blob_traverse(pysqlite_Blob *self, visitproc visit, void *arg)
blob_traverse(PyObject *op, visitproc visit, void *arg)
{
pysqlite_Blob *self = _pysqlite_Blob_CAST(op);
Py_VISIT(Py_TYPE(self));
Py_VISIT(self->connection);
return 0;
}
static int
blob_clear(pysqlite_Blob *self)
blob_clear(PyObject *op)
{
pysqlite_Blob *self = _pysqlite_Blob_CAST(op);
Py_CLEAR(self->connection);
return 0;
}
static void
blob_dealloc(pysqlite_Blob *self)
blob_dealloc(PyObject *op)
{
pysqlite_Blob *self = _pysqlite_Blob_CAST(op);
PyTypeObject *tp = Py_TYPE(self);
PyObject_GC_UnTrack(self);
close_blob(self);
if (self->in_weakreflist != NULL) {
PyObject_ClearWeakRefs((PyObject*)self);
PyObject_ClearWeakRefs(op);
}
tp->tp_clear((PyObject *)self);
(void)tp->tp_clear(op);
tp->tp_free(self);
Py_DECREF(tp);
}
@ -373,8 +378,9 @@ blob_exit_impl(pysqlite_Blob *self, PyObject *type, PyObject *val,
}
static Py_ssize_t
blob_length(pysqlite_Blob *self)
blob_length(PyObject *op)
{
pysqlite_Blob *self = _pysqlite_Blob_CAST(op);
if (!check_blob(self)) {
return -1;
}
@ -449,8 +455,9 @@ subscript_slice(pysqlite_Blob *self, PyObject *item)
}
static PyObject *
blob_subscript(pysqlite_Blob *self, PyObject *item)
blob_subscript(PyObject *op, PyObject *item)
{
pysqlite_Blob *self = _pysqlite_Blob_CAST(op);
if (!check_blob(self)) {
return NULL;
}
@ -546,8 +553,9 @@ ass_subscript_slice(pysqlite_Blob *self, PyObject *item, PyObject *value)
}
static int
blob_ass_subscript(pysqlite_Blob *self, PyObject *item, PyObject *value)
blob_ass_subscript(PyObject *op, PyObject *item, PyObject *value)
{
pysqlite_Blob *self = _pysqlite_Blob_CAST(op);
if (!check_blob(self)) {
return -1;
}

View file

@ -135,6 +135,8 @@ sqlite3_int64_converter(PyObject *obj, sqlite3_int64 *result)
#include "clinic/connection.c.h"
#undef clinic_state
#define _pysqlite_Connection_CAST(op) ((pysqlite_Connection *)(op))
/*[clinic input]
module _sqlite3
class _sqlite3.Connection "pysqlite_Connection *" "clinic_state()->ConnectionType"
@ -384,8 +386,9 @@ do { \
} while (0)
static int
connection_traverse(pysqlite_Connection *self, visitproc visit, void *arg)
connection_traverse(PyObject *op, visitproc visit, void *arg)
{
pysqlite_Connection *self = _pysqlite_Connection_CAST(op);
Py_VISIT(Py_TYPE(self));
Py_VISIT(self->statement_cache);
Py_VISIT(self->cursors);
@ -409,8 +412,9 @@ clear_callback_context(callback_context *ctx)
}
static int
connection_clear(pysqlite_Connection *self)
connection_clear(PyObject *op)
{
pysqlite_Connection *self = _pysqlite_Connection_CAST(op);
Py_CLEAR(self->statement_cache);
Py_CLEAR(self->cursors);
Py_CLEAR(self->blobs);
@ -517,7 +521,7 @@ connection_dealloc(PyObject *self)
}
PyTypeObject *tp = Py_TYPE(self);
PyObject_GC_UnTrack(self);
tp->tp_clear(self);
(void)tp->tp_clear(self);
tp->tp_free(self);
Py_DECREF(tp);
}
@ -1715,8 +1719,10 @@ int pysqlite_check_thread(pysqlite_Connection* self)
return 1;
}
static PyObject* pysqlite_connection_get_isolation_level(pysqlite_Connection* self, void* unused)
static PyObject *
pysqlite_connection_get_isolation_level(PyObject *op, void *Py_UNUSED(closure))
{
pysqlite_Connection *self = _pysqlite_Connection_CAST(op);
if (!pysqlite_check_connection(self)) {
return NULL;
}
@ -1726,16 +1732,20 @@ static PyObject* pysqlite_connection_get_isolation_level(pysqlite_Connection* se
Py_RETURN_NONE;
}
static PyObject* pysqlite_connection_get_total_changes(pysqlite_Connection* self, void* unused)
static PyObject *
pysqlite_connection_get_total_changes(PyObject *op, void *Py_UNUSED(closure))
{
pysqlite_Connection *self = _pysqlite_Connection_CAST(op);
if (!pysqlite_check_connection(self)) {
return NULL;
}
return PyLong_FromLong(sqlite3_total_changes(self->db));
}
static PyObject* pysqlite_connection_get_in_transaction(pysqlite_Connection* self, void* unused)
static PyObject *
pysqlite_connection_get_in_transaction(PyObject *op, void *Py_UNUSED(closure))
{
pysqlite_Connection *self = _pysqlite_Connection_CAST(op);
if (!pysqlite_check_connection(self)) {
return NULL;
}
@ -1746,8 +1756,11 @@ static PyObject* pysqlite_connection_get_in_transaction(pysqlite_Connection* sel
}
static int
pysqlite_connection_set_isolation_level(pysqlite_Connection* self, PyObject* isolation_level, void *Py_UNUSED(ignored))
pysqlite_connection_set_isolation_level(PyObject *op,
PyObject *isolation_level,
void *Py_UNUSED(ignored))
{
pysqlite_Connection *self = _pysqlite_Connection_CAST(op);
if (isolation_level == NULL) {
PyErr_SetString(PyExc_AttributeError, "cannot delete attribute");
return -1;
@ -1770,11 +1783,11 @@ pysqlite_connection_set_isolation_level(pysqlite_Connection* self, PyObject* iso
}
static PyObject *
pysqlite_connection_call(pysqlite_Connection *self, PyObject *args,
PyObject *kwargs)
pysqlite_connection_call(PyObject *op, PyObject *args, PyObject *kwargs)
{
PyObject* sql;
pysqlite_Statement* statement;
pysqlite_Connection *self = _pysqlite_Connection_CAST(op);
if (!pysqlite_check_thread(self) || !pysqlite_check_connection(self)) {
return NULL;
@ -2525,8 +2538,9 @@ getconfig_impl(pysqlite_Connection *self, int op)
}
static PyObject *
get_autocommit(pysqlite_Connection *self, void *Py_UNUSED(ctx))
get_autocommit(PyObject *op, void *Py_UNUSED(closure))
{
pysqlite_Connection *self = _pysqlite_Connection_CAST(op);
if (!pysqlite_check_thread(self) || !pysqlite_check_connection(self)) {
return NULL;
}
@ -2540,8 +2554,9 @@ get_autocommit(pysqlite_Connection *self, void *Py_UNUSED(ctx))
}
static int
set_autocommit(pysqlite_Connection *self, PyObject *val, void *Py_UNUSED(ctx))
set_autocommit(PyObject *op, PyObject *val, void *Py_UNUSED(closure))
{
pysqlite_Connection *self = _pysqlite_Connection_CAST(op);
if (!pysqlite_check_thread(self) || !pysqlite_check_connection(self)) {
return -1;
}
@ -2566,7 +2581,7 @@ set_autocommit(pysqlite_Connection *self, PyObject *val, void *Py_UNUSED(ctx))
}
static PyObject *
get_sig(PyObject *self, void *Py_UNUSED(ctx))
get_sig(PyObject *Py_UNUSED(self), void *Py_UNUSED(closure))
{
return PyUnicode_FromString("(sql, /)");
}
@ -2576,11 +2591,12 @@ static const char connection_doc[] =
PyDoc_STR("SQLite database connection object.");
static PyGetSetDef connection_getset[] = {
{"isolation_level", (getter)pysqlite_connection_get_isolation_level, (setter)pysqlite_connection_set_isolation_level},
{"total_changes", (getter)pysqlite_connection_get_total_changes, (setter)0},
{"in_transaction", (getter)pysqlite_connection_get_in_transaction, (setter)0},
{"autocommit", (getter)get_autocommit, (setter)set_autocommit},
{"__text_signature__", get_sig, (setter)0},
{"isolation_level", pysqlite_connection_get_isolation_level,
pysqlite_connection_set_isolation_level},
{"total_changes", pysqlite_connection_get_total_changes, NULL},
{"in_transaction", pysqlite_connection_get_in_transaction, NULL},
{"autocommit", get_autocommit, set_autocommit},
{"__text_signature__", get_sig, NULL},
{NULL}
};

View file

@ -44,6 +44,8 @@ typedef enum {
#include "clinic/cursor.c.h"
#undef clinic_state
#define _pysqlite_Cursor_CAST(op) ((pysqlite_Cursor *)(op))
static inline int
check_cursor_locked(pysqlite_Cursor *cur)
{
@ -146,8 +148,9 @@ stmt_reset(pysqlite_Statement *self)
}
static int
cursor_traverse(pysqlite_Cursor *self, visitproc visit, void *arg)
cursor_traverse(PyObject *op, visitproc visit, void *arg)
{
pysqlite_Cursor *self = _pysqlite_Cursor_CAST(op);
Py_VISIT(Py_TYPE(self));
Py_VISIT(self->connection);
Py_VISIT(self->description);
@ -159,8 +162,9 @@ cursor_traverse(pysqlite_Cursor *self, visitproc visit, void *arg)
}
static int
cursor_clear(pysqlite_Cursor *self)
cursor_clear(PyObject *op)
{
pysqlite_Cursor *self = _pysqlite_Cursor_CAST(op);
Py_CLEAR(self->connection);
Py_CLEAR(self->description);
Py_CLEAR(self->row_cast_map);
@ -176,14 +180,15 @@ cursor_clear(pysqlite_Cursor *self)
}
static void
cursor_dealloc(pysqlite_Cursor *self)
cursor_dealloc(PyObject *op)
{
pysqlite_Cursor *self = _pysqlite_Cursor_CAST(op);
PyTypeObject *tp = Py_TYPE(self);
PyObject_GC_UnTrack(self);
if (self->in_weakreflist != NULL) {
PyObject_ClearWeakRefs((PyObject*)self);
PyObject_ClearWeakRefs(op);
}
tp->tp_clear((PyObject *)self);
(void)tp->tp_clear(op);
tp->tp_free(self);
Py_DECREF(tp);
}
@ -1087,8 +1092,9 @@ error:
}
static PyObject *
pysqlite_cursor_iternext(pysqlite_Cursor *self)
pysqlite_cursor_iternext(PyObject *op)
{
pysqlite_Cursor *self = _pysqlite_Cursor_CAST(op);
if (!check_cursor(self)) {
return NULL;
}
@ -1125,7 +1131,7 @@ pysqlite_cursor_iternext(pysqlite_Cursor *self)
}
if (!Py_IsNone(self->row_factory)) {
PyObject *factory = self->row_factory;
PyObject *args[] = { (PyObject *)self, row, };
PyObject *args[] = { op, row, };
PyObject *new_row = PyObject_Vectorcall(factory, args, 2, NULL);
Py_SETREF(row, new_row);
}
@ -1144,7 +1150,7 @@ pysqlite_cursor_fetchone_impl(pysqlite_Cursor *self)
{
PyObject* row;
row = pysqlite_cursor_iternext(self);
row = pysqlite_cursor_iternext((PyObject *)self);
if (!row && !PyErr_Occurred()) {
Py_RETURN_NONE;
}
@ -1174,7 +1180,7 @@ pysqlite_cursor_fetchmany_impl(pysqlite_Cursor *self, int maxrows)
return NULL;
}
while ((row = pysqlite_cursor_iternext(self))) {
while ((row = pysqlite_cursor_iternext((PyObject *)self))) {
if (PyList_Append(list, row) < 0) {
Py_DECREF(row);
break;
@ -1212,7 +1218,7 @@ pysqlite_cursor_fetchall_impl(pysqlite_Cursor *self)
return NULL;
}
while ((row = pysqlite_cursor_iternext(self))) {
while ((row = pysqlite_cursor_iternext((PyObject *)self))) {
if (PyList_Append(list, row) < 0) {
Py_DECREF(row);
break;

View file

@ -617,7 +617,7 @@ module_clear(PyObject *module)
static void
module_free(void *module)
{
module_clear((PyObject *)module);
(void)module_clear((PyObject *)module);
}
#define ADD_TYPE(module, type) \

View file

@ -24,8 +24,7 @@
#include "prepare_protocol.h"
static int
pysqlite_prepare_protocol_init(pysqlite_PrepareProtocol *self, PyObject *args,
PyObject *kwargs)
pysqlite_prepare_protocol_init(PyObject *self, PyObject *args, PyObject *kwargs)
{
return 0;
}
@ -38,7 +37,7 @@ pysqlite_prepare_protocol_traverse(PyObject *self, visitproc visit, void *arg)
}
static void
pysqlite_prepare_protocol_dealloc(pysqlite_PrepareProtocol *self)
pysqlite_prepare_protocol_dealloc(PyObject *self)
{
PyTypeObject *tp = Py_TYPE(self);
PyObject_GC_UnTrack(self);

View file

@ -32,6 +32,8 @@
#include "clinic/row.c.h"
#undef clinic_state
#define _pysqlite_Row_CAST(op) ((pysqlite_Row *)(op))
/*[clinic input]
module _sqlite3
class _sqlite3.Row "pysqlite_Row *" "clinic_state()->RowType"
@ -39,16 +41,18 @@ class _sqlite3.Row "pysqlite_Row *" "clinic_state()->RowType"
/*[clinic end generated code: output=da39a3ee5e6b4b0d input=966c53403d7f3a40]*/
static int
row_clear(pysqlite_Row *self)
row_clear(PyObject *op)
{
pysqlite_Row *self = _pysqlite_Row_CAST(op);
Py_CLEAR(self->data);
Py_CLEAR(self->description);
return 0;
}
static int
row_traverse(pysqlite_Row *self, visitproc visit, void *arg)
row_traverse(PyObject *op, visitproc visit, void *arg)
{
pysqlite_Row *self = _pysqlite_Row_CAST(op);
Py_VISIT(Py_TYPE(self));
Py_VISIT(self->data);
Py_VISIT(self->description);
@ -60,7 +64,7 @@ pysqlite_row_dealloc(PyObject *self)
{
PyTypeObject *tp = Py_TYPE(self);
PyObject_GC_UnTrack(self);
tp->tp_clear(self);
(void)tp->tp_clear(self);
tp->tp_free(self);
Py_DECREF(tp);
}
@ -94,10 +98,12 @@ pysqlite_row_new_impl(PyTypeObject *type, pysqlite_Cursor *cursor,
return (PyObject *) self;
}
PyObject* pysqlite_row_item(pysqlite_Row* self, Py_ssize_t idx)
static PyObject *
pysqlite_row_item(PyObject *op, Py_ssize_t idx)
{
PyObject *item = PyTuple_GetItem(self->data, idx);
return Py_XNewRef(item);
pysqlite_Row *self = _pysqlite_Row_CAST(op);
PyObject *item = PyTuple_GetItem(self->data, idx);
return Py_XNewRef(item);
}
static int
@ -129,10 +135,11 @@ equal_ignore_case(PyObject *left, PyObject *right)
}
static PyObject *
pysqlite_row_subscript(pysqlite_Row *self, PyObject *idx)
pysqlite_row_subscript(PyObject *op, PyObject *idx)
{
Py_ssize_t _idx;
Py_ssize_t nitems, i;
pysqlite_Row *self = _pysqlite_Row_CAST(op);
if (PyLong_Check(idx)) {
_idx = PyNumber_AsSsize_t(idx, PyExc_IndexError);
@ -174,8 +181,9 @@ pysqlite_row_subscript(pysqlite_Row *self, PyObject *idx)
}
static Py_ssize_t
pysqlite_row_length(pysqlite_Row* self)
pysqlite_row_length(PyObject *op)
{
pysqlite_Row *self = _pysqlite_Row_CAST(op);
return PyTuple_GET_SIZE(self->data);
}
@ -208,24 +216,30 @@ pysqlite_row_keys_impl(pysqlite_Row *self)
return list;
}
static PyObject* pysqlite_iter(pysqlite_Row* self)
static PyObject *
pysqlite_iter(PyObject *op)
{
pysqlite_Row *self = _pysqlite_Row_CAST(op);
return PyObject_GetIter(self->data);
}
static Py_hash_t pysqlite_row_hash(pysqlite_Row *self)
static Py_hash_t
pysqlite_row_hash(PyObject *op)
{
pysqlite_Row *self = _pysqlite_Row_CAST(op);
return PyObject_Hash(self->description) ^ PyObject_Hash(self->data);
}
static PyObject* pysqlite_row_richcompare(pysqlite_Row *self, PyObject *_other, int opid)
static PyObject *
pysqlite_row_richcompare(PyObject *op, PyObject *opother, int opid)
{
if (opid != Py_EQ && opid != Py_NE)
Py_RETURN_NOTIMPLEMENTED;
pysqlite_Row *self = _pysqlite_Row_CAST(op);
pysqlite_state *state = pysqlite_get_state_by_type(Py_TYPE(self));
if (PyObject_TypeCheck(_other, state->RowType)) {
pysqlite_Row *other = (pysqlite_Row *)_other;
if (PyObject_TypeCheck(opother, state->RowType)) {
pysqlite_Row *other = (pysqlite_Row *)opother;
int eq = PyObject_RichCompareBool(self->description, other->description, Py_EQ);
if (eq < 0) {
return NULL;

View file

@ -25,6 +25,8 @@
#include "statement.h"
#include "util.h"
#define _pysqlite_Statement_CAST(op) ((pysqlite_Statement *)(op))
/* prototypes */
static const char *lstrip_sql(const char *sql);
@ -99,10 +101,11 @@ error:
}
static void
stmt_dealloc(pysqlite_Statement *self)
stmt_dealloc(PyObject *op)
{
pysqlite_Statement *self = _pysqlite_Statement_CAST(op);
PyTypeObject *tp = Py_TYPE(self);
PyObject_GC_UnTrack(self);
PyObject_GC_UnTrack(op);
if (self->st) {
Py_BEGIN_ALLOW_THREADS
sqlite3_finalize(self->st);
@ -114,7 +117,7 @@ stmt_dealloc(pysqlite_Statement *self)
}
static int
stmt_traverse(pysqlite_Statement *self, visitproc visit, void *arg)
stmt_traverse(PyObject *self, visitproc visit, void *arg)
{
Py_VISIT(Py_TYPE(self));
return 0;