Skip to content

gh-111178: fix UBSan failures in Modules/cjkcodecs/multibytecodec.c #129090

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 9 commits into from
Jan 25, 2025
71 changes: 49 additions & 22 deletions Modules/cjkcodecs/multibytecodec.c
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,27 @@ class _multibytecodec.MultibyteStreamWriter "MultibyteStreamWriterObject *" "cli
/*[clinic end generated code: output=da39a3ee5e6b4b0d input=305a76dfdd24b99c]*/
#undef clinic_get_state

#define _MultibyteCodec_CAST(op) ((MultibyteCodec *)(op))
#define _MultibyteCodecObject_CAST(op) ((MultibyteCodecObject *)(op))

#define _MultibyteStatefulCodecContext_CAST(op) \
((MultibyteStatefulCodecContext *)(op))

#define _MultibyteStatefulEncoderContext_CAST(op) \
((MultibyteStatefulEncoderContext *)(op))
#define _MultibyteStatefulDecoderContext_CAST(op) \
((MultibyteStatefulDecoderContext *)(op))

#define _MultibyteIncrementalEncoderObject_CAST(op) \
((MultibyteIncrementalEncoderObject *)(op))
#define _MultibyteIncrementalDecoderObject_CAST(op) \
((MultibyteIncrementalDecoderObject *)(op))

#define _MultibyteStreamReaderObject_CAST(op) \
((MultibyteStreamReaderObject *)(op))
#define _MultibyteStreamWriterObject_CAST(op) \
((MultibyteStreamWriterObject *)(op))

typedef struct {
PyObject *inobj;
Py_ssize_t inpos, inlen;
Expand Down Expand Up @@ -136,9 +157,10 @@ call_error_callback(PyObject *errors, PyObject *exc)
}

