gh-111178: fix UBSan failures in `Modules/_jsonmodule.c` (GH-129781)

Fix UBSan failures for `PyScannerObject`, fix UBSan failures for `PyEncoderObject`
This commit is contained in:
Bénédikt Tran 2025-02-17 14:51:18 +01:00 committed by GitHub
parent ef8eeca9d8
commit 31ad8b6d08
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
1 changed files with 27 additions and 16 deletions

View File

@ -27,6 +27,8 @@ typedef struct _PyScannerObject {
PyObject *parse_constant; PyObject *parse_constant;
} PyScannerObject; } PyScannerObject;
#define PyScannerObject_CAST(op) ((PyScannerObject *)(op))
static PyMemberDef scanner_members[] = { static PyMemberDef scanner_members[] = {
{"strict", Py_T_BOOL, offsetof(PyScannerObject, strict), Py_READONLY, "strict"}, {"strict", Py_T_BOOL, offsetof(PyScannerObject, strict), Py_READONLY, "strict"},
{"object_hook", _Py_T_OBJECT, offsetof(PyScannerObject, object_hook), Py_READONLY, "object_hook"}, {"object_hook", _Py_T_OBJECT, offsetof(PyScannerObject, object_hook), Py_READONLY, "object_hook"},
@ -51,6 +53,8 @@ typedef struct _PyEncoderObject {
PyCFunction fast_encode; PyCFunction fast_encode;
} PyEncoderObject; } PyEncoderObject;
#define PyEncoderObject_CAST(op) ((PyEncoderObject *)(op))
static PyMemberDef encoder_members[] = { static PyMemberDef encoder_members[] = {
{"markers", _Py_T_OBJECT, offsetof(PyEncoderObject, markers), Py_READONLY, "markers"}, {"markers", _Py_T_OBJECT, offsetof(PyEncoderObject, markers), Py_READONLY, "markers"},
{"default", _Py_T_OBJECT, offsetof(PyEncoderObject, defaultfn), Py_READONLY, "default"}, {"default", _Py_T_OBJECT, offsetof(PyEncoderObject, defaultfn), Py_READONLY, "default"},
@ -69,6 +73,7 @@ static PyObject *
ascii_escape_unicode(PyObject *pystr); ascii_escape_unicode(PyObject *pystr);
static PyObject * static PyObject *
py_encode_basestring_ascii(PyObject* Py_UNUSED(self), PyObject *pystr); py_encode_basestring_ascii(PyObject* Py_UNUSED(self), PyObject *pystr);
static PyObject * static PyObject *
scan_once_unicode(PyScannerObject *s, PyObject *memo, PyObject *pystr, Py_ssize_t idx, Py_ssize_t *next_idx_ptr); scan_once_unicode(PyScannerObject *s, PyObject *memo, PyObject *pystr, Py_ssize_t idx, Py_ssize_t *next_idx_ptr);
static PyObject * static PyObject *
@ -78,13 +83,14 @@ scanner_new(PyTypeObject *type, PyObject *args, PyObject *kwds);
static void static void
scanner_dealloc(PyObject *self); scanner_dealloc(PyObject *self);
static int static int
scanner_clear(PyScannerObject *self); scanner_clear(PyObject *self);
static PyObject * static PyObject *
encoder_new(PyTypeObject *type, PyObject *args, PyObject *kwds); encoder_new(PyTypeObject *type, PyObject *args, PyObject *kwds);
static void static void
encoder_dealloc(PyObject *self); encoder_dealloc(PyObject *self);
static int static int
encoder_clear(PyEncoderObject *self); encoder_clear(PyObject *self);
static int static int
encoder_listencode_list(PyEncoderObject *s, PyUnicodeWriter *writer, PyObject *seq, Py_ssize_t indent_level, PyObject *indent_cache); encoder_listencode_list(PyEncoderObject *s, PyUnicodeWriter *writer, PyObject *seq, Py_ssize_t indent_level, PyObject *indent_cache);
static int static int
@ -626,14 +632,15 @@ scanner_dealloc(PyObject *self)
PyTypeObject *tp = Py_TYPE(self); PyTypeObject *tp = Py_TYPE(self);
/* bpo-31095: UnTrack is needed before calling any callbacks */ /* bpo-31095: UnTrack is needed before calling any callbacks */
PyObject_GC_UnTrack(self); PyObject_GC_UnTrack(self);
scanner_clear((PyScannerObject *)self); (void)scanner_clear(self);
tp->tp_free(self); tp->tp_free(self);
Py_DECREF(tp); Py_DECREF(tp);
} }
static int static int
scanner_traverse(PyScannerObject *self, visitproc visit, void *arg) scanner_traverse(PyObject *op, visitproc visit, void *arg)
{ {
PyScannerObject *self = PyScannerObject_CAST(op);
Py_VISIT(Py_TYPE(self)); Py_VISIT(Py_TYPE(self));
Py_VISIT(self->object_hook); Py_VISIT(self->object_hook);
Py_VISIT(self->object_pairs_hook); Py_VISIT(self->object_pairs_hook);
@ -644,8 +651,9 @@ scanner_traverse(PyScannerObject *self, visitproc visit, void *arg)
} }
static int static int
scanner_clear(PyScannerObject *self) scanner_clear(PyObject *op)
{ {
PyScannerObject *self = PyScannerObject_CAST(op);
Py_CLEAR(self->object_hook); Py_CLEAR(self->object_hook);
Py_CLEAR(self->object_pairs_hook); Py_CLEAR(self->object_pairs_hook);
Py_CLEAR(self->parse_float); Py_CLEAR(self->parse_float);
@ -1115,7 +1123,7 @@ scan_once_unicode(PyScannerObject *s, PyObject *memo, PyObject *pystr, Py_ssize_
} }
static PyObject * static PyObject *
scanner_call(PyScannerObject *self, PyObject *args, PyObject *kwds) scanner_call(PyObject *self, PyObject *args, PyObject *kwds)
{ {
/* Python callable interface to scan_once_{str,unicode} */ /* Python callable interface to scan_once_{str,unicode} */
PyObject *pystr; PyObject *pystr;
@ -1137,7 +1145,8 @@ scanner_call(PyScannerObject *self, PyObject *args, PyObject *kwds)
if (memo == NULL) { if (memo == NULL) {
return NULL; return NULL;
} }
rval = scan_once_unicode(self, memo, pystr, idx, &next_idx); rval = scan_once_unicode(PyScannerObject_CAST(self),
memo, pystr, idx, &next_idx);
Py_DECREF(memo); Py_DECREF(memo);
if (rval == NULL) if (rval == NULL)
return NULL; return NULL;
@ -1252,8 +1261,7 @@ encoder_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
if (PyCFunction_Check(s->encoder)) { if (PyCFunction_Check(s->encoder)) {
PyCFunction f = PyCFunction_GetFunction(s->encoder); PyCFunction f = PyCFunction_GetFunction(s->encoder);
if (f == (PyCFunction)py_encode_basestring_ascii || if (f == py_encode_basestring_ascii || f == py_encode_basestring) {
f == (PyCFunction)py_encode_basestring) {
s->fast_encode = f; s->fast_encode = f;
} }
} }
@ -1348,12 +1356,13 @@ write_newline_indent(PyUnicodeWriter *writer,
static PyObject * static PyObject *
encoder_call(PyEncoderObject *self, PyObject *args, PyObject *kwds) encoder_call(PyObject *op, PyObject *args, PyObject *kwds)
{ {
/* Python callable interface to encode_listencode_obj */ /* Python callable interface to encode_listencode_obj */
static char *kwlist[] = {"obj", "_current_indent_level", NULL}; static char *kwlist[] = {"obj", "_current_indent_level", NULL};
PyObject *obj; PyObject *obj;
Py_ssize_t indent_level; Py_ssize_t indent_level;
PyEncoderObject *self = PyEncoderObject_CAST(op);
if (!PyArg_ParseTupleAndKeywords(args, kwds, "On:_iterencode", kwlist, if (!PyArg_ParseTupleAndKeywords(args, kwds, "On:_iterencode", kwlist,
&obj, &indent_level)) &obj, &indent_level))
@ -1825,14 +1834,15 @@ encoder_dealloc(PyObject *self)
PyTypeObject *tp = Py_TYPE(self); PyTypeObject *tp = Py_TYPE(self);
/* bpo-31095: UnTrack is needed before calling any callbacks */ /* bpo-31095: UnTrack is needed before calling any callbacks */
PyObject_GC_UnTrack(self); PyObject_GC_UnTrack(self);
encoder_clear((PyEncoderObject *)self); (void)encoder_clear(self);
tp->tp_free(self); tp->tp_free(self);
Py_DECREF(tp); Py_DECREF(tp);
} }
static int static int
encoder_traverse(PyEncoderObject *self, visitproc visit, void *arg) encoder_traverse(PyObject *op, visitproc visit, void *arg)
{ {
PyEncoderObject *self = PyEncoderObject_CAST(op);
Py_VISIT(Py_TYPE(self)); Py_VISIT(Py_TYPE(self));
Py_VISIT(self->markers); Py_VISIT(self->markers);
Py_VISIT(self->defaultfn); Py_VISIT(self->defaultfn);
@ -1844,8 +1854,9 @@ encoder_traverse(PyEncoderObject *self, visitproc visit, void *arg)
} }
static int static int
encoder_clear(PyEncoderObject *self) encoder_clear(PyObject *op)
{ {
PyEncoderObject *self = PyEncoderObject_CAST(op);
/* Deallocate Encoder */ /* Deallocate Encoder */
Py_CLEAR(self->markers); Py_CLEAR(self->markers);
Py_CLEAR(self->defaultfn); Py_CLEAR(self->defaultfn);
@ -1879,15 +1890,15 @@ static PyType_Spec PyEncoderType_spec = {
static PyMethodDef speedups_methods[] = { static PyMethodDef speedups_methods[] = {
{"encode_basestring_ascii", {"encode_basestring_ascii",
(PyCFunction)py_encode_basestring_ascii, py_encode_basestring_ascii,
METH_O, METH_O,
pydoc_encode_basestring_ascii}, pydoc_encode_basestring_ascii},
{"encode_basestring", {"encode_basestring",
(PyCFunction)py_encode_basestring, py_encode_basestring,
METH_O, METH_O,
pydoc_encode_basestring}, pydoc_encode_basestring},
{"scanstring", {"scanstring",
(PyCFunction)py_scanstring, py_scanstring,
METH_VARARGS, METH_VARARGS,
pydoc_scanstring}, pydoc_scanstring},
{NULL, NULL, 0, NULL} {NULL, NULL, 0, NULL}