Skip to content

Commit 8522f8b

Browse files
authored
gh-111178: fix UBSan failures in Modules/_csv.c (GH-128243)
Also: suppress unused return values
1 parent b4f799b commit 8522f8b

File tree

1 file changed

+48
-28
lines changed

1 file changed

+48
-28
lines changed

Modules/_csv.c

+48-28
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ _csv_traverse(PyObject *module, visitproc visit, void *arg)
7777
static void
7878
_csv_free(void *module)
7979
{
80-
_csv_clear((PyObject *)module);
80+
(void)_csv_clear((PyObject *)module);
8181
}
8282

8383
typedef enum {
@@ -151,6 +151,10 @@ typedef struct {
151151
PyObject *error_obj; /* cached error object */
152152
} WriterObj;
153153

154+
#define _DialectObj_CAST(op) ((DialectObj *)(op))
155+
#define _ReaderObj_CAST(op) ((ReaderObj *)(op))
156+
#define _WriterObj_CAST(op) ((WriterObj *)(op))
157+
154158
/*
155159
* DIALECT class
156160
*/
@@ -176,32 +180,37 @@ get_char_or_None(Py_UCS4 c)
176180
}
177181

178182
static PyObject *
179-
Dialect_get_lineterminator(DialectObj *self, void *Py_UNUSED(ignored))
183+
Dialect_get_lineterminator(PyObject *op, void *Py_UNUSED(ignored))
180184
{
185+
DialectObj *self = _DialectObj_CAST(op);
181186
return Py_XNewRef(self->lineterminator);
182187
}
183188

184189
static PyObject *
185-
Dialect_get_delimiter(DialectObj *self, void *Py_UNUSED(ignored))
190+
Dialect_get_delimiter(PyObject *op, void *Py_UNUSED(ignored))
186191
{
192+
DialectObj *self = _DialectObj_CAST(op);
187193
return get_char_or_None(self->delimiter);
188194
}
189195

190196
static PyObject *
191-
Dialect_get_escapechar(DialectObj *self, void *Py_UNUSED(ignored))
197+
Dialect_get_escapechar(PyObject *op, void *Py_UNUSED(ignored))
192198
{
199+
DialectObj *self = _DialectObj_CAST(op);
193200
return get_char_or_None(self->escapechar);
194201
}
195202

196203
static PyObject *
197-
Dialect_get_quotechar(DialectObj *self, void *Py_UNUSED(ignored))
204+
Dialect_get_quotechar(PyObject *op, void *Py_UNUSED(ignored))
198205
{
206+
DialectObj *self = _DialectObj_CAST(op);
199207
return get_char_or_None(self->quotechar);
200208
}
201209

202210
static PyObject *
203-
Dialect_get_quoting(DialectObj *self, void *Py_UNUSED(ignored))
211+
Dialect_get_quoting(PyObject *op, void *Py_UNUSED(ignored))
204212
{
213+
DialectObj *self = _DialectObj_CAST(op);
205214
return PyLong_FromLong(self->quoting);
206215
}
207216

