Thanks to visit codestin.com
Credit goes to github.com

Skip to content
Next Next commit
fix UBSan failures for dequeobject
  • Loading branch information
picnixz committed Jan 25, 2025
commit 22e4df825b78e8c9770062b5f92a7bf40609d7a1
74 changes: 45 additions & 29 deletions Modules/_collectionsmodule.c
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,8 @@ struct dequeobject {
PyObject *weakreflist;
};

#define _dequeobject_CAST(op) ((dequeobject *)(op))

/* For debug builds, add error checking to track the endpoints
* in the chain of links. The goal is to make sure that link
* assignments only take place at endpoints so that links already
Expand Down Expand Up @@ -570,8 +572,9 @@ deque_extendleft_impl(dequeobject *deque, PyObject *iterable)
}

static PyObject *
deque_inplace_concat(dequeobject *deque, PyObject *other)
deque_inplace_concat(PyObject *self, PyObject *other)
{
dequeobject *deque = _dequeobject_CAST(self);
PyObject *result;

// deque_extend is thread-safe
Expand All @@ -597,14 +600,13 @@ deque_copy_impl(dequeobject *deque)
/*[clinic end generated code: output=6409b3d1ad2898b5 input=51d2ed1a23bab5e2]*/
{
PyObject *result;
dequeobject *old_deque = (dequeobject *)deque;
dequeobject *old_deque = deque;
collections_state *state = find_module_state_by_def(Py_TYPE(deque));
if (Py_IS_TYPE(deque, state->deque_type)) {
dequeobject *new_deque;
PyObject *rv;

new_deque = (dequeobject *)deque_new(state->deque_type,
(PyObject *)NULL, (PyObject *)NULL);
new_deque = (dequeobject *)deque_new(state->deque_type, NULL, NULL);
if (new_deque == NULL)
return NULL;
new_deque->maxlen = old_deque->maxlen;
Expand Down Expand Up @@ -689,8 +691,9 @@ deque_concat_lock_held(dequeobject *deque, PyObject *other)
}

static PyObject *
deque_concat(dequeobject *deque, PyObject *other)
deque_concat(PyObject *self, PyObject *other)
{
dequeobject *deque = _dequeobject_CAST(self);
PyObject *result;
Py_BEGIN_CRITICAL_SECTION(deque);
result = deque_concat_lock_held(deque, other);
Expand All @@ -699,7 +702,7 @@ deque_concat(dequeobject *deque, PyObject *other)
}

static int
deque_clear(dequeobject *deque)
deque_clear(PyObject *self)
{
block *b;
block *prevblock;
Expand All @@ -708,6 +711,7 @@ deque_clear(dequeobject *deque)
Py_ssize_t n, m;
PyObject *item;
PyObject **itemptr, **limit;
dequeobject *deque = _dequeobject_CAST(self);

if (Py_SIZE(deque) == 0)
return 0;
Expand Down Expand Up @@ -795,7 +799,7 @@ static PyObject *
deque_clearmethod_impl(dequeobject *deque)
/*[clinic end generated code: output=79b2513e097615c1 input=3a22e9605d20c5e9]*/
{
deque_clear(deque);
(void)deque_clear((PyObject *)deque);
Py_RETURN_NONE;
}

Expand All @@ -812,7 +816,7 @@ deque_inplace_repeat_lock_held(dequeobject *deque, Py_ssize_t n)
}

if (n <= 0) {
deque_clear(deque);
(void)deque_clear((PyObject *)deque);
return Py_NewRef(deque);
}

Expand Down Expand Up @@ -877,8 +881,9 @@ deque_inplace_repeat_lock_held(dequeobject *deque, Py_ssize_t n)
}

static PyObject *
deque_inplace_repeat(dequeobject *deque, Py_ssize_t n)
deque_inplace_repeat(PyObject *self, Py_ssize_t n)
{
dequeobject *deque = _dequeobject_CAST(self);
PyObject *result;
Py_BEGIN_CRITICAL_SECTION(deque);
result = deque_inplace_repeat_lock_held(deque, n);
Expand All @@ -887,8 +892,9 @@ deque_inplace_repeat(dequeobject *deque, Py_ssize_t n)
}

static PyObject *
deque_repeat(dequeobject *deque, Py_ssize_t n)
deque_repeat(PyObject *self, Py_ssize_t n)
{
dequeobject *deque = _dequeobject_CAST(self);
dequeobject *new_deque;
PyObject *rv;

Expand Down Expand Up @@ -1202,8 +1208,9 @@ deque_contains_lock_held(dequeobject *deque, PyObject *v)
}

static int
deque_contains(dequeobject *deque, PyObject *v)
deque_contains(PyObject *self, PyObject *v)
{
dequeobject *deque = _dequeobject_CAST(self);
int result;
Py_BEGIN_CRITICAL_SECTION(deque);
result = deque_contains_lock_held(deque, v);
Expand All @@ -1212,9 +1219,10 @@ deque_contains(dequeobject *deque, PyObject *v)
}

static Py_ssize_t
deque_len(dequeobject *deque)
deque_len(PyObject *self)
{
return FT_ATOMIC_LOAD_SSIZE(((PyVarObject *)deque)->ob_size);
PyVarObject *deque = _PyVarObject_CAST(self);
return FT_ATOMIC_LOAD_SSIZE(deque->ob_size);
}

