gh-111178: fix UBSan failures in Modules/_io/*.c (GH-129083)

* fix UBSan failures for `buffered`, `rwpair`, `bytesio`, `bytesiobuf`, `iobase`, `stringio`, `nldecoder_object`, `textio`, `winconsoleio`

* arg names: use 'dummy' for NOARGS method and 'args' for others
This commit is contained in:
Bénédikt Tran
2025-02-08 14:21:32 +01:00
committed by GitHub
parent 421ea1291d
commit 1988003625
7 changed files with 230 additions and 163 deletions

View File

@@ -261,6 +261,8 @@ typedef struct {
PyObject *weakreflist;
} buffered;
#define buffered_CAST(op) ((buffered *)(op))
/*
Implementation notes:
@@ -399,8 +401,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 +411,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 +430,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(self);
Py_DECREF(tp);
}
@@ -2227,6 +2231,8 @@ typedef struct {
PyObject *weakreflist;
} rwpair;
#define rwpair_CAST(op) ((rwpair *)(op))
/*[clinic input]
_io.BufferedRWPair.__init__
reader: object
@@ -2276,8 +2282,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);
@@ -2286,8 +2293,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);
@@ -2295,14 +2303,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);
}
@@ -2328,62 +2337,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(dummy))
{
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(dummy))
{
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(dummy))
{
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(dummy))
{
rwpair *self = rwpair_CAST(op);
PyObject *exc = NULL;
PyObject *ret = _forward_call(self->writer, &_Py_ID(close), NULL);
if (ret == NULL) {
@@ -2401,8 +2420,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(dummy))
{
rwpair *self = rwpair_CAST(op);
PyObject *ret = _forward_call(self->writer, &_Py_ID(isatty), NULL);
if (ret != Py_False) {
@@ -2415,8 +2435,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(dummy))
{
rwpair *self = rwpair_CAST(op);
if (self->writer == NULL) {
PyErr_SetString(PyExc_RuntimeError,
"the BufferedRWPair object is being garbage-collected");
@@ -2633,20 +2654,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}
};
@@ -2658,7 +2679,7 @@ static PyMemberDef bufferedrwpair_members[] = {
};
static PyGetSetDef bufferedrwpair_getset[] = {
{"closed", (getter)bufferedrwpair_closed_get, NULL, NULL},
{"closed", bufferedrwpair_closed_get, NULL, NULL},
{NULL}
};

View File

@@ -21,11 +21,15 @@ typedef struct {
Py_ssize_t exports;
} bytesio;
#define bytesio_CAST(op) ((bytesio *)(op))
typedef struct {
PyObject_HEAD
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,
@@ -239,8 +243,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(closure))
{
bytesio *self = bytesio_CAST(op);
if (self->buf == NULL) {
Py_RETURN_TRUE;
}
@@ -620,9 +625,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 +789,9 @@ _io_BytesIO_close_impl(bytesio *self)
*/
static PyObject *
bytesio_getstate(bytesio *self, PyObject *Py_UNUSED(ignored))
bytesio_getstate(PyObject *op, PyObject *Py_UNUSED(dummy))
{
bytesio *self = bytesio_CAST(op);
PyObject *initvalue = _io_BytesIO_getvalue_impl(self);
PyObject *dict;
PyObject *state;
@@ -808,12 +815,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,8 +891,9 @@ 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);
if (self->exports > 0) {
@@ -895,7 +904,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 +970,9 @@ _io_BytesIO___init___impl(bytesio *self, PyObject *initvalue)
}
static PyObject *
bytesio_sizeof(bytesio *self, void *unused)
bytesio_sizeof(PyObject *op, PyObject *Py_UNUSED(dummy))
{
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 +985,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 +995,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 +1011,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 +1035,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 */
};
@@ -1065,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,
@@ -1080,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++;
@@ -1088,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);

View File

@@ -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) {
@@ -1227,9 +1227,9 @@ _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);
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);

View File

@@ -35,6 +35,8 @@ typedef struct {
PyObject *weakreflist;
} iobase;
#define iobase_CAST(op) ((iobase *)(op))
PyDoc_STRVAR(iobase_doc,
"The abstract base class for all I/O classes.\n"
"\n"
@@ -343,16 +345,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;
}
@@ -360,14 +364,15 @@ iobase_clear(iobase *self)
/* Destructor */
static void
iobase_dealloc(iobase *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.
*/
if (_PyIOBase_finalize((PyObject *) 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)) {
@@ -378,9 +383,9 @@ iobase_dealloc(iobase *self)
PyTypeObject *tp = Py_TYPE(self);
_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);
}
@@ -853,7 +858,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}
};

View File

@@ -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
@@ -402,9 +404,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);
@@ -416,8 +419,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, "
@@ -591,8 +593,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);
@@ -602,8 +605,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);
@@ -612,8 +616,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;
@@ -622,9 +627,9 @@ stringio_dealloc(stringio *self)
self->buf = NULL;
}
PyUnicodeWriter_Discard(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);

View File

@@ -223,6 +223,8 @@ struct nldecoder_object {
unsigned int seennl: 3;
};
#define nldecoder_object_CAST(op) ((nldecoder_object *)(op))
/*[clinic input]
_io.IncrementalNewlineDecoder.__init__
decoder: object
@@ -263,9 +265,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 +275,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 +327,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 +629,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) {
@@ -652,8 +657,7 @@ incrementalnewlinedecoder_newlines_get(nldecoder_object *self, void *context)
/* TextIOWrapper */
typedef PyObject *
(*encodefunc_t)(PyObject *, PyObject *);
typedef PyObject *(*encodefunc_t)(PyObject *, PyObject *);
struct textio
{
@@ -716,6 +720,8 @@ struct textio
_PyIO_State *state;
};
#define textio_CAST(op) ((textio *)(op))
static void
textiowrapper_set_decoded_chars(textio *self, PyObject *chars);
@@ -723,78 +729,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));
}
@@ -802,9 +811,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 */
@@ -815,15 +822,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}
};
@@ -1433,8 +1440,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);
@@ -1452,24 +1460,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);
@@ -2963,10 +2973,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);
@@ -2975,7 +2986,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,
@@ -2984,7 +2995,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;
}
@@ -3000,7 +3011,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) {
@@ -3016,14 +3027,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;
}
@@ -3163,9 +3174,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);
@@ -3175,8 +3187,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, "
@@ -3313,7 +3324,7 @@ static PyMethodDef incrementalnewlinedecoder_methods[] = {
};
static PyGetSetDef incrementalnewlinedecoder_getset[] = {
{"newlines", (getter)incrementalnewlinedecoder_newlines_get, NULL, NULL},
{"newlines", incrementalnewlinedecoder_newlines_get, NULL, NULL},
{NULL}
};

View File

@@ -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 @@ done:
}
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},
};