gh-111178: fix UBSan failures in Modules/mmapmodule.c (GH-129784)

Fix UBSan failures for `mmap_object`

Use 'ignored' for NOARGS method and 'args' for others
This commit is contained in:
Bénédikt Tran 2025-02-19 12:02:32 +01:00 committed by GitHub
parent f8c041bff9
commit 0d0be7f7f1
No known key found for this signature in database
GPG key ID: B5690EEEBB952194

View file

@ -125,16 +125,19 @@ typedef struct {
access_mode access; access_mode access;
} mmap_object; } mmap_object;
#define mmap_object_CAST(op) ((mmap_object *)(op))
static int static int
mmap_object_traverse(mmap_object *m_obj, visitproc visit, void *arg) mmap_object_traverse(PyObject *op, visitproc visit, void *arg)
{ {
Py_VISIT(Py_TYPE(m_obj)); Py_VISIT(Py_TYPE(op));
return 0; return 0;
} }
static void static void
mmap_object_dealloc(mmap_object *m_obj) mmap_object_dealloc(PyObject *op)
{ {
mmap_object *m_obj = mmap_object_CAST(op);
PyTypeObject *tp = Py_TYPE(m_obj); PyTypeObject *tp = Py_TYPE(m_obj);
PyObject_GC_UnTrack(m_obj); PyObject_GC_UnTrack(m_obj);
@ -162,15 +165,16 @@ mmap_object_dealloc(mmap_object *m_obj)
#endif /* UNIX */ #endif /* UNIX */
if (m_obj->weakreflist != NULL) if (m_obj->weakreflist != NULL)
PyObject_ClearWeakRefs((PyObject *) m_obj); PyObject_ClearWeakRefs(op);
tp->tp_free(m_obj); tp->tp_free(m_obj);
Py_DECREF(tp); Py_DECREF(tp);
} }
static PyObject * static PyObject *
mmap_close_method(mmap_object *self, PyObject *Py_UNUSED(ignored)) mmap_close_method(PyObject *op, PyObject *Py_UNUSED(ignored))
{ {
mmap_object *self = mmap_object_CAST(op);
if (self->exports > 0) { if (self->exports > 0) {
PyErr_SetString(PyExc_BufferError, "cannot close "\ PyErr_SetString(PyExc_BufferError, "cannot close "\
"exported pointers exist"); "exported pointers exist");
@ -459,9 +463,9 @@ _safe_PyBytes_FromStringAndSize(char *start, size_t num_bytes) {
} }
static PyObject * static PyObject *
mmap_read_byte_method(mmap_object *self, mmap_read_byte_method(PyObject *op, PyObject *Py_UNUSED(ignored))
PyObject *Py_UNUSED(ignored))
{ {
mmap_object *self = mmap_object_CAST(op);
CHECK_VALID(NULL); CHECK_VALID(NULL);
if (self->pos >= self->size) { if (self->pos >= self->size) {
PyErr_SetString(PyExc_ValueError, "read byte out of range"); PyErr_SetString(PyExc_ValueError, "read byte out of range");
@ -476,11 +480,11 @@ mmap_read_byte_method(mmap_object *self,
} }
static PyObject * static PyObject *
mmap_read_line_method(mmap_object *self, mmap_read_line_method(PyObject *op, PyObject *Py_UNUSED(ignored))
PyObject *Py_UNUSED(ignored))
{ {
Py_ssize_t remaining; Py_ssize_t remaining;
char *start, *eol; char *start, *eol;
mmap_object *self = mmap_object_CAST(op);
CHECK_VALID(NULL); CHECK_VALID(NULL);
@ -506,10 +510,10 @@ mmap_read_line_method(mmap_object *self,
} }
static PyObject * static PyObject *
mmap_read_method(mmap_object *self, mmap_read_method(PyObject *op, PyObject *args)
PyObject *args)
{ {
Py_ssize_t num_bytes = PY_SSIZE_T_MAX, remaining; Py_ssize_t num_bytes = PY_SSIZE_T_MAX, remaining;
mmap_object *self = mmap_object_CAST(op);
CHECK_VALID(NULL); CHECK_VALID(NULL);
if (!PyArg_ParseTuple(args, "|O&:read", _Py_convert_optional_to_ssize_t, &num_bytes)) if (!PyArg_ParseTuple(args, "|O&:read", _Py_convert_optional_to_ssize_t, &num_bytes))
@ -594,16 +598,16 @@ mmap_gfind(mmap_object *self,
} }
static PyObject * static PyObject *
mmap_find_method(mmap_object *self, mmap_find_method(PyObject *op, PyObject *args)
PyObject *args)
{ {
mmap_object *self = mmap_object_CAST(op);
return mmap_gfind(self, args, 0); return mmap_gfind(self, args, 0);
} }
static PyObject * static PyObject *
mmap_rfind_method(mmap_object *self, mmap_rfind_method(PyObject *op, PyObject *args)
PyObject *args)
{ {
mmap_object *self = mmap_object_CAST(op);
return mmap_gfind(self, args, 1); return mmap_gfind(self, args, 1);
} }
@ -641,10 +645,10 @@ is_resizeable(mmap_object *self)
static PyObject * static PyObject *
mmap_write_method(mmap_object *self, mmap_write_method(PyObject *op, PyObject *args)
PyObject *args)
{ {
Py_buffer data; Py_buffer data;
mmap_object *self = mmap_object_CAST(op);
CHECK_VALID(NULL); CHECK_VALID(NULL);
if (!PyArg_ParseTuple(args, "y*:write", &data)) if (!PyArg_ParseTuple(args, "y*:write", &data))
@ -675,10 +679,10 @@ mmap_write_method(mmap_object *self,
} }
static PyObject * static PyObject *
mmap_write_byte_method(mmap_object *self, mmap_write_byte_method(PyObject *op, PyObject *args)
PyObject *args)
{ {
char value; char value;
mmap_object *self = mmap_object_CAST(op);
CHECK_VALID(NULL); CHECK_VALID(NULL);
if (!PyArg_ParseTuple(args, "b:write_byte", &value)) if (!PyArg_ParseTuple(args, "b:write_byte", &value))
@ -701,9 +705,9 @@ mmap_write_byte_method(mmap_object *self,
} }
static PyObject * static PyObject *
mmap_size_method(mmap_object *self, mmap_size_method(PyObject *op, PyObject *Py_UNUSED(ignored))
PyObject *Py_UNUSED(ignored))
{ {
mmap_object *self = mmap_object_CAST(op);
CHECK_VALID(NULL); CHECK_VALID(NULL);
#ifdef MS_WINDOWS #ifdef MS_WINDOWS
@ -751,10 +755,10 @@ mmap_size_method(mmap_object *self,
*/ */
static PyObject * static PyObject *
mmap_resize_method(mmap_object *self, mmap_resize_method(PyObject *op, PyObject *args)
PyObject *args)
{ {
Py_ssize_t new_size; Py_ssize_t new_size;
mmap_object *self = mmap_object_CAST(op);
CHECK_VALID(NULL); CHECK_VALID(NULL);
if (!PyArg_ParseTuple(args, "n:resize", &new_size) || if (!PyArg_ParseTuple(args, "n:resize", &new_size) ||
!is_resizeable(self)) { !is_resizeable(self)) {
@ -899,16 +903,18 @@ mmap_resize_method(mmap_object *self,
} }
static PyObject * static PyObject *
mmap_tell_method(mmap_object *self, PyObject *Py_UNUSED(ignored)) mmap_tell_method(PyObject *op, PyObject *Py_UNUSED(ignored))
{ {
mmap_object *self = mmap_object_CAST(op);
CHECK_VALID(NULL); CHECK_VALID(NULL);
return PyLong_FromSize_t(self->pos); return PyLong_FromSize_t(self->pos);
} }
static PyObject * static PyObject *
mmap_flush_method(mmap_object *self, PyObject *args) mmap_flush_method(PyObject *op, PyObject *args)
{ {
Py_ssize_t offset = 0; Py_ssize_t offset = 0;
mmap_object *self = mmap_object_CAST(op);
Py_ssize_t size = self->size; Py_ssize_t size = self->size;
CHECK_VALID(NULL); CHECK_VALID(NULL);
if (!PyArg_ParseTuple(args, "|nn:flush", &offset, &size)) if (!PyArg_ParseTuple(args, "|nn:flush", &offset, &size))
@ -941,9 +947,10 @@ mmap_flush_method(mmap_object *self, PyObject *args)
} }
static PyObject * static PyObject *
mmap_seek_method(mmap_object *self, PyObject *args) mmap_seek_method(PyObject *op, PyObject *args)
{ {
Py_ssize_t dist; Py_ssize_t dist;
mmap_object *self = mmap_object_CAST(op);
int how=0; int how=0;
CHECK_VALID(NULL); CHECK_VALID(NULL);
if (!PyArg_ParseTuple(args, "n|i:seek", &dist, &how)) if (!PyArg_ParseTuple(args, "n|i:seek", &dist, &how))
@ -980,15 +987,16 @@ mmap_seek_method(mmap_object *self, PyObject *args)
} }
static PyObject * static PyObject *
mmap_seekable_method(mmap_object *self, PyObject *Py_UNUSED(ignored)) mmap_seekable_method(PyObject *op, PyObject *Py_UNUSED(ignored))
{ {
Py_RETURN_TRUE; Py_RETURN_TRUE;
} }
static PyObject * static PyObject *
mmap_move_method(mmap_object *self, PyObject *args) mmap_move_method(PyObject *op, PyObject *args)
{ {
Py_ssize_t dest, src, cnt; Py_ssize_t dest, src, cnt;
mmap_object *self = mmap_object_CAST(op);
CHECK_VALID(NULL); CHECK_VALID(NULL);
if (!PyArg_ParseTuple(args, "nnn:move", &dest, &src, &cnt) || if (!PyArg_ParseTuple(args, "nnn:move", &dest, &src, &cnt) ||
!is_writable(self)) { !is_writable(self)) {
@ -1014,8 +1022,9 @@ mmap_move_method(mmap_object *self, PyObject *args)
} }
static PyObject * static PyObject *
mmap_closed_get(mmap_object *self, void *Py_UNUSED(ignored)) mmap_closed_get(PyObject *op, void *Py_UNUSED(closure))
{ {
mmap_object *self = mmap_object_CAST(op);
#ifdef MS_WINDOWS #ifdef MS_WINDOWS
return PyBool_FromLong(self->map_handle == NULL ? 1 : 0); return PyBool_FromLong(self->map_handle == NULL ? 1 : 0);
#elif defined(UNIX) #elif defined(UNIX)
@ -1024,23 +1033,24 @@ mmap_closed_get(mmap_object *self, void *Py_UNUSED(ignored))
} }
static PyObject * static PyObject *
mmap__enter__method(mmap_object *self, PyObject *args) mmap__enter__method(PyObject *op, PyObject *Py_UNUSED(ignored))
{ {
mmap_object *self = mmap_object_CAST(op);
CHECK_VALID(NULL); CHECK_VALID(NULL);
return Py_NewRef(self); return Py_NewRef(self);
} }
static PyObject * static PyObject *
mmap__exit__method(PyObject *self, PyObject *args) mmap__exit__method(PyObject *op, PyObject *Py_UNUSED(args))
{ {
return mmap_close_method((mmap_object *)self, NULL); return mmap_close_method(op, NULL);
} }
static PyObject * static PyObject *
mmap__repr__method(PyObject *self) mmap__repr__method(PyObject *op)
{ {
mmap_object *mobj = (mmap_object *)self; mmap_object *mobj = mmap_object_CAST(op);
#ifdef MS_WINDOWS #ifdef MS_WINDOWS
#define _Py_FORMAT_OFFSET "lld" #define _Py_FORMAT_OFFSET "lld"
@ -1054,7 +1064,7 @@ mmap__repr__method(PyObject *self)
if (mobj->data == NULL) if (mobj->data == NULL)
#endif #endif
{ {
return PyUnicode_FromFormat("<%s closed=True>", Py_TYPE(self)->tp_name); return PyUnicode_FromFormat("<%s closed=True>", Py_TYPE(op)->tp_name);
} else { } else {
const char *access_str; const char *access_str;
@ -1077,15 +1087,16 @@ mmap__repr__method(PyObject *self)
return PyUnicode_FromFormat("<%s closed=False, access=%s, length=%zd, " return PyUnicode_FromFormat("<%s closed=False, access=%s, length=%zd, "
"pos=%zd, offset=%" _Py_FORMAT_OFFSET ">", "pos=%zd, offset=%" _Py_FORMAT_OFFSET ">",
Py_TYPE(self)->tp_name, access_str, Py_TYPE(op)->tp_name, access_str,
mobj->size, mobj->pos, mobj->offset); mobj->size, mobj->pos, mobj->offset);
} }
} }
#ifdef MS_WINDOWS #ifdef MS_WINDOWS
static PyObject * static PyObject *
mmap__sizeof__method(mmap_object *self, void *Py_UNUSED(ignored)) mmap__sizeof__method(PyObject *op, void *Py_UNUSED(ignored))
{ {
mmap_object *self = mmap_object_CAST(op);
size_t res = _PyObject_SIZE(Py_TYPE(self)); size_t res = _PyObject_SIZE(Py_TYPE(self));
if (self->tagname) { if (self->tagname) {
res += (wcslen(self->tagname) + 1) * sizeof(self->tagname[0]); res += (wcslen(self->tagname) + 1) * sizeof(self->tagname[0]);
@ -1096,9 +1107,10 @@ mmap__sizeof__method(mmap_object *self, void *Py_UNUSED(ignored))
#if defined(MS_WINDOWS) && defined(Py_DEBUG) #if defined(MS_WINDOWS) && defined(Py_DEBUG)
static PyObject * static PyObject *
mmap_protect_method(mmap_object *self, PyObject *args) { mmap_protect_method(PyObject *op, PyObject *args) {
DWORD flNewProtect, flOldProtect; DWORD flNewProtect, flOldProtect;
Py_ssize_t start, length; Py_ssize_t start, length;
mmap_object *self = mmap_object_CAST(op);
CHECK_VALID(NULL); CHECK_VALID(NULL);
@ -1119,10 +1131,11 @@ mmap_protect_method(mmap_object *self, PyObject *args) {
#ifdef HAVE_MADVISE #ifdef HAVE_MADVISE
static PyObject * static PyObject *
mmap_madvise_method(mmap_object *self, PyObject *args) mmap_madvise_method(PyObject *op, PyObject *args)
{ {
int option; int option;
Py_ssize_t start = 0, length; Py_ssize_t start = 0, length;
mmap_object *self = mmap_object_CAST(op);
CHECK_VALID(NULL); CHECK_VALID(NULL);
length = self->size; length = self->size;
@ -1164,37 +1177,37 @@ static struct PyMemberDef mmap_object_members[] = {
}; };
static struct PyMethodDef mmap_object_methods[] = { static struct PyMethodDef mmap_object_methods[] = {
{"close", (PyCFunction) mmap_close_method, METH_NOARGS}, {"close", mmap_close_method, METH_NOARGS},
{"find", (PyCFunction) mmap_find_method, METH_VARARGS}, {"find", mmap_find_method, METH_VARARGS},
{"rfind", (PyCFunction) mmap_rfind_method, METH_VARARGS}, {"rfind", mmap_rfind_method, METH_VARARGS},
{"flush", (PyCFunction) mmap_flush_method, METH_VARARGS}, {"flush", mmap_flush_method, METH_VARARGS},
#ifdef HAVE_MADVISE #ifdef HAVE_MADVISE
{"madvise", (PyCFunction) mmap_madvise_method, METH_VARARGS}, {"madvise", mmap_madvise_method, METH_VARARGS},
#endif #endif
{"move", (PyCFunction) mmap_move_method, METH_VARARGS}, {"move", mmap_move_method, METH_VARARGS},
{"read", (PyCFunction) mmap_read_method, METH_VARARGS}, {"read", mmap_read_method, METH_VARARGS},
{"read_byte", (PyCFunction) mmap_read_byte_method, METH_NOARGS}, {"read_byte", mmap_read_byte_method, METH_NOARGS},
{"readline", (PyCFunction) mmap_read_line_method, METH_NOARGS}, {"readline", mmap_read_line_method, METH_NOARGS},
{"resize", (PyCFunction) mmap_resize_method, METH_VARARGS}, {"resize", mmap_resize_method, METH_VARARGS},
{"seek", (PyCFunction) mmap_seek_method, METH_VARARGS}, {"seek", mmap_seek_method, METH_VARARGS},
{"seekable", (PyCFunction) mmap_seekable_method, METH_NOARGS}, {"seekable", mmap_seekable_method, METH_NOARGS},
{"size", (PyCFunction) mmap_size_method, METH_NOARGS}, {"size", mmap_size_method, METH_NOARGS},
{"tell", (PyCFunction) mmap_tell_method, METH_NOARGS}, {"tell", mmap_tell_method, METH_NOARGS},
{"write", (PyCFunction) mmap_write_method, METH_VARARGS}, {"write", mmap_write_method, METH_VARARGS},
{"write_byte", (PyCFunction) mmap_write_byte_method, METH_VARARGS}, {"write_byte", mmap_write_byte_method, METH_VARARGS},
{"__enter__", (PyCFunction) mmap__enter__method, METH_NOARGS}, {"__enter__", mmap__enter__method, METH_NOARGS},
{"__exit__", (PyCFunction) mmap__exit__method, METH_VARARGS}, {"__exit__", mmap__exit__method, METH_VARARGS},
#ifdef MS_WINDOWS #ifdef MS_WINDOWS
{"__sizeof__", (PyCFunction) mmap__sizeof__method, METH_NOARGS}, {"__sizeof__", mmap__sizeof__method, METH_NOARGS},
#ifdef Py_DEBUG #ifdef Py_DEBUG
{"_protect", (PyCFunction) mmap_protect_method, METH_VARARGS}, {"_protect", mmap_protect_method, METH_VARARGS},
#endif // Py_DEBUG #endif // Py_DEBUG
#endif // MS_WINDOWS #endif // MS_WINDOWS
{NULL, NULL} /* sentinel */ {NULL, NULL} /* sentinel */
}; };
static PyGetSetDef mmap_object_getset[] = { static PyGetSetDef mmap_object_getset[] = {
{"closed", (getter) mmap_closed_get, NULL, NULL}, {"closed", mmap_closed_get, NULL, NULL},
{NULL} {NULL}
}; };
@ -1202,10 +1215,11 @@ static PyGetSetDef mmap_object_getset[] = {
/* Functions for treating an mmap'ed file as a buffer */ /* Functions for treating an mmap'ed file as a buffer */
static int static int
mmap_buffer_getbuf(mmap_object *self, Py_buffer *view, int flags) mmap_buffer_getbuf(PyObject *op, Py_buffer *view, int flags)
{ {
mmap_object *self = mmap_object_CAST(op);
CHECK_VALID(-1); CHECK_VALID(-1);
if (PyBuffer_FillInfo(view, (PyObject*)self, self->data, self->size, if (PyBuffer_FillInfo(view, op, self->data, self->size,
(self->access == ACCESS_READ), flags) < 0) (self->access == ACCESS_READ), flags) < 0)
return -1; return -1;
self->exports++; self->exports++;
@ -1213,21 +1227,24 @@ mmap_buffer_getbuf(mmap_object *self, Py_buffer *view, int flags)
} }
static void static void
mmap_buffer_releasebuf(mmap_object *self, Py_buffer *view) mmap_buffer_releasebuf(PyObject *op, Py_buffer *Py_UNUSED(view))
{ {
mmap_object *self = mmap_object_CAST(op);
self->exports--; self->exports--;
} }
static Py_ssize_t static Py_ssize_t
mmap_length(mmap_object *self) mmap_length(PyObject *op)
{ {
mmap_object *self = mmap_object_CAST(op);
CHECK_VALID(-1); CHECK_VALID(-1);
return self->size; return self->size;
} }
static PyObject * static PyObject *
mmap_item(mmap_object *self, Py_ssize_t i) mmap_item(PyObject *op, Py_ssize_t i)
{ {
mmap_object *self = mmap_object_CAST(op);
CHECK_VALID(NULL); CHECK_VALID(NULL);
if (i < 0 || i >= self->size) { if (i < 0 || i >= self->size) {
PyErr_SetString(PyExc_IndexError, "mmap index out of range"); PyErr_SetString(PyExc_IndexError, "mmap index out of range");
@ -1242,8 +1259,9 @@ mmap_item(mmap_object *self, Py_ssize_t i)
} }
static PyObject * static PyObject *
mmap_subscript(mmap_object *self, PyObject *item) mmap_subscript(PyObject *op, PyObject *item)
{ {
mmap_object *self = mmap_object_CAST(op);
CHECK_VALID(NULL); CHECK_VALID(NULL);
if (PyIndex_Check(item)) { if (PyIndex_Check(item)) {
Py_ssize_t i = PyNumber_AsSsize_t(item, PyExc_IndexError); Py_ssize_t i = PyNumber_AsSsize_t(item, PyExc_IndexError);
@ -1304,9 +1322,10 @@ mmap_subscript(mmap_object *self, PyObject *item)
} }
static int static int
mmap_ass_item(mmap_object *self, Py_ssize_t i, PyObject *v) mmap_ass_item(PyObject *op, Py_ssize_t i, PyObject *v)
{ {
const char *buf; const char *buf;
mmap_object *self = mmap_object_CAST(op);
CHECK_VALID(-1); CHECK_VALID(-1);
if (i < 0 || i >= self->size) { if (i < 0 || i >= self->size) {
@ -1334,8 +1353,9 @@ mmap_ass_item(mmap_object *self, Py_ssize_t i, PyObject *v)
} }
static int static int
mmap_ass_subscript(mmap_object *self, PyObject *item, PyObject *value) mmap_ass_subscript(PyObject *op, PyObject *item, PyObject *value)
{ {
mmap_object *self = mmap_object_CAST(op);
CHECK_VALID(-1); CHECK_VALID(-1);
if (!is_writable(self)) if (!is_writable(self))