/*[clinic input]
Expand Down Expand Up @@ -1394,8 +1402,9 @@ deque_item_lock_held(dequeobject *deque, Py_ssize_t i)
}

static PyObject *
deque_item(dequeobject *deque, Py_ssize_t i)
deque_item(PyObject *self, Py_ssize_t i)
{
dequeobject *deque = _dequeobject_CAST(self);
PyObject *result;
Py_BEGIN_CRITICAL_SECTION(deque);
result = deque_item_lock_held(deque, i);
Expand Down Expand Up @@ -1505,8 +1514,9 @@ deque_ass_item_lock_held(dequeobject *deque, Py_ssize_t i, PyObject *v)
}

static int
deque_ass_item(dequeobject *deque, Py_ssize_t i, PyObject *v)
deque_ass_item(PyObject *self, Py_ssize_t i, PyObject *v)
{
dequeobject *deque = _dequeobject_CAST(self);
int result;
Py_BEGIN_CRITICAL_SECTION(deque);
result = deque_ass_item_lock_held(deque, i, v);
Expand All @@ -1515,16 +1525,18 @@ deque_ass_item(dequeobject *deque, Py_ssize_t i, PyObject *v)
}

static void
deque_dealloc(dequeobject *deque)
deque_dealloc(PyObject *self)
{
dequeobject *deque = _dequeobject_CAST(self);
PyTypeObject *tp = Py_TYPE(deque);
Py_ssize_t i;

PyObject_GC_UnTrack(deque);
if (deque->weakreflist != NULL)
PyObject_ClearWeakRefs((PyObject *) deque);
if (deque->weakreflist != NULL) {
PyObject_ClearWeakRefs(self);
}
if (deque->leftblock != NULL) {
deque_clear(deque);
(void)deque_clear(self);
assert(deque->leftblock != NULL);
freeblock(deque, deque->leftblock);
}
Expand All @@ -1538,8 +1550,9 @@ deque_dealloc(dequeobject *deque)
}

static int
deque_traverse(dequeobject *deque, visitproc visit, void *arg)
deque_traverse(PyObject *self, visitproc visit, void *arg)
{
dequeobject *deque = _dequeobject_CAST(self);
Py_VISIT(Py_TYPE(deque));

block *b;
Expand Down Expand Up @@ -1618,10 +1631,11 @@ deque_repr(PyObject *deque)
Py_ReprLeave(deque);
return NULL;
}
if (((dequeobject *)deque)->maxlen >= 0)
Py_ssize_t maxlen = _dequeobject_CAST(deque)->maxlen;
if (maxlen >= 0)
result = PyUnicode_FromFormat("%s(%R, maxlen=%zd)",
_PyType_Name(Py_TYPE(deque)), aslist,
((dequeobject *)deque)->maxlen);
maxlen);
else
result = PyUnicode_FromFormat("%s(%R)",
_PyType_Name(Py_TYPE(deque)), aslist);
Expand All @@ -1644,8 +1658,8 @@ deque_richcompare(PyObject *v, PyObject *w, int op)
}

/* Shortcuts */
vs = Py_SIZE((dequeobject *)v);
ws = Py_SIZE((dequeobject *)w);
vs = Py_SIZE(v);
ws = Py_SIZE(w);
if (op == Py_EQ) {
if (v == w)
Py_RETURN_TRUE;
Expand Down Expand Up @@ -1737,7 +1751,7 @@ deque_init_impl(dequeobject *deque, PyObject *iterable, PyObject *maxlenobj)
}
deque->maxlen = maxlen;
if (Py_SIZE(deque) > 0)
deque_clear(deque);
(void)deque_clear((PyObject *)deque);
if (iterable != NULL) {
PyObject *rv = deque_extend_impl(deque, iterable);
if (rv == NULL)
Expand Down Expand Up @@ -1770,8 +1784,9 @@ deque___sizeof___impl(dequeobject *deque)
}

static PyObject *
deque_get_maxlen(dequeobject *deque, void *Py_UNUSED(ignored))
deque_get_maxlen(PyObject *self, void *Py_UNUSED(closure))
{
dequeobject *deque = _dequeobject_CAST(self);
if (deque->maxlen < 0)
Py_RETURN_NONE;
return PyLong_FromSsize_t(deque->maxlen);
Expand All @@ -1797,12 +1812,12 @@ deque___reversed___impl(dequeobject *deque)
/* deque object ********************************************************/

static PyGetSetDef deque_getset[] = {
{"maxlen", (getter)deque_get_maxlen, (setter)NULL,
{"maxlen", deque_get_maxlen, NULL,
"maximum size of a deque or None if unbounded"},
{0}
};

static PyObject *deque_iter(dequeobject *deque);
static PyObject *deque_iter(PyObject *deque);

static PyMethodDef deque_methods[] = {
DEQUE_APPEND_METHODDEF
Expand Down Expand Up @@ -1884,9 +1899,10 @@ typedef struct {
} dequeiterobject;

static PyObject *
deque_iter(dequeobject *deque)
deque_iter(PyObject *self)
{
dequeiterobject *it;
dequeobject *deque = _dequeobject_CAST(self);

collections_state *state = find_module_state_by_def(Py_TYPE(deque));
it = PyObject_GC_New(dequeiterobject, state->dequeiter_type);
Expand Down