Skip to content

Commit 31ad8b6

Browse files
authored
gh-111178: fix UBSan failures in Modules/_jsonmodule.c (GH-129781)
Fix UBSan failures for `PyScannerObject`, fix UBSan failures for `PyEncoderObject`
1 parent ef8eeca commit 31ad8b6

File tree

1 file changed

+27
-16
lines changed

1 file changed

+27
-16
lines changed

Modules/_json.c

Lines changed: 27 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,8 @@ typedef struct _PyScannerObject {
2727
PyObject *parse_constant;
2828
} PyScannerObject;
2929

30+
#define PyScannerObject_CAST(op) ((PyScannerObject *)(op))
31+
3032
static PyMemberDef scanner_members[] = {
3133
{"strict", Py_T_BOOL, offsetof(PyScannerObject, strict), Py_READONLY, "strict"},
3234
{"object_hook", _Py_T_OBJECT, offsetof(PyScannerObject, object_hook), Py_READONLY, "object_hook"},
@@ -51,6 +53,8 @@ typedef struct _PyEncoderObject {
5153
PyCFunction fast_encode;
5254
} PyEncoderObject;
5355

56+
#define PyEncoderObject_CAST(op) ((PyEncoderObject *)(op))
57+
5458
static PyMemberDef encoder_members[] = {
5559
{"markers", _Py_T_OBJECT, offsetof(PyEncoderObject, markers), Py_READONLY, "markers"},
5660
{"default", _Py_T_OBJECT, offsetof(PyEncoderObject, defaultfn), Py_READONLY, "default"},
@@ -69,6 +73,7 @@ static PyObject *
6973
ascii_escape_unicode(PyObject *pystr);
7074
static PyObject *
7175
py_encode_basestring_ascii(PyObject* Py_UNUSED(self), PyObject *pystr);
76+
7277
static PyObject *
7378
scan_once_unicode(PyScannerObject *s, PyObject *memo, PyObject *pystr, Py_ssize_t idx, Py_ssize_t *next_idx_ptr);
7479
static PyObject *
@@ -78,13 +83,14 @@ scanner_new(PyTypeObject *type, PyObject *args, PyObject *kwds);
7883
static void
7984
scanner_dealloc(PyObject *self);
8085
static int
81-
scanner_clear(PyScannerObject *self);
86+
scanner_clear(PyObject *self);
87+
8288
static PyObject *
8389
encoder_new(PyTypeObject *type, PyObject *args, PyObject *kwds);
8490
static void
8591
encoder_dealloc(PyObject *self);
8692
static int
87-
encoder_clear(PyEncoderObject *self);
93+
encoder_clear(PyObject *self);
8894
static int
8995
encoder_listencode_list(PyEncoderObject *s, PyUnicodeWriter *writer, PyObject *seq, Py_ssize_t indent_level, PyObject *indent_cache);
9096
static int
@@ -626,14 +632,15 @@ scanner_dealloc(PyObject *self)
626632
PyTypeObject *tp = Py_TYPE(self);
627633
/* bpo-31095: UnTrack is needed before calling any callbacks */
628634
PyObject_GC_UnTrack(self);
629-
scanner_clear((PyScannerObject *)self);
635+
(void)scanner_clear(self);
630636
tp->tp_free(self);
631637
Py_DECREF(tp);
632638
}
633639

634640
static int
635-
scanner_traverse(PyScannerObject *self, visitproc visit, void *arg)
641+
scanner_traverse(PyObject *op, visitproc visit, void *arg)
636642
{
643+
PyScannerObject *self = PyScannerObject_CAST(op);
637644
Py_VISIT(Py_TYPE(self));
638645
Py_VISIT(self->object_hook);
639646
Py_VISIT(self->object_pairs_hook);
@@ -644,8 +651,9 @@ scanner_traverse(PyScannerObject *self, visitproc visit, void *arg)
644651
}
645652

646653
static int
647-
scanner_clear(PyScannerObject *self)
654+
scanner_clear(PyObject *op)
648655
{
656+
PyScannerObject *self = PyScannerObject_CAST(op);
649657
Py_CLEAR(self->object_hook);
650658
Py_CLEAR(self->object_pairs_hook);
651659
Py_CLEAR(self->parse_float);
@@ -1115,7 +1123,7 @@ scan_once_unicode(PyScannerObject *s, PyObject *memo, PyObject *pystr, Py_ssize_
11151123
}
11161124

11171125
static PyObject *
1118-
scanner_call(PyScannerObject *self, PyObject *args, PyObject *kwds)
1126+
scanner_call(PyObject *self, PyObject *args, PyObject *kwds)
11191127
{
11201128
/* Python callable interface to scan_once_{str,unicode} */
11211129
PyObject *pystr;
@@ -1137,7 +1145,8 @@ scanner_call(PyScannerObject *self, PyObject *args, PyObject *kwds)
11371145
if (memo == NULL) {
11381146
return NULL;
11391147
}
1140-
rval = scan_once_unicode(self, memo, pystr, idx, &next_idx);
1148+
rval = scan_once_unicode(PyScannerObject_CAST(self),
1149+
memo, pystr, idx, &next_idx);
11411150
Py_DECREF(memo);
11421151
if (rval == NULL)
11431152
return NULL;
@@ -1252,8 +1261,7 @@ encoder_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
12521261

12531262
if (PyCFunction_Check(s->encoder)) {
12541263
PyCFunction f = PyCFunction_GetFunction(s->encoder);
1255-
if (f == (PyCFunction)py_encode_basestring_ascii ||
1256-
f == (PyCFunction)py_encode_basestring) {
1264+
if (f == py_encode_basestring_ascii || f == py_encode_basestring) {
12571265
s->fast_encode = f;
12581266
}
12591267
}
@@ -1348,12 +1356,13 @@ write_newline_indent(PyUnicodeWriter *writer,
13481356

13491357

13501358
static PyObject *
1351-
encoder_call(PyEncoderObject *self, PyObject *args, PyObject *kwds)
1359+
encoder_call(PyObject *op, PyObject *args, PyObject *kwds)
13521360
{
13531361
/* Python callable interface to encode_listencode_obj */
13541362
static char *kwlist[] = {"obj", "_current_indent_level", NULL};
13551363
PyObject *obj;
13561364
Py_ssize_t indent_level;
1365+
PyEncoderObject *self = PyEncoderObject_CAST(op);
13571366

13581367
if (!PyArg_ParseTupleAndKeywords(args, kwds, "On:_iterencode", kwlist,
13591368
&obj, &indent_level))
@@ -1825,14 +1834,15 @@ encoder_dealloc(PyObject *self)
18251834
PyTypeObject *tp = Py_TYPE(self);
18261835
/* bpo-31095: UnTrack is needed before calling any callbacks */
18271836
PyObject_GC_UnTrack(self);
1828-
encoder_clear((PyEncoderObject *)self);
1837+
(void)encoder_clear(self);
18291838
tp->tp_free(self);
18301839
Py_DECREF(tp);
18311840
}
18321841

18331842
static int
1834-
encoder_traverse(PyEncoderObject *self, visitproc visit, void *arg)
1843+
encoder_traverse(PyObject *op, visitproc visit, void *arg)
18351844
{
1845+
PyEncoderObject *self = PyEncoderObject_CAST(op);
18361846
Py_VISIT(Py_TYPE(self));
18371847
Py_VISIT(self->markers);
18381848
Py_VISIT(self->defaultfn);
@@ -1844,8 +1854,9 @@ encoder_traverse(PyEncoderObject *self, visitproc visit, void *arg)
18441854
}
18451855

18461856
static int
1847-
encoder_clear(PyEncoderObject *self)
1857+
encoder_clear(PyObject *op)
18481858
{
1859+
PyEncoderObject *self = PyEncoderObject_CAST(op);
18491860
/* Deallocate Encoder */
18501861
Py_CLEAR(self->markers);
18511862
Py_CLEAR(self->defaultfn);
@@ -1879,15 +1890,15 @@ static PyType_Spec PyEncoderType_spec = {
18791890

18801891
static PyMethodDef speedups_methods[] = {
18811892
{"encode_basestring_ascii",
1882-
(PyCFunction)py_encode_basestring_ascii,
1893+
py_encode_basestring_ascii,
18831894
METH_O,
18841895
pydoc_encode_basestring_ascii},
18851896
{"encode_basestring",
1886-
(PyCFunction)py_encode_basestring,
1897+
py_encode_basestring,
18871898
METH_O,
18881899
pydoc_encode_basestring},
18891900
{"scanstring",
1890-
(PyCFunction)py_scanstring,
1901+
py_scanstring,
18911902
METH_VARARGS,
18921903
pydoc_scanstring},
18931904
{NULL, NULL, 0, NULL}

0 commit comments

Comments
 (0)