From 37bc5562403d626ff74b16dbcb0aafcccb507039 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=A9n=C3=A9dikt=20Tran?= <10796600+picnixz@users.noreply.github.com> Date: Mon, 20 Jan 2025 16:20:32 +0100 Subject: [PATCH 01/16] fix UBSan failures for `buffered` --- Modules/_io/bufferedio.c | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/Modules/_io/bufferedio.c b/Modules/_io/bufferedio.c index bc5fff54a62b6d..0877dac696d87f 100644 --- a/Modules/_io/bufferedio.c +++ b/Modules/_io/bufferedio.c @@ -260,6 +260,7 @@ typedef struct { PyObject *dict; PyObject *weakreflist; } buffered; +#define _buffered_CAST(op) ((buffered *)(op)) /* Implementation notes: @@ -399,8 +400,9 @@ _enter_buffered_busy(buffered *self) static int -buffered_clear(buffered *self) +buffered_clear(PyObject *op) { + buffered *self = _buffered_CAST(op); self->ok = 0; Py_CLEAR(self->raw); Py_CLEAR(self->dict); @@ -408,16 +410,17 @@ buffered_clear(buffered *self) } static void -buffered_dealloc(buffered *self) +buffered_dealloc(PyObject *op) { + buffered *self = _buffered_CAST(op); PyTypeObject *tp = Py_TYPE(self); self->finalizing = 1; - if (_PyIOBase_finalize((PyObject *) self) < 0) + if (_PyIOBase_finalize(op) < 0) return; _PyObject_GC_UNTRACK(self); self->ok = 0; if (self->weakreflist != NULL) - PyObject_ClearWeakRefs((PyObject *)self); + PyObject_ClearWeakRefs(op); if (self->buffer) { PyMem_Free(self->buffer); self->buffer = NULL; @@ -426,8 +429,8 @@ buffered_dealloc(buffered *self) PyThread_free_lock(self->lock); self->lock = NULL; } - (void)buffered_clear(self); - tp->tp_free((PyObject *)self); + (void)buffered_clear(op); + tp->tp_free(op); Py_DECREF(tp); } From 36f5adc10d218540cc3c24dd97cee9562af13cb2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=A9n=C3=A9dikt=20Tran?= <10796600+picnixz@users.noreply.github.com> Date: Mon, 20 Jan 2025 16:23:35 +0100 Subject: [PATCH 02/16] fix UBSan failures for `rwpair` --- Modules/_io/bufferedio.c | 76 ++++++++++++++++++++++++---------------- 1 file changed, 46 insertions(+), 30 deletions(-) diff --git a/Modules/_io/bufferedio.c b/Modules/_io/bufferedio.c index 0877dac696d87f..10531cbab00b02 100644 --- a/Modules/_io/bufferedio.c +++ b/Modules/_io/bufferedio.c @@ -2229,6 +2229,7 @@ typedef struct { PyObject *dict; PyObject *weakreflist; } rwpair; +#define _rwpair_CAST(op) ((rwpair *)(op)) /*[clinic input] _io.BufferedRWPair.__init__ @@ -2279,8 +2280,9 @@ _io_BufferedRWPair___init___impl(rwpair *self, PyObject *reader, } static int -bufferedrwpair_traverse(rwpair *self, visitproc visit, void *arg) +bufferedrwpair_traverse(PyObject *op, visitproc visit, void *arg) { + rwpair *self = _rwpair_CAST(op); Py_VISIT(Py_TYPE(self)); Py_VISIT(self->dict); Py_VISIT(self->reader); @@ -2289,8 +2291,9 @@ bufferedrwpair_traverse(rwpair *self, visitproc visit, void *arg) } static int -bufferedrwpair_clear(rwpair *self) +bufferedrwpair_clear(PyObject *op) { + rwpair *self = _rwpair_CAST(op); Py_CLEAR(self->reader); Py_CLEAR(self->writer); Py_CLEAR(self->dict); @@ -2298,14 +2301,15 @@ bufferedrwpair_clear(rwpair *self) } static void -bufferedrwpair_dealloc(rwpair *self) +bufferedrwpair_dealloc(PyObject *op) { + rwpair *self = _rwpair_CAST(op); PyTypeObject *tp = Py_TYPE(self); _PyObject_GC_UNTRACK(self); if (self->weakreflist != NULL) - PyObject_ClearWeakRefs((PyObject *)self); - (void)bufferedrwpair_clear(self); - tp->tp_free((PyObject *) self); + PyObject_ClearWeakRefs(op); + (void)bufferedrwpair_clear(op); + tp->tp_free(self); Py_DECREF(tp); } @@ -2331,62 +2335,72 @@ _forward_call(buffered *self, PyObject *name, PyObject *args) } static PyObject * -bufferedrwpair_read(rwpair *self, PyObject *args) +bufferedrwpair_read(PyObject *op, PyObject *args) { + rwpair *self = _rwpair_CAST(op); return _forward_call(self->reader, &_Py_ID(read), args); } static PyObject * -bufferedrwpair_peek(rwpair *self, PyObject *args) +bufferedrwpair_peek(PyObject *op, PyObject *args) { + rwpair *self = _rwpair_CAST(op); return _forward_call(self->reader, &_Py_ID(peek), args); } static PyObject * -bufferedrwpair_read1(rwpair *self, PyObject *args) +bufferedrwpair_read1(PyObject *op, PyObject *args) { + rwpair *self = _rwpair_CAST(op); return _forward_call(self->reader, &_Py_ID(read1), args); } static PyObject * -bufferedrwpair_readinto(rwpair *self, PyObject *args) +bufferedrwpair_readinto(PyObject *op, PyObject *args) { + rwpair *self = _rwpair_CAST(op); return _forward_call(self->reader, &_Py_ID(readinto), args); } static PyObject * -bufferedrwpair_readinto1(rwpair *self, PyObject *args) +bufferedrwpair_readinto1(PyObject *op, PyObject *args) { + rwpair *self = _rwpair_CAST(op); return _forward_call(self->reader, &_Py_ID(readinto1), args); } static PyObject * -bufferedrwpair_write(rwpair *self, PyObject *args) +bufferedrwpair_write(PyObject *op, PyObject *args) { + rwpair *self = _rwpair_CAST(op); return _forward_call(self->writer, &_Py_ID(write), args); } static PyObject * -bufferedrwpair_flush(rwpair *self, PyObject *Py_UNUSED(ignored)) +bufferedrwpair_flush(PyObject *op, PyObject *Py_UNUSED(ignored)) { + rwpair *self = _rwpair_CAST(op); return _forward_call(self->writer, &_Py_ID(flush), NULL); } static PyObject * -bufferedrwpair_readable(rwpair *self, PyObject *Py_UNUSED(ignored)) +bufferedrwpair_readable(PyObject *op, PyObject *Py_UNUSED(ignored)) { + rwpair *self = _rwpair_CAST(op); return _forward_call(self->reader, &_Py_ID(readable), NULL); } static PyObject * -bufferedrwpair_writable(rwpair *self, PyObject *Py_UNUSED(ignored)) +bufferedrwpair_writable(PyObject *op, PyObject *Py_UNUSED(ignored)) { + rwpair *self = _rwpair_CAST(op); return _forward_call(self->writer, &_Py_ID(writable), NULL); } static PyObject * -bufferedrwpair_close(rwpair *self, PyObject *Py_UNUSED(ignored)) +bufferedrwpair_close(PyObject *op, PyObject *Py_UNUSED(ignored)) { + rwpair *self = _rwpair_CAST(op); PyObject *exc = NULL; PyObject *ret = _forward_call(self->writer, &_Py_ID(close), NULL); if (ret == NULL) { @@ -2404,8 +2418,9 @@ bufferedrwpair_close(rwpair *self, PyObject *Py_UNUSED(ignored)) } static PyObject * -bufferedrwpair_isatty(rwpair *self, PyObject *Py_UNUSED(ignored)) +bufferedrwpair_isatty(PyObject *op, PyObject *Py_UNUSED(ignored)) { + rwpair *self = _rwpair_CAST(op); PyObject *ret = _forward_call(self->writer, &_Py_ID(isatty), NULL); if (ret != Py_False) { @@ -2418,8 +2433,9 @@ bufferedrwpair_isatty(rwpair *self, PyObject *Py_UNUSED(ignored)) } static PyObject * -bufferedrwpair_closed_get(rwpair *self, void *context) +bufferedrwpair_closed_get(PyObject *op, void *Py_UNUSED(context)) { + rwpair *self = _rwpair_CAST(op); if (self->writer == NULL) { PyErr_SetString(PyExc_RuntimeError, "the BufferedRWPair object is being garbage-collected"); @@ -2636,20 +2652,20 @@ PyType_Spec bufferedwriter_spec = { }; static PyMethodDef bufferedrwpair_methods[] = { - {"read", (PyCFunction)bufferedrwpair_read, METH_VARARGS}, - {"peek", (PyCFunction)bufferedrwpair_peek, METH_VARARGS}, - {"read1", (PyCFunction)bufferedrwpair_read1, METH_VARARGS}, - {"readinto", (PyCFunction)bufferedrwpair_readinto, METH_VARARGS}, - {"readinto1", (PyCFunction)bufferedrwpair_readinto1, METH_VARARGS}, + {"read", bufferedrwpair_read, METH_VARARGS}, + {"peek", bufferedrwpair_peek, METH_VARARGS}, + {"read1", bufferedrwpair_read1, METH_VARARGS}, + {"readinto", bufferedrwpair_readinto, METH_VARARGS}, + {"readinto1", bufferedrwpair_readinto1, METH_VARARGS}, - {"write", (PyCFunction)bufferedrwpair_write, METH_VARARGS}, - {"flush", (PyCFunction)bufferedrwpair_flush, METH_NOARGS}, + {"write", bufferedrwpair_write, METH_VARARGS}, + {"flush", bufferedrwpair_flush, METH_NOARGS}, - {"readable", (PyCFunction)bufferedrwpair_readable, METH_NOARGS}, - {"writable", (PyCFunction)bufferedrwpair_writable, METH_NOARGS}, + {"readable", bufferedrwpair_readable, METH_NOARGS}, + {"writable", bufferedrwpair_writable, METH_NOARGS}, - {"close", (PyCFunction)bufferedrwpair_close, METH_NOARGS}, - {"isatty", (PyCFunction)bufferedrwpair_isatty, METH_NOARGS}, + {"close", bufferedrwpair_close, METH_NOARGS}, + {"isatty", bufferedrwpair_isatty, METH_NOARGS}, {NULL, NULL} }; @@ -2661,7 +2677,7 @@ static PyMemberDef bufferedrwpair_members[] = { }; static PyGetSetDef bufferedrwpair_getset[] = { - {"closed", (getter)bufferedrwpair_closed_get, NULL, NULL}, + {"closed", bufferedrwpair_closed_get, NULL, NULL}, {NULL} }; From 2a0229327f0189224f5a2cf4195cea5447a8d8fb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=A9n=C3=A9dikt=20Tran?= <10796600+picnixz@users.noreply.github.com> Date: Mon, 20 Jan 2025 16:50:45 +0100 Subject: [PATCH 03/16] fix UBSan failures for `bytesio` --- Modules/_io/bytesio.c | 38 ++++++++++++++++++++++++-------------- 1 file changed, 24 insertions(+), 14 deletions(-) diff --git a/Modules/_io/bytesio.c b/Modules/_io/bytesio.c index 16095333db6638..be0a64ed2a214d 100644 --- a/Modules/_io/bytesio.c +++ b/Modules/_io/bytesio.c @@ -21,6 +21,8 @@ typedef struct { Py_ssize_t exports; } bytesio; +#define _bytesio_CAST(op) ((bytesio *)(op)) + typedef struct { PyObject_HEAD bytesio *source; @@ -239,8 +241,9 @@ write_bytes(bytesio *self, PyObject *b) } static PyObject * -bytesio_get_closed(bytesio *self, void *Py_UNUSED(ignored)) +bytesio_get_closed(PyObject *op, void *Py_UNUSED(ignored)) { + bytesio *self = _bytesio_CAST(op); if (self->buf == NULL) { Py_RETURN_TRUE; } @@ -620,9 +623,10 @@ _io_BytesIO_truncate_impl(bytesio *self, Py_ssize_t size) } static PyObject * -bytesio_iternext(bytesio *self) +bytesio_iternext(PyObject *op) { Py_ssize_t n; + bytesio *self = _bytesio_CAST(op); CHECK_CLOSED(self); @@ -783,8 +787,9 @@ _io_BytesIO_close_impl(bytesio *self) */ static PyObject * -bytesio_getstate(bytesio *self, PyObject *Py_UNUSED(ignored)) +bytesio_getstate(PyObject *op, PyObject *Py_UNUSED(ignored)) { + bytesio *self = _bytesio_CAST(op); PyObject *initvalue = _io_BytesIO_getvalue_impl(self); PyObject *dict; PyObject *state; @@ -808,12 +813,13 @@ bytesio_getstate(bytesio *self, PyObject *Py_UNUSED(ignored)) } static PyObject * -bytesio_setstate(bytesio *self, PyObject *state) +bytesio_setstate(PyObject *op, PyObject *state) { PyObject *result; PyObject *position_obj; PyObject *dict; Py_ssize_t pos; + bytesio *self = _bytesio_CAST(op); assert(state != NULL); @@ -883,10 +889,11 @@ bytesio_setstate(bytesio *self, PyObject *state) } static void -bytesio_dealloc(bytesio *self) +bytesio_dealloc(PyObject *op) { + bytesio *self = _bytesio_CAST(op); PyTypeObject *tp = Py_TYPE(self); - _PyObject_GC_UNTRACK(self); + _PyObject_GC_UNTRACK(op); if (self->exports > 0) { PyErr_SetString(PyExc_SystemError, "deallocated BytesIO object has exported buffers"); @@ -895,7 +902,7 @@ bytesio_dealloc(bytesio *self) Py_CLEAR(self->buf); Py_CLEAR(self->dict); if (self->weakreflist != NULL) - PyObject_ClearWeakRefs((PyObject *) self); + PyObject_ClearWeakRefs(op); tp->tp_free(self); Py_DECREF(tp); } @@ -961,8 +968,9 @@ _io_BytesIO___init___impl(bytesio *self, PyObject *initvalue) } static PyObject * -bytesio_sizeof(bytesio *self, void *unused) +bytesio_sizeof(PyObject *op, PyObject *Py_UNUSED(args)) { + bytesio *self = _bytesio_CAST(op); size_t res = _PyObject_SIZE(Py_TYPE(self)); if (self->buf && !SHARED_BUF(self)) { size_t s = _PySys_GetSizeOf(self->buf); @@ -975,8 +983,9 @@ bytesio_sizeof(bytesio *self, void *unused) } static int -bytesio_traverse(bytesio *self, visitproc visit, void *arg) +bytesio_traverse(PyObject *op, visitproc visit, void *arg) { + bytesio *self = _bytesio_CAST(op); Py_VISIT(Py_TYPE(self)); Py_VISIT(self->dict); Py_VISIT(self->buf); @@ -984,8 +993,9 @@ bytesio_traverse(bytesio *self, visitproc visit, void *arg) } static int -bytesio_clear(bytesio *self) +bytesio_clear(PyObject *op) { + bytesio *self = _bytesio_CAST(op); Py_CLEAR(self->dict); if (self->exports == 0) { Py_CLEAR(self->buf); @@ -999,7 +1009,7 @@ bytesio_clear(bytesio *self) #undef clinic_state static PyGetSetDef bytesio_getsetlist[] = { - {"closed", (getter)bytesio_get_closed, NULL, + {"closed", bytesio_get_closed, NULL, "True if the file is closed."}, {NULL}, /* sentinel */ }; @@ -1023,9 +1033,9 @@ static struct PyMethodDef bytesio_methods[] = { _IO_BYTESIO_GETVALUE_METHODDEF _IO_BYTESIO_SEEK_METHODDEF _IO_BYTESIO_TRUNCATE_METHODDEF - {"__getstate__", (PyCFunction)bytesio_getstate, METH_NOARGS, NULL}, - {"__setstate__", (PyCFunction)bytesio_setstate, METH_O, NULL}, - {"__sizeof__", (PyCFunction)bytesio_sizeof, METH_NOARGS, NULL}, + {"__getstate__", bytesio_getstate, METH_NOARGS, NULL}, + {"__setstate__", bytesio_setstate, METH_O, NULL}, + {"__sizeof__", bytesio_sizeof, METH_NOARGS, NULL}, {NULL, NULL} /* sentinel */ }; From fc3cd12689a19ef793a42eadc0706f3f24802989 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=A9n=C3=A9dikt=20Tran?= <10796600+picnixz@users.noreply.github.com> Date: Mon, 20 Jan 2025 16:53:03 +0100 Subject: [PATCH 04/16] fix UBSan failures for `bytesiobuf` --- Modules/_io/bytesio.c | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/Modules/_io/bytesio.c b/Modules/_io/bytesio.c index be0a64ed2a214d..0fd3cc96e4a85d 100644 --- a/Modules/_io/bytesio.c +++ b/Modules/_io/bytesio.c @@ -28,6 +28,8 @@ typedef struct { bytesio *source; } bytesiobuf; +#define _bytesiobuf_CAST(op) ((bytesiobuf *)(op)) + /* The bytesio object can be in three states: * Py_REFCNT(buf) == 1, exports == 0. * Py_REFCNT(buf) > 1. exports == 0, @@ -1075,9 +1077,10 @@ PyType_Spec bytesio_spec = { */ static int -bytesiobuf_getbuffer(bytesiobuf *obj, Py_buffer *view, int flags) +bytesiobuf_getbuffer(PyObject *op, Py_buffer *view, int flags) { - bytesio *b = (bytesio *) obj->source; + bytesiobuf *obj = _bytesiobuf_CAST(op); + bytesio *b = _bytesio_CAST(obj->source); if (view == NULL) { PyErr_SetString(PyExc_BufferError, @@ -1090,7 +1093,7 @@ bytesiobuf_getbuffer(bytesiobuf *obj, Py_buffer *view, int flags) } /* cannot fail if view != NULL and readonly == 0 */ - (void)PyBuffer_FillInfo(view, (PyObject*)obj, + (void)PyBuffer_FillInfo(view, op, PyBytes_AS_STRING(b->buf), b->string_size, 0, flags); b->exports++; @@ -1098,26 +1101,29 @@ bytesiobuf_getbuffer(bytesiobuf *obj, Py_buffer *view, int flags) } static void -bytesiobuf_releasebuffer(bytesiobuf *obj, Py_buffer *view) +bytesiobuf_releasebuffer(PyObject *op, Py_buffer *Py_UNUSED(view)) { - bytesio *b = (bytesio *) obj->source; + bytesiobuf *obj = _bytesiobuf_CAST(op); + bytesio *b = _bytesio_CAST(obj->source); b->exports--; } static int -bytesiobuf_traverse(bytesiobuf *self, visitproc visit, void *arg) +bytesiobuf_traverse(PyObject *op, visitproc visit, void *arg) { + bytesiobuf *self = _bytesiobuf_CAST(op); Py_VISIT(Py_TYPE(self)); Py_VISIT(self->source); return 0; } static void -bytesiobuf_dealloc(bytesiobuf *self) +bytesiobuf_dealloc(PyObject *op) { + bytesiobuf *self = _bytesiobuf_CAST(op); PyTypeObject *tp = Py_TYPE(self); /* bpo-31095: UnTrack is needed before calling any callbacks */ - PyObject_GC_UnTrack(self); + PyObject_GC_UnTrack(op); Py_CLEAR(self->source); tp->tp_free(self); Py_DECREF(tp); From cd728f5e2ecb3ea3ada4151f7923e7f67ba0dff4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=A9n=C3=A9dikt=20Tran?= <10796600+picnixz@users.noreply.github.com> Date: Mon, 20 Jan 2025 16:58:33 +0100 Subject: [PATCH 05/16] fix UBSan failures for `iobase` --- Modules/_io/iobase.c | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/Modules/_io/iobase.c b/Modules/_io/iobase.c index 419e5516b5c11e..23ea8357ef9ad0 100644 --- a/Modules/_io/iobase.c +++ b/Modules/_io/iobase.c @@ -34,6 +34,7 @@ typedef struct { PyObject *dict; PyObject *weakreflist; } iobase; +#define _iobase_CAST(op) ((iobase *)(op)) PyDoc_STRVAR(iobase_doc, "The abstract base class for all I/O classes.\n" @@ -342,16 +343,18 @@ _PyIOBase_finalize(PyObject *self) } static int -iobase_traverse(iobase *self, visitproc visit, void *arg) +iobase_traverse(PyObject *op, visitproc visit, void *arg) { + iobase *self = _iobase_CAST(op); Py_VISIT(Py_TYPE(self)); Py_VISIT(self->dict); return 0; } static int -iobase_clear(iobase *self) +iobase_clear(PyObject *op) { + iobase *self = _iobase_CAST(op); Py_CLEAR(self->dict); return 0; } @@ -359,14 +362,15 @@ iobase_clear(iobase *self) /* Destructor */ static void -iobase_dealloc(iobase *self) +iobase_dealloc(PyObject *self) { /* NOTE: since IOBaseObject has its own dict, Python-defined attributes are still available here for close() to use. However, if the derived class declares a __slots__, those slots are already gone. */ - if (_PyIOBase_finalize((PyObject *) self) < 0) { + iobase *base = _iobase_CAST(self); + if (_PyIOBase_finalize(self) < 0) { /* When called from a heap type's dealloc, the type will be decref'ed on return (see e.g. subtype_dealloc in typeobject.c). */ if (_PyType_HasFeature(Py_TYPE(self), Py_TPFLAGS_HEAPTYPE)) { @@ -376,10 +380,10 @@ iobase_dealloc(iobase *self) } PyTypeObject *tp = Py_TYPE(self); _PyObject_GC_UNTRACK(self); - if (self->weakreflist != NULL) - PyObject_ClearWeakRefs((PyObject *) self); - Py_CLEAR(self->dict); - tp->tp_free((PyObject *)self); + if (base->weakreflist != NULL) + PyObject_ClearWeakRefs(self); + Py_CLEAR(base->dict); + tp->tp_free(self); Py_DECREF(tp); } @@ -852,7 +856,7 @@ static PyMethodDef iobase_methods[] = { static PyGetSetDef iobase_getset[] = { {"__dict__", PyObject_GenericGetDict, NULL, NULL}, - {"closed", (getter)iobase_closed_get, NULL, NULL}, + {"closed", iobase_closed_get, NULL, NULL}, {NULL} }; From 0da5a8122cc892fd897e0da97bd708528d534309 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=A9n=C3=A9dikt=20Tran?= <10796600+picnixz@users.noreply.github.com> Date: Mon, 20 Jan 2025 17:00:59 +0100 Subject: [PATCH 06/16] fix UBSan failures for `stringio` --- Modules/_io/stringio.c | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/Modules/_io/stringio.c b/Modules/_io/stringio.c index 687f584ee6caff..f87acd0bd2d87b 100644 --- a/Modules/_io/stringio.c +++ b/Modules/_io/stringio.c @@ -45,6 +45,8 @@ typedef struct { _PyIO_State *module_state; } stringio; +#define _stringio_CAST(op) ((stringio *)(op)) + #define clinic_state() (find_io_state_by_def(Py_TYPE(self))) #include "clinic/stringio.c.h" #undef clinic_state @@ -397,9 +399,10 @@ _io_StringIO_readline_impl(stringio *self, Py_ssize_t size) } static PyObject * -stringio_iternext(stringio *self) +stringio_iternext(PyObject *op) { PyObject *line; + stringio *self = _stringio_CAST(op); CHECK_INITIALIZED(self); CHECK_CLOSED(self); @@ -411,8 +414,7 @@ stringio_iternext(stringio *self) } else { /* XXX is subclassing StringIO really supported? */ - line = PyObject_CallMethodNoArgs((PyObject *)self, - &_Py_ID(readline)); + line = PyObject_CallMethodNoArgs(op, &_Py_ID(readline)); if (line && !PyUnicode_Check(line)) { PyErr_Format(PyExc_OSError, "readline() should have returned a str object, " @@ -585,8 +587,9 @@ _io_StringIO_close_impl(stringio *self) } static int -stringio_traverse(stringio *self, visitproc visit, void *arg) +stringio_traverse(PyObject *op, visitproc visit, void *arg) { + stringio *self = _stringio_CAST(op); Py_VISIT(Py_TYPE(self)); Py_VISIT(self->readnl); Py_VISIT(self->writenl); @@ -596,8 +599,9 @@ stringio_traverse(stringio *self, visitproc visit, void *arg) } static int -stringio_clear(stringio *self) +stringio_clear(PyObject *op) { + stringio *self = _stringio_CAST(op); Py_CLEAR(self->readnl); Py_CLEAR(self->writenl); Py_CLEAR(self->decoder); @@ -606,8 +610,9 @@ stringio_clear(stringio *self) } static void -stringio_dealloc(stringio *self) +stringio_dealloc(PyObject *op) { + stringio *self = _stringio_CAST(op); PyTypeObject *tp = Py_TYPE(self); _PyObject_GC_UNTRACK(self); self->ok = 0; @@ -616,9 +621,9 @@ stringio_dealloc(stringio *self) self->buf = NULL; } _PyUnicodeWriter_Dealloc(&self->writer); - (void)stringio_clear(self); + (void)stringio_clear(op); if (self->weakreflist != NULL) { - PyObject_ClearWeakRefs((PyObject *) self); + PyObject_ClearWeakRefs(op); } tp->tp_free(self); Py_DECREF(tp); From 9889af87da581969bd081e5cf265346eb33256b7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=A9n=C3=A9dikt=20Tran?= <10796600+picnixz@users.noreply.github.com> Date: Mon, 20 Jan 2025 17:04:36 +0100 Subject: [PATCH 07/16] fix UBSan failures for `nldecoder_object` --- Modules/_io/textio.c | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/Modules/_io/textio.c b/Modules/_io/textio.c index 791ee070401fe5..7fb20f773c003b 100644 --- a/Modules/_io/textio.c +++ b/Modules/_io/textio.c @@ -222,6 +222,7 @@ struct nldecoder_object { unsigned int translate: 1; unsigned int seennl: 3; }; +#define _nldecoder_object_CAST(op) ((nldecoder_object *)(op)) /*[clinic input] _io.IncrementalNewlineDecoder.__init__ @@ -263,9 +264,9 @@ _io_IncrementalNewlineDecoder___init___impl(nldecoder_object *self, } static int -incrementalnewlinedecoder_traverse(nldecoder_object *self, visitproc visit, - void *arg) +incrementalnewlinedecoder_traverse(PyObject *op, visitproc visit, void *arg) { + nldecoder_object *self = _nldecoder_object_CAST(op); Py_VISIT(Py_TYPE(self)); Py_VISIT(self->decoder); Py_VISIT(self->errors); @@ -273,20 +274,22 @@ incrementalnewlinedecoder_traverse(nldecoder_object *self, visitproc visit, } static int -incrementalnewlinedecoder_clear(nldecoder_object *self) +incrementalnewlinedecoder_clear(PyObject *op) { + nldecoder_object *self = _nldecoder_object_CAST(op); Py_CLEAR(self->decoder); Py_CLEAR(self->errors); return 0; } static void -incrementalnewlinedecoder_dealloc(nldecoder_object *self) +incrementalnewlinedecoder_dealloc(PyObject *op) { + nldecoder_object *self = _nldecoder_object_CAST(op); PyTypeObject *tp = Py_TYPE(self); _PyObject_GC_UNTRACK(self); - (void)incrementalnewlinedecoder_clear(self); - tp->tp_free((PyObject *)self); + (void)incrementalnewlinedecoder_clear(op); + tp->tp_free(self); Py_DECREF(tp); } @@ -323,7 +326,7 @@ _PyIncrementalNewlineDecoder_decode(PyObject *myself, { PyObject *output; Py_ssize_t output_len; - nldecoder_object *self = (nldecoder_object *) myself; + nldecoder_object *self = _nldecoder_object_CAST(myself); CHECK_INITIALIZED_DECODER(self); @@ -625,8 +628,9 @@ _io_IncrementalNewlineDecoder_reset_impl(nldecoder_object *self) } static PyObject * -incrementalnewlinedecoder_newlines_get(nldecoder_object *self, void *context) +incrementalnewlinedecoder_newlines_get(PyObject *op, void *Py_UNUSED(context)) { + nldecoder_object *self = _nldecoder_object_CAST(op); CHECK_INITIALIZED_DECODER(self); switch (self->seennl) { @@ -3313,7 +3317,7 @@ static PyMethodDef incrementalnewlinedecoder_methods[] = { }; static PyGetSetDef incrementalnewlinedecoder_getset[] = { - {"newlines", (getter)incrementalnewlinedecoder_newlines_get, NULL, NULL}, + {"newlines", incrementalnewlinedecoder_newlines_get, NULL, NULL}, {NULL} }; From 19ed68d7be319569e567fa0382974d1f2ea314d1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=A9n=C3=A9dikt=20Tran?= <10796600+picnixz@users.noreply.github.com> Date: Mon, 20 Jan 2025 17:13:12 +0100 Subject: [PATCH 08/16] fix UBSan failures for `textio` --- Modules/_io/textio.c | 115 ++++++++++++++++++++++--------------------- 1 file changed, 60 insertions(+), 55 deletions(-) diff --git a/Modules/_io/textio.c b/Modules/_io/textio.c index 7fb20f773c003b..dca22d013b751f 100644 --- a/Modules/_io/textio.c +++ b/Modules/_io/textio.c @@ -656,8 +656,7 @@ incrementalnewlinedecoder_newlines_get(PyObject *op, void *Py_UNUSED(context)) /* TextIOWrapper */ -typedef PyObject * - (*encodefunc_t)(PyObject *, PyObject *); +typedef PyObject *(*encodefunc_t)(PyObject *, PyObject *); struct textio { @@ -719,6 +718,7 @@ struct textio _PyIO_State *state; }; +#define _textio_CAST(op) ((textio *)(op)) static void textiowrapper_set_decoded_chars(textio *self, PyObject *chars); @@ -727,78 +727,81 @@ textiowrapper_set_decoded_chars(textio *self, PyObject *chars); encoding methods for the most popular encodings. */ static PyObject * -ascii_encode(textio *self, PyObject *text) +ascii_encode(PyObject *op, PyObject *text) { + textio *self = _textio_CAST(op); return _PyUnicode_AsASCIIString(text, PyUnicode_AsUTF8(self->errors)); } static PyObject * -utf16be_encode(textio *self, PyObject *text) +utf16be_encode(PyObject *op, PyObject *text) { - return _PyUnicode_EncodeUTF16(text, - PyUnicode_AsUTF8(self->errors), 1); + textio *self = _textio_CAST(op); + return _PyUnicode_EncodeUTF16(text, PyUnicode_AsUTF8(self->errors), 1); } static PyObject * -utf16le_encode(textio *self, PyObject *text) +utf16le_encode(PyObject *op, PyObject *text) { - return _PyUnicode_EncodeUTF16(text, - PyUnicode_AsUTF8(self->errors), -1); + textio *self = _textio_CAST(op); + return _PyUnicode_EncodeUTF16(text, PyUnicode_AsUTF8(self->errors), -1); } static PyObject * -utf16_encode(textio *self, PyObject *text) +utf16_encode(PyObject *op, PyObject *text) { + textio *self = _textio_CAST(op); if (!self->encoding_start_of_stream) { /* Skip the BOM and use native byte ordering */ #if PY_BIG_ENDIAN - return utf16be_encode(self, text); + return utf16be_encode(op, text); #else - return utf16le_encode(self, text); + return utf16le_encode(op, text); #endif } - return _PyUnicode_EncodeUTF16(text, - PyUnicode_AsUTF8(self->errors), 0); + return _PyUnicode_EncodeUTF16(text, PyUnicode_AsUTF8(self->errors), 0); } static PyObject * -utf32be_encode(textio *self, PyObject *text) +utf32be_encode(PyObject *op, PyObject *text) { - return _PyUnicode_EncodeUTF32(text, - PyUnicode_AsUTF8(self->errors), 1); + textio *self = _textio_CAST(op); + return _PyUnicode_EncodeUTF32(text, PyUnicode_AsUTF8(self->errors), 1); } static PyObject * -utf32le_encode(textio *self, PyObject *text) +utf32le_encode(PyObject *op, PyObject *text) { - return _PyUnicode_EncodeUTF32(text, - PyUnicode_AsUTF8(self->errors), -1); + textio *self = _textio_CAST(op); + return _PyUnicode_EncodeUTF32(text, PyUnicode_AsUTF8(self->errors), -1); } static PyObject * -utf32_encode(textio *self, PyObject *text) +utf32_encode(PyObject *op, PyObject *text) { + textio *self = _textio_CAST(op); if (!self->encoding_start_of_stream) { /* Skip the BOM and use native byte ordering */ #if PY_BIG_ENDIAN - return utf32be_encode(self, text); + return utf32be_encode(op, text); #else - return utf32le_encode(self, text); + return utf32le_encode(op, text); #endif } - return _PyUnicode_EncodeUTF32(text, - PyUnicode_AsUTF8(self->errors), 0); + return _PyUnicode_EncodeUTF32(text, PyUnicode_AsUTF8(self->errors), 0); } static PyObject * -utf8_encode(textio *self, PyObject *text) +utf8_encode(PyObject *op, PyObject *text) { + textio *self = _textio_CAST(op); return _PyUnicode_AsUTF8String(text, PyUnicode_AsUTF8(self->errors)); } static PyObject * -latin1_encode(textio *self, PyObject *text) +latin1_encode(PyObject *op, PyObject *text) { + textio *self = _textio_CAST(op); return _PyUnicode_AsLatin1String(text, PyUnicode_AsUTF8(self->errors)); } @@ -806,9 +809,7 @@ latin1_encode(textio *self, PyObject *text) static inline int is_asciicompat_encoding(encodefunc_t f) { - return f == (encodefunc_t) ascii_encode - || f == (encodefunc_t) latin1_encode - || f == (encodefunc_t) utf8_encode; + return f == ascii_encode || f == latin1_encode || f == utf8_encode; } /* Map normalized encoding names onto the specialized encoding funcs */ @@ -819,15 +820,15 @@ typedef struct { } encodefuncentry; static const encodefuncentry encodefuncs[] = { - {"ascii", (encodefunc_t) ascii_encode}, - {"iso8859-1", (encodefunc_t) latin1_encode}, - {"utf-8", (encodefunc_t) utf8_encode}, - {"utf-16-be", (encodefunc_t) utf16be_encode}, - {"utf-16-le", (encodefunc_t) utf16le_encode}, - {"utf-16", (encodefunc_t) utf16_encode}, - {"utf-32-be", (encodefunc_t) utf32be_encode}, - {"utf-32-le", (encodefunc_t) utf32le_encode}, - {"utf-32", (encodefunc_t) utf32_encode}, + {"ascii", ascii_encode}, + {"iso8859-1", latin1_encode}, + {"utf-8", utf8_encode}, + {"utf-16-be", utf16be_encode}, + {"utf-16-le", utf16le_encode}, + {"utf-16", utf16_encode}, + {"utf-32-be", utf32be_encode}, + {"utf-32-le", utf32le_encode}, + {"utf-32", utf32_encode}, {NULL, NULL} }; @@ -1437,8 +1438,9 @@ _io_TextIOWrapper_reconfigure_impl(textio *self, PyObject *encoding, } static int -textiowrapper_clear(textio *self) +textiowrapper_clear(PyObject *op) { + textio *self = _textio_CAST(op); self->ok = 0; Py_CLEAR(self->buffer); Py_CLEAR(self->encoding); @@ -1456,24 +1458,26 @@ textiowrapper_clear(textio *self) } static void -textiowrapper_dealloc(textio *self) +textiowrapper_dealloc(PyObject *op) { + textio *self = _textio_CAST(op); PyTypeObject *tp = Py_TYPE(self); self->finalizing = 1; - if (_PyIOBase_finalize((PyObject *) self) < 0) + if (_PyIOBase_finalize(op) < 0) return; self->ok = 0; _PyObject_GC_UNTRACK(self); if (self->weakreflist != NULL) - PyObject_ClearWeakRefs((PyObject *)self); - (void)textiowrapper_clear(self); - tp->tp_free((PyObject *)self); + PyObject_ClearWeakRefs(op); + (void)textiowrapper_clear(op); + tp->tp_free(self); Py_DECREF(tp); } static int -textiowrapper_traverse(textio *self, visitproc visit, void *arg) +textiowrapper_traverse(PyObject *op, visitproc visit, void *arg) { + textio *self = _textio_CAST(op); Py_VISIT(Py_TYPE(self)); Py_VISIT(self->buffer); Py_VISIT(self->encoding); @@ -2967,10 +2971,11 @@ _io_TextIOWrapper_truncate_impl(textio *self, PyObject *pos) } static PyObject * -textiowrapper_repr(textio *self) +textiowrapper_repr(PyObject *op) { PyObject *nameobj, *modeobj, *res, *s; int status; + textio *self = _textio_CAST(op); const char *type_name = Py_TYPE(self)->tp_name; CHECK_INITIALIZED(self); @@ -2979,7 +2984,7 @@ textiowrapper_repr(textio *self) if (res == NULL) return NULL; - status = Py_ReprEnter((PyObject *)self); + status = Py_ReprEnter(op); if (status != 0) { if (status > 0) { PyErr_Format(PyExc_RuntimeError, @@ -2988,7 +2993,7 @@ textiowrapper_repr(textio *self) } goto error; } - if (PyObject_GetOptionalAttr((PyObject *) self, &_Py_ID(name), &nameobj) < 0) { + if (PyObject_GetOptionalAttr(op, &_Py_ID(name), &nameobj) < 0) { if (!PyErr_ExceptionMatches(PyExc_ValueError)) { goto error; } @@ -3004,7 +3009,7 @@ textiowrapper_repr(textio *self) if (res == NULL) goto error; } - if (PyObject_GetOptionalAttr((PyObject *) self, &_Py_ID(mode), &modeobj) < 0) { + if (PyObject_GetOptionalAttr(op, &_Py_ID(mode), &modeobj) < 0) { goto error; } if (modeobj != NULL) { @@ -3020,14 +3025,14 @@ textiowrapper_repr(textio *self) res, self->encoding); Py_DECREF(res); if (status == 0) { - Py_ReprLeave((PyObject *)self); + Py_ReprLeave(op); } return s; error: Py_XDECREF(res); if (status == 0) { - Py_ReprLeave((PyObject *)self); + Py_ReprLeave(op); } return NULL; } @@ -3167,9 +3172,10 @@ _io_TextIOWrapper_close_impl(textio *self) } static PyObject * -textiowrapper_iternext(textio *self) +textiowrapper_iternext(PyObject *op) { PyObject *line; + textio *self = _textio_CAST(op); CHECK_ATTACHED(self); @@ -3179,8 +3185,7 @@ textiowrapper_iternext(textio *self) line = _textiowrapper_readline(self, -1); } else { - line = PyObject_CallMethodNoArgs((PyObject *)self, - &_Py_ID(readline)); + line = PyObject_CallMethodNoArgs(op, &_Py_ID(readline)); if (line && !PyUnicode_Check(line)) { PyErr_Format(PyExc_OSError, "readline() should have returned a str object, " From 249ec3e4f257a480f1d12377cf343c09679df46b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=A9n=C3=A9dikt=20Tran?= <10796600+picnixz@users.noreply.github.com> Date: Mon, 20 Jan 2025 17:17:07 +0100 Subject: [PATCH 09/16] fix UBSan failures for `winconsoleio` --- Modules/_io/winconsoleio.c | 37 +++++++++++++++++++++++-------------- 1 file changed, 23 insertions(+), 14 deletions(-) diff --git a/Modules/_io/winconsoleio.c b/Modules/_io/winconsoleio.c index 3fa0301e337991..48886c3b3f507b 100644 --- a/Modules/_io/winconsoleio.c +++ b/Modules/_io/winconsoleio.c @@ -221,6 +221,8 @@ typedef struct { wchar_t wbuf; } winconsoleio; +#define _winconsoleio_CAST(op) ((winconsoleio *)(op)) + int _PyWindowsConsoleIO_closed(PyObject *self) { @@ -492,32 +494,35 @@ _io__WindowsConsoleIO___init___impl(winconsoleio *self, PyObject *nameobj, } static int -winconsoleio_traverse(winconsoleio *self, visitproc visit, void *arg) +winconsoleio_traverse(PyObject *op, visitproc visit, void *arg) { + winconsoleio *self = _winconsoleio_CAST(op); Py_VISIT(Py_TYPE(self)); Py_VISIT(self->dict); return 0; } static int -winconsoleio_clear(winconsoleio *self) +winconsoleio_clear(PyObject *op) { + winconsoleio *self = _winconsoleio_CAST(op); Py_CLEAR(self->dict); return 0; } static void -winconsoleio_dealloc(winconsoleio *self) +winconsoleio_dealloc(PyObject *op) { + winconsoleio *self = _winconsoleio_CAST(op); PyTypeObject *tp = Py_TYPE(self); self->finalizing = 1; - if (_PyIOBase_finalize((PyObject *) self) < 0) + if (_PyIOBase_finalize(op) < 0) return; _PyObject_GC_UNTRACK(self); if (self->weakreflist != NULL) - PyObject_ClearWeakRefs((PyObject *) self); + PyObject_ClearWeakRefs(op); Py_CLEAR(self->dict); - tp->tp_free((PyObject *)self); + tp->tp_free(self); Py_DECREF(tp); } @@ -1137,9 +1142,10 @@ _io__WindowsConsoleIO_write_impl(winconsoleio *self, PyTypeObject *cls, } static PyObject * -winconsoleio_repr(winconsoleio *self) +winconsoleio_repr(PyObject *op) { - const char *type_name = (Py_TYPE((PyObject *)self)->tp_name); + winconsoleio *self = _winconsoleio_CAST(op); + const char *type_name = Py_TYPE(self)->tp_name; if (self->fd == -1) { return PyUnicode_FromFormat("<%.100s [closed]>", type_name); @@ -1197,28 +1203,31 @@ static PyMethodDef winconsoleio_methods[] = { /* 'closed' and 'mode' are attributes for compatibility with FileIO. */ static PyObject * -get_closed(winconsoleio *self, void *closure) +get_closed(PyObject *op, void *Py_UNUSED(closure)) { + winconsoleio *self = _winconsoleio_CAST(op); return PyBool_FromLong((long)(self->fd == -1)); } static PyObject * -get_closefd(winconsoleio *self, void *closure) +get_closefd(PyObject *op, void *Py_UNUSED(closure)) { + winconsoleio *self = _winconsoleio_CAST(op); return PyBool_FromLong((long)(self->closefd)); } static PyObject * -get_mode(winconsoleio *self, void *closure) +get_mode(PyObject *op, void *Py_UNUSED(closure)) { + winconsoleio *self = _winconsoleio_CAST(op); return PyUnicode_FromString(self->readable ? "rb" : "wb"); } static PyGetSetDef winconsoleio_getsetlist[] = { - {"closed", (getter)get_closed, NULL, "True if the file is closed"}, - {"closefd", (getter)get_closefd, NULL, + {"closed", get_closed, NULL, "True if the file is closed"}, + {"closefd", get_closefd, NULL, "True if the file descriptor will be closed by close()."}, - {"mode", (getter)get_mode, NULL, "String giving the file mode"}, + {"mode", get_mode, NULL, "String giving the file mode"}, {NULL}, }; From cf4414173930baffb7e258e8cbeaee81ae51690b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=A9n=C3=A9dikt=20Tran?= <10796600+picnixz@users.noreply.github.com> Date: Mon, 20 Jan 2025 17:28:11 +0100 Subject: [PATCH 10/16] reduce diff --- Modules/_io/bufferedio.c | 2 +- Modules/_io/bytesio.c | 2 +- Modules/_io/iobase.c | 12 ++++++------ 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/Modules/_io/bufferedio.c b/Modules/_io/bufferedio.c index 10531cbab00b02..cbcb4e80b1c56e 100644 --- a/Modules/_io/bufferedio.c +++ b/Modules/_io/bufferedio.c @@ -430,7 +430,7 @@ buffered_dealloc(PyObject *op) self->lock = NULL; } (void)buffered_clear(op); - tp->tp_free(op); + tp->tp_free(self); Py_DECREF(tp); } diff --git a/Modules/_io/bytesio.c b/Modules/_io/bytesio.c index 0fd3cc96e4a85d..aac664e0d3d77d 100644 --- a/Modules/_io/bytesio.c +++ b/Modules/_io/bytesio.c @@ -895,7 +895,7 @@ bytesio_dealloc(PyObject *op) { bytesio *self = _bytesio_CAST(op); PyTypeObject *tp = Py_TYPE(self); - _PyObject_GC_UNTRACK(op); + _PyObject_GC_UNTRACK(self); if (self->exports > 0) { PyErr_SetString(PyExc_SystemError, "deallocated BytesIO object has exported buffers"); diff --git a/Modules/_io/iobase.c b/Modules/_io/iobase.c index 23ea8357ef9ad0..64b94d4ab23607 100644 --- a/Modules/_io/iobase.c +++ b/Modules/_io/iobase.c @@ -362,15 +362,15 @@ iobase_clear(PyObject *op) /* Destructor */ static void -iobase_dealloc(PyObject *self) +iobase_dealloc(PyObject *op) { /* NOTE: since IOBaseObject has its own dict, Python-defined attributes are still available here for close() to use. However, if the derived class declares a __slots__, those slots are already gone. */ - iobase *base = _iobase_CAST(self); - if (_PyIOBase_finalize(self) < 0) { + iobase *self = _iobase_CAST(op); + if (_PyIOBase_finalize(op) < 0) { /* When called from a heap type's dealloc, the type will be decref'ed on return (see e.g. subtype_dealloc in typeobject.c). */ if (_PyType_HasFeature(Py_TYPE(self), Py_TPFLAGS_HEAPTYPE)) { @@ -380,9 +380,9 @@ iobase_dealloc(PyObject *self) } PyTypeObject *tp = Py_TYPE(self); _PyObject_GC_UNTRACK(self); - if (base->weakreflist != NULL) - PyObject_ClearWeakRefs(self); - Py_CLEAR(base->dict); + if (self->weakreflist != NULL) + PyObject_ClearWeakRefs(op); + Py_CLEAR(self->dict); tp->tp_free(self); Py_DECREF(tp); } From a9b3ca616b6d930e3db71e5e9541192dc29a9ec3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=A9n=C3=A9dikt=20Tran?= <10796600+picnixz@users.noreply.github.com> Date: Mon, 20 Jan 2025 17:31:51 +0100 Subject: [PATCH 11/16] add some new lines --- Modules/_io/bufferedio.c | 2 ++ Modules/_io/iobase.c | 1 + Modules/_io/textio.c | 2 ++ 3 files changed, 5 insertions(+) diff --git a/Modules/_io/bufferedio.c b/Modules/_io/bufferedio.c index cbcb4e80b1c56e..19db4922c00d7c 100644 --- a/Modules/_io/bufferedio.c +++ b/Modules/_io/bufferedio.c @@ -260,6 +260,7 @@ typedef struct { PyObject *dict; PyObject *weakreflist; } buffered; + #define _buffered_CAST(op) ((buffered *)(op)) /* @@ -2229,6 +2230,7 @@ typedef struct { PyObject *dict; PyObject *weakreflist; } rwpair; + #define _rwpair_CAST(op) ((rwpair *)(op)) /*[clinic input] diff --git a/Modules/_io/iobase.c b/Modules/_io/iobase.c index 64b94d4ab23607..744e8d45de98d5 100644 --- a/Modules/_io/iobase.c +++ b/Modules/_io/iobase.c @@ -34,6 +34,7 @@ typedef struct { PyObject *dict; PyObject *weakreflist; } iobase; + #define _iobase_CAST(op) ((iobase *)(op)) PyDoc_STRVAR(iobase_doc, diff --git a/Modules/_io/textio.c b/Modules/_io/textio.c index dca22d013b751f..92bf3c45583f60 100644 --- a/Modules/_io/textio.c +++ b/Modules/_io/textio.c @@ -222,6 +222,7 @@ struct nldecoder_object { unsigned int translate: 1; unsigned int seennl: 3; }; + #define _nldecoder_object_CAST(op) ((nldecoder_object *)(op)) /*[clinic input] @@ -718,6 +719,7 @@ struct textio _PyIO_State *state; }; + #define _textio_CAST(op) ((textio *)(op)) static void From 416d7405f4dc7669fa50d4d9aa06370c3058e969 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=A9n=C3=A9dikt=20Tran?= <10796600+picnixz@users.noreply.github.com> Date: Sat, 25 Jan 2025 20:40:03 +0100 Subject: [PATCH 12/16] post-merge fix --- Modules/_io/stringio.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Modules/_io/stringio.c b/Modules/_io/stringio.c index 6bd72a72b32c85..949c4ae0e67a6a 100644 --- a/Modules/_io/stringio.c +++ b/Modules/_io/stringio.c @@ -627,7 +627,7 @@ stringio_dealloc(PyObject *op) self->buf = NULL; } PyUnicodeWriter_Discard(self->writer); - (void)stringio_clear(self); + (void)stringio_clear(op); if (self->weakreflist != NULL) { PyObject_ClearWeakRefs(op); } From c6f2d0ee2e452ca5ad1f6383caf9bd96076572de Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=A9n=C3=A9dikt=20Tran?= <10796600+picnixz@users.noreply.github.com> Date: Thu, 6 Feb 2025 17:44:14 +0100 Subject: [PATCH 13/16] use 'ignored' for NOARGS method and 'args' for others --- Modules/_io/bytesio.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Modules/_io/bytesio.c b/Modules/_io/bytesio.c index aac664e0d3d77d..b8a5d8440581f4 100644 --- a/Modules/_io/bytesio.c +++ b/Modules/_io/bytesio.c @@ -970,7 +970,7 @@ _io_BytesIO___init___impl(bytesio *self, PyObject *initvalue) } static PyObject * -bytesio_sizeof(PyObject *op, PyObject *Py_UNUSED(args)) +bytesio_sizeof(PyObject *op, PyObject *Py_UNUSED(ignored)) { bytesio *self = _bytesio_CAST(op); size_t res = _PyObject_SIZE(Py_TYPE(self)); From ec1e15d5636377000e198d7a8daf7d86ef88bed3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=A9n=C3=A9dikt=20Tran?= <10796600+picnixz@users.noreply.github.com> Date: Thu, 6 Feb 2025 17:49:38 +0100 Subject: [PATCH 14/16] use 'dummy' for NOARGS method --- Modules/_io/bufferedio.c | 12 ++++++------ Modules/_io/bytesio.c | 6 +++--- Modules/_io/fileio.c | 2 +- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/Modules/_io/bufferedio.c b/Modules/_io/bufferedio.c index 19db4922c00d7c..477c98d03ab61d 100644 --- a/Modules/_io/bufferedio.c +++ b/Modules/_io/bufferedio.c @@ -2379,28 +2379,28 @@ bufferedrwpair_write(PyObject *op, PyObject *args) } static PyObject * -bufferedrwpair_flush(PyObject *op, PyObject *Py_UNUSED(ignored)) +bufferedrwpair_flush(PyObject *op, PyObject *Py_UNUSED(dummy)) { rwpair *self = _rwpair_CAST(op); return _forward_call(self->writer, &_Py_ID(flush), NULL); } static PyObject * -bufferedrwpair_readable(PyObject *op, PyObject *Py_UNUSED(ignored)) +bufferedrwpair_readable(PyObject *op, PyObject *Py_UNUSED(dummy)) { rwpair *self = _rwpair_CAST(op); return _forward_call(self->reader, &_Py_ID(readable), NULL); } static PyObject * -bufferedrwpair_writable(PyObject *op, PyObject *Py_UNUSED(ignored)) +bufferedrwpair_writable(PyObject *op, PyObject *Py_UNUSED(dummy)) { rwpair *self = _rwpair_CAST(op); return _forward_call(self->writer, &_Py_ID(writable), NULL); } static PyObject * -bufferedrwpair_close(PyObject *op, PyObject *Py_UNUSED(ignored)) +bufferedrwpair_close(PyObject *op, PyObject *Py_UNUSED(dummy)) { rwpair *self = _rwpair_CAST(op); PyObject *exc = NULL; @@ -2420,7 +2420,7 @@ bufferedrwpair_close(PyObject *op, PyObject *Py_UNUSED(ignored)) } static PyObject * -bufferedrwpair_isatty(PyObject *op, PyObject *Py_UNUSED(ignored)) +bufferedrwpair_isatty(PyObject *op, PyObject *Py_UNUSED(dummy)) { rwpair *self = _rwpair_CAST(op); PyObject *ret = _forward_call(self->writer, &_Py_ID(isatty), NULL); @@ -2435,7 +2435,7 @@ bufferedrwpair_isatty(PyObject *op, PyObject *Py_UNUSED(ignored)) } static PyObject * -bufferedrwpair_closed_get(PyObject *op, void *Py_UNUSED(context)) +bufferedrwpair_closed_get(PyObject *op, void *Py_UNUSED(dummy)) { rwpair *self = _rwpair_CAST(op); if (self->writer == NULL) { diff --git a/Modules/_io/bytesio.c b/Modules/_io/bytesio.c index b8a5d8440581f4..f95fe2508d1f71 100644 --- a/Modules/_io/bytesio.c +++ b/Modules/_io/bytesio.c @@ -243,7 +243,7 @@ write_bytes(bytesio *self, PyObject *b) } static PyObject * -bytesio_get_closed(PyObject *op, void *Py_UNUSED(ignored)) +bytesio_get_closed(PyObject *op, void *Py_UNUSED(closure)) { bytesio *self = _bytesio_CAST(op); if (self->buf == NULL) { @@ -789,7 +789,7 @@ _io_BytesIO_close_impl(bytesio *self) */ static PyObject * -bytesio_getstate(PyObject *op, PyObject *Py_UNUSED(ignored)) +bytesio_getstate(PyObject *op, PyObject *Py_UNUSED(dummy)) { bytesio *self = _bytesio_CAST(op); PyObject *initvalue = _io_BytesIO_getvalue_impl(self); @@ -970,7 +970,7 @@ _io_BytesIO___init___impl(bytesio *self, PyObject *initvalue) } static PyObject * -bytesio_sizeof(PyObject *op, PyObject *Py_UNUSED(ignored)) +bytesio_sizeof(PyObject *op, PyObject *Py_UNUSED(dummy)) { bytesio *self = _bytesio_CAST(op); size_t res = _PyObject_SIZE(Py_TYPE(self)); diff --git a/Modules/_io/fileio.c b/Modules/_io/fileio.c index cf0f1d671b507a..49d01e2ba2f779 100644 --- a/Modules/_io/fileio.c +++ b/Modules/_io/fileio.c @@ -1225,7 +1225,7 @@ _io_FileIO_isatty_impl(fileio *self) context TOCTOU issues (the fd could be arbitrarily modified by surrounding code). */ static PyObject * -_io_FileIO_isatty_open_only(PyObject *op, PyObject *Py_UNUSED(ignored)) +_io_FileIO_isatty_open_only(PyObject *op, PyObject *Py_UNUSED(dummy)) { fileio *self = _PyFileIO_CAST(op); if (self->stat_atopen != NULL && !S_ISCHR(self->stat_atopen->st_mode)) { From bb95ac083f694a2c18755f38563b00f71d983c93 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=A9n=C3=A9dikt=20Tran?= <10796600+picnixz@users.noreply.github.com> Date: Sat, 8 Feb 2025 10:43:23 +0100 Subject: [PATCH 15/16] Do not add an underscore to the macro if none is needed. --- Modules/_io/bufferedio.c | 38 +++++++++++++++++----------------- Modules/_io/bytesio.c | 32 ++++++++++++++--------------- Modules/_io/iobase.c | 8 ++++---- Modules/_io/stringio.c | 10 ++++----- Modules/_io/textio.c | 42 +++++++++++++++++++------------------- Modules/_io/winconsoleio.c | 16 +++++++-------- 6 files changed, 73 insertions(+), 73 deletions(-) diff --git a/Modules/_io/bufferedio.c b/Modules/_io/bufferedio.c index 477c98d03ab61d..53c4702f673786 100644 --- a/Modules/_io/bufferedio.c +++ b/Modules/_io/bufferedio.c @@ -261,7 +261,7 @@ typedef struct { PyObject *weakreflist; } buffered; -#define _buffered_CAST(op) ((buffered *)(op)) +#define buffered_CAST(op) ((buffered *)(op)) /* Implementation notes: @@ -403,7 +403,7 @@ _enter_buffered_busy(buffered *self) static int buffered_clear(PyObject *op) { - buffered *self = _buffered_CAST(op); + buffered *self = buffered_CAST(op); self->ok = 0; Py_CLEAR(self->raw); Py_CLEAR(self->dict); @@ -413,7 +413,7 @@ buffered_clear(PyObject *op) static void buffered_dealloc(PyObject *op) { - buffered *self = _buffered_CAST(op); + buffered *self = buffered_CAST(op); PyTypeObject *tp = Py_TYPE(self); self->finalizing = 1; if (_PyIOBase_finalize(op) < 0) @@ -2231,7 +2231,7 @@ typedef struct { PyObject *weakreflist; } rwpair; -#define _rwpair_CAST(op) ((rwpair *)(op)) +#define rwpair_CAST(op) ((rwpair *)(op)) /*[clinic input] _io.BufferedRWPair.__init__ @@ -2284,7 +2284,7 @@ _io_BufferedRWPair___init___impl(rwpair *self, PyObject *reader, static int bufferedrwpair_traverse(PyObject *op, visitproc visit, void *arg) { - rwpair *self = _rwpair_CAST(op); + rwpair *self = rwpair_CAST(op); Py_VISIT(Py_TYPE(self)); Py_VISIT(self->dict); Py_VISIT(self->reader); @@ -2295,7 +2295,7 @@ bufferedrwpair_traverse(PyObject *op, visitproc visit, void *arg) static int bufferedrwpair_clear(PyObject *op) { - rwpair *self = _rwpair_CAST(op); + rwpair *self = rwpair_CAST(op); Py_CLEAR(self->reader); Py_CLEAR(self->writer); Py_CLEAR(self->dict); @@ -2305,7 +2305,7 @@ bufferedrwpair_clear(PyObject *op) static void bufferedrwpair_dealloc(PyObject *op) { - rwpair *self = _rwpair_CAST(op); + rwpair *self = rwpair_CAST(op); PyTypeObject *tp = Py_TYPE(self); _PyObject_GC_UNTRACK(self); if (self->weakreflist != NULL) @@ -2339,70 +2339,70 @@ _forward_call(buffered *self, PyObject *name, PyObject *args) static PyObject * bufferedrwpair_read(PyObject *op, PyObject *args) { - rwpair *self = _rwpair_CAST(op); + rwpair *self = rwpair_CAST(op); return _forward_call(self->reader, &_Py_ID(read), args); } static PyObject * bufferedrwpair_peek(PyObject *op, PyObject *args) { - rwpair *self = _rwpair_CAST(op); + rwpair *self = rwpair_CAST(op); return _forward_call(self->reader, &_Py_ID(peek), args); } static PyObject * bufferedrwpair_read1(PyObject *op, PyObject *args) { - rwpair *self = _rwpair_CAST(op); + rwpair *self = rwpair_CAST(op); return _forward_call(self->reader, &_Py_ID(read1), args); } static PyObject * bufferedrwpair_readinto(PyObject *op, PyObject *args) { - rwpair *self = _rwpair_CAST(op); + rwpair *self = rwpair_CAST(op); return _forward_call(self->reader, &_Py_ID(readinto), args); } static PyObject * bufferedrwpair_readinto1(PyObject *op, PyObject *args) { - rwpair *self = _rwpair_CAST(op); + rwpair *self = rwpair_CAST(op); return _forward_call(self->reader, &_Py_ID(readinto1), args); } static PyObject * bufferedrwpair_write(PyObject *op, PyObject *args) { - rwpair *self = _rwpair_CAST(op); + rwpair *self = rwpair_CAST(op); return _forward_call(self->writer, &_Py_ID(write), args); } static PyObject * bufferedrwpair_flush(PyObject *op, PyObject *Py_UNUSED(dummy)) { - rwpair *self = _rwpair_CAST(op); + rwpair *self = rwpair_CAST(op); return _forward_call(self->writer, &_Py_ID(flush), NULL); } static PyObject * bufferedrwpair_readable(PyObject *op, PyObject *Py_UNUSED(dummy)) { - rwpair *self = _rwpair_CAST(op); + rwpair *self = rwpair_CAST(op); return _forward_call(self->reader, &_Py_ID(readable), NULL); } static PyObject * bufferedrwpair_writable(PyObject *op, PyObject *Py_UNUSED(dummy)) { - rwpair *self = _rwpair_CAST(op); + rwpair *self = rwpair_CAST(op); return _forward_call(self->writer, &_Py_ID(writable), NULL); } static PyObject * bufferedrwpair_close(PyObject *op, PyObject *Py_UNUSED(dummy)) { - rwpair *self = _rwpair_CAST(op); + rwpair *self = rwpair_CAST(op); PyObject *exc = NULL; PyObject *ret = _forward_call(self->writer, &_Py_ID(close), NULL); if (ret == NULL) { @@ -2422,7 +2422,7 @@ bufferedrwpair_close(PyObject *op, PyObject *Py_UNUSED(dummy)) static PyObject * bufferedrwpair_isatty(PyObject *op, PyObject *Py_UNUSED(dummy)) { - rwpair *self = _rwpair_CAST(op); + rwpair *self = rwpair_CAST(op); PyObject *ret = _forward_call(self->writer, &_Py_ID(isatty), NULL); if (ret != Py_False) { @@ -2437,7 +2437,7 @@ bufferedrwpair_isatty(PyObject *op, PyObject *Py_UNUSED(dummy)) static PyObject * bufferedrwpair_closed_get(PyObject *op, void *Py_UNUSED(dummy)) { - rwpair *self = _rwpair_CAST(op); + rwpair *self = rwpair_CAST(op); if (self->writer == NULL) { PyErr_SetString(PyExc_RuntimeError, "the BufferedRWPair object is being garbage-collected"); diff --git a/Modules/_io/bytesio.c b/Modules/_io/bytesio.c index f95fe2508d1f71..dc4e40b9f09a1d 100644 --- a/Modules/_io/bytesio.c +++ b/Modules/_io/bytesio.c @@ -21,14 +21,14 @@ typedef struct { Py_ssize_t exports; } bytesio; -#define _bytesio_CAST(op) ((bytesio *)(op)) +#define bytesio_CAST(op) ((bytesio *)(op)) typedef struct { PyObject_HEAD bytesio *source; } bytesiobuf; -#define _bytesiobuf_CAST(op) ((bytesiobuf *)(op)) +#define bytesiobuf_CAST(op) ((bytesiobuf *)(op)) /* The bytesio object can be in three states: * Py_REFCNT(buf) == 1, exports == 0. @@ -245,7 +245,7 @@ write_bytes(bytesio *self, PyObject *b) static PyObject * bytesio_get_closed(PyObject *op, void *Py_UNUSED(closure)) { - bytesio *self = _bytesio_CAST(op); + bytesio *self = bytesio_CAST(op); if (self->buf == NULL) { Py_RETURN_TRUE; } @@ -628,7 +628,7 @@ static PyObject * bytesio_iternext(PyObject *op) { Py_ssize_t n; - bytesio *self = _bytesio_CAST(op); + bytesio *self = bytesio_CAST(op); CHECK_CLOSED(self); @@ -791,7 +791,7 @@ _io_BytesIO_close_impl(bytesio *self) static PyObject * bytesio_getstate(PyObject *op, PyObject *Py_UNUSED(dummy)) { - bytesio *self = _bytesio_CAST(op); + bytesio *self = bytesio_CAST(op); PyObject *initvalue = _io_BytesIO_getvalue_impl(self); PyObject *dict; PyObject *state; @@ -821,7 +821,7 @@ bytesio_setstate(PyObject *op, PyObject *state) PyObject *position_obj; PyObject *dict; Py_ssize_t pos; - bytesio *self = _bytesio_CAST(op); + bytesio *self = bytesio_CAST(op); assert(state != NULL); @@ -893,7 +893,7 @@ bytesio_setstate(PyObject *op, PyObject *state) static void bytesio_dealloc(PyObject *op) { - bytesio *self = _bytesio_CAST(op); + bytesio *self = bytesio_CAST(op); PyTypeObject *tp = Py_TYPE(self); _PyObject_GC_UNTRACK(self); if (self->exports > 0) { @@ -972,7 +972,7 @@ _io_BytesIO___init___impl(bytesio *self, PyObject *initvalue) static PyObject * bytesio_sizeof(PyObject *op, PyObject *Py_UNUSED(dummy)) { - bytesio *self = _bytesio_CAST(op); + bytesio *self = bytesio_CAST(op); size_t res = _PyObject_SIZE(Py_TYPE(self)); if (self->buf && !SHARED_BUF(self)) { size_t s = _PySys_GetSizeOf(self->buf); @@ -987,7 +987,7 @@ bytesio_sizeof(PyObject *op, PyObject *Py_UNUSED(dummy)) static int bytesio_traverse(PyObject *op, visitproc visit, void *arg) { - bytesio *self = _bytesio_CAST(op); + bytesio *self = bytesio_CAST(op); Py_VISIT(Py_TYPE(self)); Py_VISIT(self->dict); Py_VISIT(self->buf); @@ -997,7 +997,7 @@ bytesio_traverse(PyObject *op, visitproc visit, void *arg) static int bytesio_clear(PyObject *op) { - bytesio *self = _bytesio_CAST(op); + bytesio *self = bytesio_CAST(op); Py_CLEAR(self->dict); if (self->exports == 0) { Py_CLEAR(self->buf); @@ -1079,8 +1079,8 @@ PyType_Spec bytesio_spec = { static int bytesiobuf_getbuffer(PyObject *op, Py_buffer *view, int flags) { - bytesiobuf *obj = _bytesiobuf_CAST(op); - bytesio *b = _bytesio_CAST(obj->source); + bytesiobuf *obj = bytesiobuf_CAST(op); + bytesio *b = bytesio_CAST(obj->source); if (view == NULL) { PyErr_SetString(PyExc_BufferError, @@ -1103,15 +1103,15 @@ bytesiobuf_getbuffer(PyObject *op, Py_buffer *view, int flags) static void bytesiobuf_releasebuffer(PyObject *op, Py_buffer *Py_UNUSED(view)) { - bytesiobuf *obj = _bytesiobuf_CAST(op); - bytesio *b = _bytesio_CAST(obj->source); + bytesiobuf *obj = bytesiobuf_CAST(op); + bytesio *b = bytesio_CAST(obj->source); b->exports--; } static int bytesiobuf_traverse(PyObject *op, visitproc visit, void *arg) { - bytesiobuf *self = _bytesiobuf_CAST(op); + bytesiobuf *self = bytesiobuf_CAST(op); Py_VISIT(Py_TYPE(self)); Py_VISIT(self->source); return 0; @@ -1120,7 +1120,7 @@ bytesiobuf_traverse(PyObject *op, visitproc visit, void *arg) static void bytesiobuf_dealloc(PyObject *op) { - bytesiobuf *self = _bytesiobuf_CAST(op); + bytesiobuf *self = bytesiobuf_CAST(op); PyTypeObject *tp = Py_TYPE(self); /* bpo-31095: UnTrack is needed before calling any callbacks */ PyObject_GC_UnTrack(op); diff --git a/Modules/_io/iobase.c b/Modules/_io/iobase.c index 59e3878ab63c01..7e0822e3350eeb 100644 --- a/Modules/_io/iobase.c +++ b/Modules/_io/iobase.c @@ -35,7 +35,7 @@ typedef struct { PyObject *weakreflist; } iobase; -#define _iobase_CAST(op) ((iobase *)(op)) +#define iobase_CAST(op) ((iobase *)(op)) PyDoc_STRVAR(iobase_doc, "The abstract base class for all I/O classes.\n" @@ -347,7 +347,7 @@ _PyIOBase_finalize(PyObject *self) static int iobase_traverse(PyObject *op, visitproc visit, void *arg) { - iobase *self = _iobase_CAST(op); + iobase *self = iobase_CAST(op); Py_VISIT(Py_TYPE(self)); Py_VISIT(self->dict); return 0; @@ -356,7 +356,7 @@ iobase_traverse(PyObject *op, visitproc visit, void *arg) static int iobase_clear(PyObject *op) { - iobase *self = _iobase_CAST(op); + iobase *self = iobase_CAST(op); Py_CLEAR(self->dict); return 0; } @@ -371,7 +371,7 @@ iobase_dealloc(PyObject *op) However, if the derived class declares a __slots__, those slots are already gone. */ - iobase *self = _iobase_CAST(op); + iobase *self = iobase_CAST(op); if (_PyIOBase_finalize(op) < 0) { /* When called from a heap type's dealloc, the type will be decref'ed on return (see e.g. subtype_dealloc in typeobject.c). */ diff --git a/Modules/_io/stringio.c b/Modules/_io/stringio.c index 949c4ae0e67a6a..9d1bfa3ea05cea 100644 --- a/Modules/_io/stringio.c +++ b/Modules/_io/stringio.c @@ -45,7 +45,7 @@ typedef struct { _PyIO_State *module_state; } stringio; -#define _stringio_CAST(op) ((stringio *)(op)) +#define stringio_CAST(op) ((stringio *)(op)) #define clinic_state() (find_io_state_by_def(Py_TYPE(self))) #include "clinic/stringio.c.h" @@ -407,7 +407,7 @@ static PyObject * stringio_iternext(PyObject *op) { PyObject *line; - stringio *self = _stringio_CAST(op); + stringio *self = stringio_CAST(op); CHECK_INITIALIZED(self); CHECK_CLOSED(self); @@ -595,7 +595,7 @@ _io_StringIO_close_impl(stringio *self) static int stringio_traverse(PyObject *op, visitproc visit, void *arg) { - stringio *self = _stringio_CAST(op); + stringio *self = stringio_CAST(op); Py_VISIT(Py_TYPE(self)); Py_VISIT(self->readnl); Py_VISIT(self->writenl); @@ -607,7 +607,7 @@ stringio_traverse(PyObject *op, visitproc visit, void *arg) static int stringio_clear(PyObject *op) { - stringio *self = _stringio_CAST(op); + stringio *self = stringio_CAST(op); Py_CLEAR(self->readnl); Py_CLEAR(self->writenl); Py_CLEAR(self->decoder); @@ -618,7 +618,7 @@ stringio_clear(PyObject *op) static void stringio_dealloc(PyObject *op) { - stringio *self = _stringio_CAST(op); + stringio *self = stringio_CAST(op); PyTypeObject *tp = Py_TYPE(self); _PyObject_GC_UNTRACK(self); self->ok = 0; diff --git a/Modules/_io/textio.c b/Modules/_io/textio.c index 92bf3c45583f60..935aaab20a031f 100644 --- a/Modules/_io/textio.c +++ b/Modules/_io/textio.c @@ -223,7 +223,7 @@ struct nldecoder_object { unsigned int seennl: 3; }; -#define _nldecoder_object_CAST(op) ((nldecoder_object *)(op)) +#define nldecoder_object_CAST(op) ((nldecoder_object *)(op)) /*[clinic input] _io.IncrementalNewlineDecoder.__init__ @@ -267,7 +267,7 @@ _io_IncrementalNewlineDecoder___init___impl(nldecoder_object *self, static int incrementalnewlinedecoder_traverse(PyObject *op, visitproc visit, void *arg) { - nldecoder_object *self = _nldecoder_object_CAST(op); + nldecoder_object *self = nldecoder_object_CAST(op); Py_VISIT(Py_TYPE(self)); Py_VISIT(self->decoder); Py_VISIT(self->errors); @@ -277,7 +277,7 @@ incrementalnewlinedecoder_traverse(PyObject *op, visitproc visit, void *arg) static int incrementalnewlinedecoder_clear(PyObject *op) { - nldecoder_object *self = _nldecoder_object_CAST(op); + nldecoder_object *self = nldecoder_object_CAST(op); Py_CLEAR(self->decoder); Py_CLEAR(self->errors); return 0; @@ -286,7 +286,7 @@ incrementalnewlinedecoder_clear(PyObject *op) static void incrementalnewlinedecoder_dealloc(PyObject *op) { - nldecoder_object *self = _nldecoder_object_CAST(op); + nldecoder_object *self = nldecoder_object_CAST(op); PyTypeObject *tp = Py_TYPE(self); _PyObject_GC_UNTRACK(self); (void)incrementalnewlinedecoder_clear(op); @@ -327,7 +327,7 @@ _PyIncrementalNewlineDecoder_decode(PyObject *myself, { PyObject *output; Py_ssize_t output_len; - nldecoder_object *self = _nldecoder_object_CAST(myself); + nldecoder_object *self = nldecoder_object_CAST(myself); CHECK_INITIALIZED_DECODER(self); @@ -631,7 +631,7 @@ _io_IncrementalNewlineDecoder_reset_impl(nldecoder_object *self) static PyObject * incrementalnewlinedecoder_newlines_get(PyObject *op, void *Py_UNUSED(context)) { - nldecoder_object *self = _nldecoder_object_CAST(op); + nldecoder_object *self = nldecoder_object_CAST(op); CHECK_INITIALIZED_DECODER(self); switch (self->seennl) { @@ -720,7 +720,7 @@ struct textio _PyIO_State *state; }; -#define _textio_CAST(op) ((textio *)(op)) +#define textio_CAST(op) ((textio *)(op)) static void textiowrapper_set_decoded_chars(textio *self, PyObject *chars); @@ -731,28 +731,28 @@ textiowrapper_set_decoded_chars(textio *self, PyObject *chars); static PyObject * ascii_encode(PyObject *op, PyObject *text) { - textio *self = _textio_CAST(op); + textio *self = textio_CAST(op); return _PyUnicode_AsASCIIString(text, PyUnicode_AsUTF8(self->errors)); } static PyObject * utf16be_encode(PyObject *op, PyObject *text) { - textio *self = _textio_CAST(op); + textio *self = textio_CAST(op); return _PyUnicode_EncodeUTF16(text, PyUnicode_AsUTF8(self->errors), 1); } static PyObject * utf16le_encode(PyObject *op, PyObject *text) { - textio *self = _textio_CAST(op); + textio *self = textio_CAST(op); return _PyUnicode_EncodeUTF16(text, PyUnicode_AsUTF8(self->errors), -1); } static PyObject * utf16_encode(PyObject *op, PyObject *text) { - textio *self = _textio_CAST(op); + textio *self = textio_CAST(op); if (!self->encoding_start_of_stream) { /* Skip the BOM and use native byte ordering */ #if PY_BIG_ENDIAN @@ -767,21 +767,21 @@ utf16_encode(PyObject *op, PyObject *text) static PyObject * utf32be_encode(PyObject *op, PyObject *text) { - textio *self = _textio_CAST(op); + textio *self = textio_CAST(op); return _PyUnicode_EncodeUTF32(text, PyUnicode_AsUTF8(self->errors), 1); } static PyObject * utf32le_encode(PyObject *op, PyObject *text) { - textio *self = _textio_CAST(op); + textio *self = textio_CAST(op); return _PyUnicode_EncodeUTF32(text, PyUnicode_AsUTF8(self->errors), -1); } static PyObject * utf32_encode(PyObject *op, PyObject *text) { - textio *self = _textio_CAST(op); + textio *self = textio_CAST(op); if (!self->encoding_start_of_stream) { /* Skip the BOM and use native byte ordering */ #if PY_BIG_ENDIAN @@ -796,14 +796,14 @@ utf32_encode(PyObject *op, PyObject *text) static PyObject * utf8_encode(PyObject *op, PyObject *text) { - textio *self = _textio_CAST(op); + textio *self = textio_CAST(op); return _PyUnicode_AsUTF8String(text, PyUnicode_AsUTF8(self->errors)); } static PyObject * latin1_encode(PyObject *op, PyObject *text) { - textio *self = _textio_CAST(op); + textio *self = textio_CAST(op); return _PyUnicode_AsLatin1String(text, PyUnicode_AsUTF8(self->errors)); } @@ -1442,7 +1442,7 @@ _io_TextIOWrapper_reconfigure_impl(textio *self, PyObject *encoding, static int textiowrapper_clear(PyObject *op) { - textio *self = _textio_CAST(op); + textio *self = textio_CAST(op); self->ok = 0; Py_CLEAR(self->buffer); Py_CLEAR(self->encoding); @@ -1462,7 +1462,7 @@ textiowrapper_clear(PyObject *op) static void textiowrapper_dealloc(PyObject *op) { - textio *self = _textio_CAST(op); + textio *self = textio_CAST(op); PyTypeObject *tp = Py_TYPE(self); self->finalizing = 1; if (_PyIOBase_finalize(op) < 0) @@ -1479,7 +1479,7 @@ textiowrapper_dealloc(PyObject *op) static int textiowrapper_traverse(PyObject *op, visitproc visit, void *arg) { - textio *self = _textio_CAST(op); + textio *self = textio_CAST(op); Py_VISIT(Py_TYPE(self)); Py_VISIT(self->buffer); Py_VISIT(self->encoding); @@ -2977,7 +2977,7 @@ textiowrapper_repr(PyObject *op) { PyObject *nameobj, *modeobj, *res, *s; int status; - textio *self = _textio_CAST(op); + textio *self = textio_CAST(op); const char *type_name = Py_TYPE(self)->tp_name; CHECK_INITIALIZED(self); @@ -3177,7 +3177,7 @@ static PyObject * textiowrapper_iternext(PyObject *op) { PyObject *line; - textio *self = _textio_CAST(op); + textio *self = textio_CAST(op); CHECK_ATTACHED(self); diff --git a/Modules/_io/winconsoleio.c b/Modules/_io/winconsoleio.c index 48886c3b3f507b..27c320ed073103 100644 --- a/Modules/_io/winconsoleio.c +++ b/Modules/_io/winconsoleio.c @@ -221,7 +221,7 @@ typedef struct { wchar_t wbuf; } winconsoleio; -#define _winconsoleio_CAST(op) ((winconsoleio *)(op)) +#define winconsoleio_CAST(op) ((winconsoleio *)(op)) int _PyWindowsConsoleIO_closed(PyObject *self) @@ -496,7 +496,7 @@ _io__WindowsConsoleIO___init___impl(winconsoleio *self, PyObject *nameobj, static int winconsoleio_traverse(PyObject *op, visitproc visit, void *arg) { - winconsoleio *self = _winconsoleio_CAST(op); + winconsoleio *self = winconsoleio_CAST(op); Py_VISIT(Py_TYPE(self)); Py_VISIT(self->dict); return 0; @@ -505,7 +505,7 @@ winconsoleio_traverse(PyObject *op, visitproc visit, void *arg) static int winconsoleio_clear(PyObject *op) { - winconsoleio *self = _winconsoleio_CAST(op); + winconsoleio *self = winconsoleio_CAST(op); Py_CLEAR(self->dict); return 0; } @@ -513,7 +513,7 @@ winconsoleio_clear(PyObject *op) static void winconsoleio_dealloc(PyObject *op) { - winconsoleio *self = _winconsoleio_CAST(op); + winconsoleio *self = winconsoleio_CAST(op); PyTypeObject *tp = Py_TYPE(self); self->finalizing = 1; if (_PyIOBase_finalize(op) < 0) @@ -1144,7 +1144,7 @@ _io__WindowsConsoleIO_write_impl(winconsoleio *self, PyTypeObject *cls, static PyObject * winconsoleio_repr(PyObject *op) { - winconsoleio *self = _winconsoleio_CAST(op); + winconsoleio *self = winconsoleio_CAST(op); const char *type_name = Py_TYPE(self)->tp_name; if (self->fd == -1) { @@ -1205,21 +1205,21 @@ static PyMethodDef winconsoleio_methods[] = { static PyObject * get_closed(PyObject *op, void *Py_UNUSED(closure)) { - winconsoleio *self = _winconsoleio_CAST(op); + winconsoleio *self = winconsoleio_CAST(op); return PyBool_FromLong((long)(self->fd == -1)); } static PyObject * get_closefd(PyObject *op, void *Py_UNUSED(closure)) { - winconsoleio *self = _winconsoleio_CAST(op); + winconsoleio *self = winconsoleio_CAST(op); return PyBool_FromLong((long)(self->closefd)); } static PyObject * get_mode(PyObject *op, void *Py_UNUSED(closure)) { - winconsoleio *self = _winconsoleio_CAST(op); + winconsoleio *self = winconsoleio_CAST(op); return PyUnicode_FromString(self->readable ? "rb" : "wb"); } From 2340cae3030ee80583c302880c3ee87ecde929b9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=A9n=C3=A9dikt=20Tran?= <10796600+picnixz@users.noreply.github.com> Date: Sat, 8 Feb 2025 10:43:32 +0100 Subject: [PATCH 16/16] Do Do not use `_` + capital letter in cast macros as it is also UB. --- Modules/_io/fileio.c | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/Modules/_io/fileio.c b/Modules/_io/fileio.c index 3a098fd76b728f..89f1cfe6b20935 100644 --- a/Modules/_io/fileio.c +++ b/Modules/_io/fileio.c @@ -83,7 +83,7 @@ typedef struct { } fileio; #define PyFileIO_Check(state, op) (PyObject_TypeCheck((op), state->PyFileIO_Type)) -#define _PyFileIO_CAST(op) _Py_CAST(fileio*, (op)) +#define PyFileIO_CAST(op) ((fileio *)(op)) /* Forward declarations */ static PyObject* portable_lseek(fileio *self, PyObject *posobj, int whence, bool suppress_pipe_error); @@ -91,7 +91,7 @@ static PyObject* portable_lseek(fileio *self, PyObject *posobj, int whence, bool int _PyFileIO_closed(PyObject *self) { - return (_PyFileIO_CAST(self)->fd < 0); + return (PyFileIO_CAST(self)->fd < 0); } /* Because this can call arbitrary code, it shouldn't be called when @@ -100,7 +100,7 @@ _PyFileIO_closed(PyObject *self) static PyObject * fileio_dealloc_warn(PyObject *op, PyObject *source) { - fileio *self = _PyFileIO_CAST(op); + fileio *self = PyFileIO_CAST(op); if (self->fd >= 0 && self->closefd) { PyObject *exc = PyErr_GetRaisedException(); if (PyErr_ResourceWarning(source, 1, "unclosed file %R", source)) { @@ -542,7 +542,7 @@ _io_FileIO___init___impl(fileio *self, PyObject *nameobj, const char *mode, static int fileio_traverse(PyObject *op, visitproc visit, void *arg) { - fileio *self = _PyFileIO_CAST(op); + fileio *self = PyFileIO_CAST(op); Py_VISIT(Py_TYPE(self)); Py_VISIT(self->dict); return 0; @@ -551,7 +551,7 @@ fileio_traverse(PyObject *op, visitproc visit, void *arg) static int fileio_clear(PyObject *op) { - fileio *self = _PyFileIO_CAST(op); + fileio *self = PyFileIO_CAST(op); Py_CLEAR(self->dict); return 0; } @@ -559,7 +559,7 @@ fileio_clear(PyObject *op) static void fileio_dealloc(PyObject *op) { - fileio *self = _PyFileIO_CAST(op); + fileio *self = PyFileIO_CAST(op); self->finalizing = 1; if (_PyIOBase_finalize(op) < 0) { return; @@ -1161,7 +1161,7 @@ mode_string(fileio *self) static PyObject * fileio_repr(PyObject *op) { - fileio *self = _PyFileIO_CAST(op); + fileio *self = PyFileIO_CAST(op); const char *type_name = Py_TYPE(self)->tp_name; if (self->fd < 0) { @@ -1229,7 +1229,7 @@ _io_FileIO_isatty_impl(fileio *self) static PyObject * _io_FileIO_isatty_open_only(PyObject *op, PyObject *Py_UNUSED(dummy)) { - fileio *self = _PyFileIO_CAST(op); + fileio *self = PyFileIO_CAST(op); if (self->stat_atopen != NULL && !S_ISCHR(self->stat_atopen->st_mode)) { Py_RETURN_FALSE; } @@ -1264,28 +1264,28 @@ static PyMethodDef fileio_methods[] = { static PyObject * fileio_get_closed(PyObject *op, void *closure) { - fileio *self = _PyFileIO_CAST(op); + fileio *self = PyFileIO_CAST(op); return PyBool_FromLong((long)(self->fd < 0)); } static PyObject * fileio_get_closefd(PyObject *op, void *closure) { - fileio *self = _PyFileIO_CAST(op); + fileio *self = PyFileIO_CAST(op); return PyBool_FromLong((long)(self->closefd)); } static PyObject * fileio_get_mode(PyObject *op, void *closure) { - fileio *self = _PyFileIO_CAST(op); + fileio *self = PyFileIO_CAST(op); return PyUnicode_FromString(mode_string(self)); } static PyObject * fileio_get_blksize(PyObject *op, void *closure) { - fileio *self = _PyFileIO_CAST(op); + fileio *self = PyFileIO_CAST(op); #ifdef HAVE_STRUCT_STAT_ST_BLKSIZE if (self->stat_atopen != NULL && self->stat_atopen->st_blksize > 1) { return PyLong_FromLong(self->stat_atopen->st_blksize);