static PyObject *
codecctx_errors_get(MultibyteStatefulCodecContext *self, void *Py_UNUSED(ignored))
codecctx_errors_get(PyObject *op, void *Py_UNUSED(closure))
{
const char *errors;
MultibyteStatefulCodecContext *self = _MultibyteStatefulCodecContext_CAST(op);

if (self->errors == ERROR_STRICT)
errors = "strict";
Expand All @@ -154,11 +176,11 @@ codecctx_errors_get(MultibyteStatefulCodecContext *self, void *Py_UNUSED(ignored
}

static int
codecctx_errors_set(MultibyteStatefulCodecContext *self, PyObject *value,
void *closure)
codecctx_errors_set(PyObject *op, PyObject *value, void *Py_UNUSED(closure))
{
PyObject *cb;
const char *str;
MultibyteStatefulCodecContext *self = _MultibyteStatefulCodecContext_CAST(op);

if (value == NULL) {
PyErr_SetString(PyExc_AttributeError, "cannot delete attribute");
Expand All @@ -184,9 +206,8 @@ codecctx_errors_set(MultibyteStatefulCodecContext *self, PyObject *value,

/* This getset handlers list is used by all the stateful codec objects */
static PyGetSetDef codecctx_getsets[] = {
{"errors", (getter)codecctx_errors_get,
(setter)codecctx_errors_set,
PyDoc_STR("how to treat errors")},
{"errors", codecctx_errors_get, codecctx_errors_set,
PyDoc_STR("how to treat errors")},
{NULL,}
};

Expand Down Expand Up @@ -719,22 +740,24 @@ static struct PyMethodDef multibytecodec_methods[] = {
};

static int
multibytecodec_clear(MultibyteCodecObject *self)
multibytecodec_clear(PyObject *op)
{
MultibyteCodecObject *self = _MultibyteCodecObject_CAST(op);
Py_CLEAR(self->cjk_module);
return 0;
}

static int
multibytecodec_traverse(MultibyteCodecObject *self, visitproc visit, void *arg)
multibytecodec_traverse(PyObject *op, visitproc visit, void *arg)
{
MultibyteCodecObject *self = _MultibyteCodecObject_CAST(op);
Py_VISIT(Py_TYPE(self));
Py_VISIT(self->cjk_module);
return 0;
}

static void
multibytecodec_dealloc(MultibyteCodecObject *self)
multibytecodec_dealloc(PyObject *self)
{
PyObject_GC_UnTrack(self);
PyTypeObject *tp = Py_TYPE(self);
Expand Down Expand Up @@ -1106,17 +1129,18 @@ mbiencoder_init(PyObject *self, PyObject *args, PyObject *kwds)
}

static int
mbiencoder_traverse(MultibyteIncrementalEncoderObject *self,
visitproc visit, void *arg)
mbiencoder_traverse(PyObject *op, visitproc visit, void *arg)
{
MultibyteIncrementalEncoderObject *self = _MultibyteIncrementalEncoderObject_CAST(op);
if (ERROR_ISCUSTOM(self->errors))
Py_VISIT(self->errors);
return 0;
}

static void
mbiencoder_dealloc(MultibyteIncrementalEncoderObject *self)
mbiencoder_dealloc(PyObject *op)
{
MultibyteIncrementalEncoderObject *self = _MultibyteIncrementalEncoderObject_CAST(op);
PyTypeObject *tp = Py_TYPE(self);
PyObject_GC_UnTrack(self);
ERROR_DECREF(self->errors);
Expand Down Expand Up @@ -1388,17 +1412,18 @@ mbidecoder_init(PyObject *self, PyObject *args, PyObject *kwds)
}

static int
mbidecoder_traverse(MultibyteIncrementalDecoderObject *self,
visitproc visit, void *arg)
mbidecoder_traverse(PyObject *op, visitproc visit, void *arg)
{
MultibyteIncrementalDecoderObject *self = _MultibyteIncrementalDecoderObject_CAST(op);
if (ERROR_ISCUSTOM(self->errors))
Py_VISIT(self->errors);
return 0;
}

static void
mbidecoder_dealloc(MultibyteIncrementalDecoderObject *self)
mbidecoder_dealloc(PyObject *op)
{
MultibyteIncrementalDecoderObject *self = _MultibyteIncrementalDecoderObject_CAST(op);
PyTypeObject *tp = Py_TYPE(self);
PyObject_GC_UnTrack(self);
ERROR_DECREF(self->errors);
Expand Down Expand Up @@ -1704,18 +1729,19 @@ mbstreamreader_init(PyObject *self, PyObject *args, PyObject *kwds)
}

static int
mbstreamreader_traverse(MultibyteStreamReaderObject *self,
visitproc visit, void *arg)
mbstreamreader_traverse(PyObject *op, visitproc visit, void *arg)
{
MultibyteStreamReaderObject *self = _MultibyteStreamReaderObject_CAST(op);
if (ERROR_ISCUSTOM(self->errors))
Py_VISIT(self->errors);
Py_VISIT(self->stream);
return 0;
}

static void
mbstreamreader_dealloc(MultibyteStreamReaderObject *self)
mbstreamreader_dealloc(PyObject *op)
{
MultibyteStreamReaderObject *self = _MultibyteStreamReaderObject_CAST(op);
PyTypeObject *tp = Py_TYPE(self);
PyObject_GC_UnTrack(self);
ERROR_DECREF(self->errors);
Expand Down Expand Up @@ -1927,18 +1953,19 @@ mbstreamwriter_init(PyObject *self, PyObject *args, PyObject *kwds)
}

static int
mbstreamwriter_traverse(MultibyteStreamWriterObject *self,
visitproc visit, void *arg)
mbstreamwriter_traverse(PyObject *op, visitproc visit, void *arg)
{
MultibyteStreamWriterObject *self = _MultibyteStreamWriterObject_CAST(op);
if (ERROR_ISCUSTOM(self->errors))
Py_VISIT(self->errors);
Py_VISIT(self->stream);
return 0;
}

static void
mbstreamwriter_dealloc(MultibyteStreamWriterObject *self)
mbstreamwriter_dealloc(PyObject *op)
{
MultibyteStreamWriterObject *self = _MultibyteStreamWriterObject_CAST(op);
PyTypeObject *tp = Py_TYPE(self);
PyObject_GC_UnTrack(self);
ERROR_DECREF(self->errors);
Expand Down Expand Up @@ -2044,7 +2071,7 @@ _multibytecodec_clear(PyObject *mod)
static void
_multibytecodec_free(void *mod)
{
_multibytecodec_clear((PyObject *)mod);
(void)_multibytecodec_clear((PyObject *)mod);
}

#define CREATE_TYPE(module, type, spec) \
Expand Down
Loading