@@ -371,16 +380,16 @@ static struct PyMemberDef Dialect_memberlist[] = {
371380
#undef D_OFF
372381

373382
static PyGetSetDef Dialect_getsetlist[] = {
374-
{ "delimiter", (getter)Dialect_get_delimiter},
375-
{ "escapechar", (getter)Dialect_get_escapechar},
376-
{ "lineterminator", (getter)Dialect_get_lineterminator},
377-
{ "quotechar", (getter)Dialect_get_quotechar},
378-
{ "quoting", (getter)Dialect_get_quoting},
383+
{"delimiter", Dialect_get_delimiter},
384+
{"escapechar", Dialect_get_escapechar},
385+
{"lineterminator", Dialect_get_lineterminator},
386+
{"quotechar", Dialect_get_quotechar},
387+
{"quoting", Dialect_get_quoting},
379388
{NULL},
380389
};
381390

382391
static void
383-
Dialect_dealloc(DialectObj *self)
392+
Dialect_dealloc(PyObject *self)
384393
{
385394
PyTypeObject *tp = Py_TYPE(self);
386395
PyObject_GC_UnTrack(self);
@@ -594,15 +603,17 @@ PyDoc_STRVAR(Dialect_Type_doc,
594603
"The Dialect type records CSV parsing and generation options.\n");
595604

596605
static int
597-
Dialect_clear(DialectObj *self)
606+
Dialect_clear(PyObject *op)
598607
{
608+
DialectObj *self = _DialectObj_CAST(op);
599609
Py_CLEAR(self->lineterminator);
600610
return 0;
601611
}
602612

603613
static int
604-
Dialect_traverse(DialectObj *self, visitproc visit, void *arg)
614+
Dialect_traverse(PyObject *op, visitproc visit, void *arg)
605615
{
616+
DialectObj *self = _DialectObj_CAST(op);
606617
Py_VISIT(self->lineterminator);
607618
Py_VISIT(Py_TYPE(self));
608619
return 0;
@@ -916,8 +927,10 @@ parse_reset(ReaderObj *self)
916927
}
917928

918929
static PyObject *
919-
Reader_iternext(ReaderObj *self)
930+
Reader_iternext(PyObject *op)
920931
{
932+
ReaderObj *self = _ReaderObj_CAST(op);
933+
921934
PyObject *fields = NULL;
922935
Py_UCS4 c;
923936
Py_ssize_t pos, linelen;
@@ -982,11 +995,12 @@ Reader_iternext(ReaderObj *self)
982995
}
983996

984997
static void
985-
Reader_dealloc(ReaderObj *self)
998+
Reader_dealloc(PyObject *op)
986999
{
1000+
ReaderObj *self = _ReaderObj_CAST(op);
9871001
PyTypeObject *tp = Py_TYPE(self);
9881002
PyObject_GC_UnTrack(self);
989-
tp->tp_clear((PyObject *)self);
1003+
(void)tp->tp_clear(op);
9901004
if (self->field != NULL) {
9911005
PyMem_Free(self->field);
9921006
self->field = NULL;
@@ -996,8 +1010,9 @@ Reader_dealloc(ReaderObj *self)
9961010
}
9971011

9981012
static int
999-
Reader_traverse(ReaderObj *self, visitproc visit, void *arg)
1013+
Reader_traverse(PyObject *op, visitproc visit, void *arg)
10001014
{
1015+
ReaderObj *self = _ReaderObj_CAST(op);
10011016
Py_VISIT(self->dialect);
10021017
Py_VISIT(self->input_iter);
10031018
Py_VISIT(self->fields);
@@ -1006,8 +1021,9 @@ Reader_traverse(ReaderObj *self, visitproc visit, void *arg)
10061021
}
10071022

10081023
static int
1009-
Reader_clear(ReaderObj *self)
1024+
Reader_clear(PyObject *op)
10101025
{
1026+
ReaderObj *self = _ReaderObj_CAST(op);
10111027
Py_CLEAR(self->dialect);
10121028
Py_CLEAR(self->input_iter);
10131029
Py_CLEAR(self->fields);
@@ -1303,8 +1319,9 @@ PyDoc_STRVAR(csv_writerow_doc,
13031319
"elements will be converted to string.");
13041320

13051321
static PyObject *
1306-
csv_writerow(WriterObj *self, PyObject *seq)
1322+
csv_writerow(PyObject *op, PyObject *seq)
13071323
{
1324+
WriterObj *self = _WriterObj_CAST(op);
13081325
DialectObj *dialect = self->dialect;
13091326
PyObject *iter, *field, *line, *result;
13101327
bool null_field = false;
@@ -1412,7 +1429,7 @@ PyDoc_STRVAR(csv_writerows_doc,
14121429
"elements will be converted to string.");
14131430

14141431
static PyObject *
1415-
csv_writerows(WriterObj *self, PyObject *seqseq)
1432+
csv_writerows(PyObject *self, PyObject *seqseq)
14161433
{
14171434
PyObject *row_iter, *row_obj, *result;
14181435

@@ -1437,9 +1454,9 @@ csv_writerows(WriterObj *self, PyObject *seqseq)
14371454
}
14381455

14391456
static struct PyMethodDef Writer_methods[] = {
1440-
{ "writerow", (PyCFunction)csv_writerow, METH_O, csv_writerow_doc},
1441-
{ "writerows", (PyCFunction)csv_writerows, METH_O, csv_writerows_doc},
1442-
{ NULL, NULL }
1457+
{"writerow", csv_writerow, METH_O, csv_writerow_doc},
1458+
{"writerows", csv_writerows, METH_O, csv_writerows_doc},
1459+
{NULL, NULL, 0, NULL} /* sentinel */
14431460
};
14441461

14451462
#define W_OFF(x) offsetof(WriterObj, x)
@@ -1452,8 +1469,9 @@ static struct PyMemberDef Writer_memberlist[] = {
14521469
#undef W_OFF
14531470

14541471
static int
1455-
Writer_traverse(WriterObj *self, visitproc visit, void *arg)
1472+
Writer_traverse(PyObject *op, visitproc visit, void *arg)
14561473
{
1474+
WriterObj *self = _WriterObj_CAST(op);
14571475
Py_VISIT(self->dialect);
14581476
Py_VISIT(self->write);
14591477
Py_VISIT(self->error_obj);
@@ -1462,20 +1480,22 @@ Writer_traverse(WriterObj *self, visitproc visit, void *arg)
14621480
}
14631481

14641482
static int
1465-
Writer_clear(WriterObj *self)
1483+
Writer_clear(PyObject *op)
14661484
{
1485+
WriterObj *self = _WriterObj_CAST(op);
14671486
Py_CLEAR(self->dialect);
14681487
Py_CLEAR(self->write);
14691488
Py_CLEAR(self->error_obj);
14701489
return 0;
14711490
}
14721491

14731492
static void
1474-
Writer_dealloc(WriterObj *self)
1493+
Writer_dealloc(PyObject *op)
14751494
{
1495+
WriterObj *self = _WriterObj_CAST(op);
14761496
PyTypeObject *tp = Py_TYPE(self);
14771497
PyObject_GC_UnTrack(self);
1478-
tp->tp_clear((PyObject *)self);
1498+
tp->tp_clear(op);
14791499
if (self->rec != NULL) {
14801500
PyMem_Free(self->rec);
14811501
}

0 commit comments

Comments
 (0)