Skip to content
Merged
Changes from 1 commit
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
2683a25
fix UBSan failures for `PyBaseExceptionObject`
picnixz Dec 21, 2024
3f1196b
fix UBSan failures for `PyStopIterationObject`
picnixz Dec 21, 2024
1886b07
fix UBSan failures for `PySystemExitObject`
picnixz Dec 21, 2024
3df93a5
fix UBSan failures for `PyImportErrorObject`
picnixz Dec 21, 2024
96f97a5
fix UBSan failures for `PyOSErrorObject`
picnixz Dec 21, 2024
09514a9
fix UBSan failures for `PyNameErrorObject`
picnixz Dec 21, 2024
9d3c8b8
fix UBSan failures for `PyAttributeErrorObject`
picnixz Dec 21, 2024
2640a34
fix UBSan failures for `PySyntaxErrorObject`
picnixz Dec 21, 2024
150f34e
fix UBSan failures for `KeyError`
picnixz Dec 21, 2024
11d9e31
remove un-necessary casts for `UnicodeError*`
picnixz Dec 21, 2024
96430d9
remove un-necessary casts for `MemoryError`
picnixz Dec 21, 2024
0437291
fix UBSan failures for `PyBaseExceptionGroupObject`
picnixz Dec 21, 2024
d17a9b4
unify naming for cast functions
picnixz Dec 21, 2024
0d2434e
Merge remote-tracking branch 'upstream/main' into fix/ubsan/exception…
picnixz Jan 14, 2025
793196d
fixup
picnixz Jan 14, 2025
6abf1d8
fixup
picnixz Jan 14, 2025
6c2ef08
align naming convention
picnixz Jan 14, 2025
96f2d2d
remove redundant casts
picnixz Jan 16, 2025
0cd116b
Merge branch 'main' into fix/ubsan/exceptions-111178
picnixz Jan 18, 2025
248f195
Merge remote-tracking branch 'upstream/main' into fix/ubsan/exception…
picnixz Jan 25, 2025
e4daf11
remove un-necessary cast
picnixz Feb 6, 2025
565edab
Merge branch 'main' into fix/ubsan/exceptions-111178
picnixz Feb 7, 2025
122c914
Do not use `_` + capital letter in cast macros as it is also UB.
picnixz Feb 8, 2025
7906e3b
Do not use `_` + capital letter in cast macros as it is also UB.
picnixz Feb 8, 2025
8862b83
Merge branch 'main' into fix/ubsan/exceptions-111178
picnixz Feb 8, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Merge remote-tracking branch 'upstream/main' into fix/ubsan/exception…
…s-111178
  • Loading branch information
picnixz committed Jan 14, 2025
commit 0d2434e788221ed0df3fd147208adf0b5f8fc4b5
165 changes: 83 additions & 82 deletions Objects/exceptions.c
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ get_exc_state(void)
*/

static inline PyBaseExceptionObject *
_PyBaseExceptionObject_CAST(PyObject *exc)
_PyBaseExceptionObject_cast(PyObject *exc)
{
assert(PyExceptionInstance_Check(exc));
return (PyBaseExceptionObject *)exc;
Expand Down Expand Up @@ -85,7 +85,7 @@ BaseException_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
static int
BaseException_init(PyObject *op, PyObject *args, PyObject *kwds)
{
PyBaseExceptionObject *self = _PyBaseExceptionObject_CAST(op);
PyBaseExceptionObject *self = _PyBaseExceptionObject_cast(op);
if (!_PyArg_NoKeywords(Py_TYPE(self)->tp_name, kwds))
return -1;

Expand Down Expand Up @@ -130,7 +130,7 @@ BaseException_vectorcall(PyObject *type_obj, PyObject * const*args,
static int
BaseException_clear(PyObject *op)
{
PyBaseExceptionObject *self = _PyBaseExceptionObject_CAST(op);
PyBaseExceptionObject *self = _PyBaseExceptionObject_cast(op);
Py_CLEAR(self->dict);
Py_CLEAR(self->args);
Py_CLEAR(self->notes);
Expand All @@ -143,7 +143,7 @@ BaseException_clear(PyObject *op)
static void
BaseException_dealloc(PyObject *op)
{
PyBaseExceptionObject *self = _PyBaseExceptionObject_CAST(op);
PyBaseExceptionObject *self = _PyBaseExceptionObject_cast(op);
PyObject_GC_UnTrack(self);
// bpo-44348: The trashcan mechanism prevents stack overflow when deleting
// long chains of exceptions. For example, exceptions can be chained
Expand All @@ -157,7 +157,7 @@ BaseException_dealloc(PyObject *op)
static int
BaseException_traverse(PyObject *op, visitproc visit, void *arg)
{
PyBaseExceptionObject *self = _PyBaseExceptionObject_CAST(op);
PyBaseExceptionObject *self = _PyBaseExceptionObject_cast(op);
Py_VISIT(self->dict);
Py_VISIT(self->args);
Py_VISIT(self->notes);
Expand All @@ -170,7 +170,10 @@ BaseException_traverse(PyObject *op, visitproc visit, void *arg)
static PyObject *
BaseException_str(PyObject *op)
{
PyBaseExceptionObject *self = _PyBaseExceptionObject_CAST(op);
PyBaseExceptionObject *self = _PyBaseExceptionObject_cast(op);

PyObject *res;
Py_BEGIN_CRITICAL_SECTION(self);
switch (PyTuple_GET_SIZE(self->args)) {
case 0:
res = Py_GetConstant(Py_CONSTANT_EMPTY_STR);
Expand All @@ -189,7 +192,11 @@ BaseException_str(PyObject *op)
static PyObject *
BaseException_repr(PyObject *op)
{
PyBaseExceptionObject *self = _PyBaseExceptionObject_CAST(op);

PyBaseExceptionObject *self = _PyBaseExceptionObject_cast(op);

PyObject *res;
Py_BEGIN_CRITICAL_SECTION(self);
const char *name = _PyType_Name(Py_TYPE(self));
if (PyTuple_GET_SIZE(self->args) == 1) {
res = PyUnicode_FromFormat("%s(%R)", name,
Expand All @@ -210,9 +217,9 @@ BaseException.__reduce__
[clinic start generated code]*/

static PyObject *
BaseException_reduce(PyObject *op, PyObject *Py_UNUSED(ignored))
BaseException___reduce___impl(PyBaseExceptionObject *self)
/*[clinic end generated code: output=af87c1247ef98748 input=283be5a10d9c964f]*/
{
PyBaseExceptionObject *self = _PyBaseExceptionObject_CAST(op);
if (self->args && self->dict)
return PyTuple_Pack(3, Py_TYPE(self), self->args, self->dict);
else
Expand Down Expand Up @@ -278,19 +285,12 @@ BaseException_with_traceback_impl(PyBaseExceptionObject *self, PyObject *tb)
return Py_NewRef(self);
}

PyDoc_STRVAR(with_traceback_doc,
"Exception.with_traceback(tb) --\n\
set self.__traceback__ to tb and return self.");

static PyObject *
BaseException_add_note(PyObject *self, PyObject *note)
{
if (!PyUnicode_Check(note)) {
PyErr_Format(PyExc_TypeError,
"note must be a str, not '%s'",
Py_TYPE(note)->tp_name);
return NULL;
}
/*[clinic input]
@critical_section
BaseException.add_note
note: object(subclass_of="&PyUnicode_Type")
/
>>>>>>> upstream/main

Add a note to the exception
[clinic start generated code]*/
Expand Down Expand Up @@ -327,12 +327,11 @@ BaseException_add_note_impl(PyBaseExceptionObject *self, PyObject *note)
}

static PyMethodDef BaseException_methods[] = {
{"__reduce__", BaseException_reduce, METH_NOARGS},
{"__setstate__", BaseException_setstate, METH_O},
{"with_traceback", BaseException_with_traceback, METH_O,
with_traceback_doc},
{"add_note", BaseException_add_note, METH_O, add_note_doc},
{NULL, NULL, 0, NULL},
BASEEXCEPTION___REDUCE___METHODDEF
BASEEXCEPTION___SETSTATE___METHODDEF
BASEEXCEPTION_WITH_TRACEBACK_METHODDEF
BASEEXCEPTION_ADD_NOTE_METHODDEF
{NULL, NULL, 0, NULL},
};

/*[clinic input]
Expand All @@ -342,9 +341,9 @@ BaseException.args
[clinic start generated code]*/

static PyObject *
BaseException_get_args(PyObject *op, void *Py_UNUSED(ignored))
BaseException_args_get_impl(PyBaseExceptionObject *self)
/*[clinic end generated code: output=e02e34e35cf4d677 input=64282386e4d7822d]*/
{
PyBaseExceptionObject *self = _PyBaseExceptionObject_CAST(op);
if (self->args == NULL) {
Py_RETURN_NONE;
}
Expand All @@ -358,7 +357,8 @@ BaseException.args
[clinic start generated code]*/

static int
BaseException_set_args(PyObject *op, PyObject *val, void *Py_UNUSED(ignored))
BaseException_args_set_impl(PyBaseExceptionObject *self, PyObject *value)
/*[clinic end generated code: output=331137e11d8f9e80 input=2400047ea5970a84]*/
{
PyObject *seq;
if (value == NULL) {
Expand All @@ -368,7 +368,6 @@ BaseException_set_args(PyObject *op, PyObject *val, void *Py_UNUSED(ignored))
seq = PySequence_Tuple(value);
if (!seq)
return -1;
PyBaseExceptionObject *self = _PyBaseExceptionObject_CAST(op);
Py_XSETREF(self->args, seq);
return 0;
}
Expand All @@ -380,9 +379,9 @@ BaseException.__traceback__
[clinic start generated code]*/

static PyObject *
BaseException_get_tb(PyObject *op, void *Py_UNUSED(ignored))
BaseException___traceback___get_impl(PyBaseExceptionObject *self)
/*[clinic end generated code: output=17cf874a52339398 input=a2277f0de62170cf]*/
{
PyBaseExceptionObject *self = _PyBaseExceptionObject_CAST(op);
if (self->traceback == NULL) {
Py_RETURN_NONE;
}
Expand All @@ -397,10 +396,11 @@ BaseException.__traceback__
[clinic start generated code]*/

static int
BaseException_set_tb(PyObject *op, PyObject *tb, void *Py_UNUSED(ignored))
BaseException___traceback___set_impl(PyBaseExceptionObject *self,
PyObject *value)
/*[clinic end generated code: output=a82c86d9f29f48f0 input=12676035676badad]*/
{
PyBaseExceptionObject *self = _PyBaseExceptionObject_CAST(op);
if (tb == NULL) {
if (value == NULL) {
PyErr_SetString(PyExc_TypeError, "__traceback__ may not be deleted");
return -1;
}
Expand Down Expand Up @@ -508,75 +508,92 @@ BaseException___cause___set_impl(PyBaseExceptionObject *self,

static PyGetSetDef BaseException_getset[] = {
{"__dict__", PyObject_GenericGetDict, PyObject_GenericSetDict},
{"args", BaseException_get_args, BaseException_set_args},
{"__traceback__", BaseException_get_tb, BaseException_set_tb},
{"__context__", BaseException_get_context,
BaseException_set_context, PyDoc_STR("exception context")},
{"__cause__", BaseException_get_cause,
BaseException_set_cause, PyDoc_STR("exception cause")},
BASEEXCEPTION_ARGS_GETSETDEF
BASEEXCEPTION___TRACEBACK___GETSETDEF
BASEEXCEPTION___CONTEXT___GETSETDEF
BASEEXCEPTION___CAUSE___GETSETDEF
{NULL},
};


PyObject *
PyException_GetTraceback(PyObject *self)
{
PyBaseExceptionObject *exc = _PyBaseExceptionObject_CAST(self);
return Py_XNewRef(exc->traceback);
PyObject *traceback;
Py_BEGIN_CRITICAL_SECTION(self);
traceback = Py_XNewRef(_PyBaseExceptionObject_cast(self)->traceback);
Py_END_CRITICAL_SECTION();
return traceback;
}


int
PyException_SetTraceback(PyObject *self, PyObject *tb)
{
return BaseException_set_tb(self, tb, NULL);
int res;
Py_BEGIN_CRITICAL_SECTION(self);
res = BaseException___traceback___set_impl(_PyBaseExceptionObject_cast(self), tb);
Py_END_CRITICAL_SECTION();
return res;
}

PyObject *
PyException_GetCause(PyObject *self)
{
PyBaseExceptionObject *exc = _PyBaseExceptionObject_CAST(self);
return Py_XNewRef(exc->cause);
PyObject *cause;
Py_BEGIN_CRITICAL_SECTION(self);
cause = Py_XNewRef(_PyBaseExceptionObject_cast(self)->cause);
Py_END_CRITICAL_SECTION();
return cause;
}

/* Steals a reference to cause */
void
PyException_SetCause(PyObject *self, PyObject *cause)
{
PyBaseExceptionObject *exc = _PyBaseExceptionObject_CAST(self);
exc->suppress_context = 1;
Py_XSETREF(exc->cause, cause);
Py_BEGIN_CRITICAL_SECTION(self);
PyBaseExceptionObject *base_self = _PyBaseExceptionObject_cast(self);
base_self->suppress_context = 1;
Py_XSETREF(base_self->cause, cause);
Py_END_CRITICAL_SECTION();
}

PyObject *
PyException_GetContext(PyObject *self)
{
PyBaseExceptionObject *exc = _PyBaseExceptionObject_CAST(self);
return Py_XNewRef(exc->context);
PyObject *context;
Py_BEGIN_CRITICAL_SECTION(self);
context = Py_XNewRef(_PyBaseExceptionObject_cast(self)->context);
Py_END_CRITICAL_SECTION();
return context;
}

/* Steals a reference to context */
void
PyException_SetContext(PyObject *self, PyObject *context)
{
PyBaseExceptionObject *exc = _PyBaseExceptionObject_CAST(self);
Py_XSETREF(exc->context, context);
Py_BEGIN_CRITICAL_SECTION(self);
Py_XSETREF(_PyBaseExceptionObject_cast(self)->context, context);
Py_END_CRITICAL_SECTION();
}

PyObject *
PyException_GetArgs(PyObject *self)
{
PyBaseExceptionObject *exc = _PyBaseExceptionObject_CAST(self);
return Py_NewRef(exc->args);
PyObject *args;
Py_BEGIN_CRITICAL_SECTION(self);
args = Py_NewRef(_PyBaseExceptionObject_cast(self)->args);
Py_END_CRITICAL_SECTION();
return args;
}

void
PyException_SetArgs(PyObject *self, PyObject *args)
{
Py_BEGIN_CRITICAL_SECTION(self);
Py_INCREF(args);
PyBaseExceptionObject *exc = _PyBaseExceptionObject_CAST(self);
Py_XSETREF(exc->args, args);
Py_XSETREF(_PyBaseExceptionObject_cast(self)->args, args);
Py_END_CRITICAL_SECTION();
}

const char *
Expand Down Expand Up @@ -1813,7 +1830,7 @@ ImportError_reduce(PyObject *self, PyObject *Py_UNUSED(ignored))
PyObject *state = ImportError_getstate(self);
if (state == NULL)
return NULL;
PyBaseExceptionObject *exc = _PyBaseExceptionObject_CAST(self);
PyBaseExceptionObject *exc = _PyBaseExceptionObject_cast(self);
if (state == Py_None)
res = PyTuple_Pack(2, Py_TYPE(self), exc->args);
else
Expand Down Expand Up @@ -2834,7 +2851,7 @@ KeyError_str(PyObject *op)
string, that string will be displayed in quotes. Too bad.
If args is anything else, use the default BaseException__str__().
*/
PyBaseExceptionObject *self = _PyBaseExceptionObject_CAST(op);
PyBaseExceptionObject *self = _PyBaseExceptionObject_cast(op);
if (PyTuple_GET_SIZE(self->args) == 1) {
return PyObject_Repr(PyTuple_GET_ITEM(self->args, 0));
}
Expand Down Expand Up @@ -3129,12 +3146,8 @@ _PyUnicodeError_GetParams(PyObject *self,
}


static inline PyUnicodeErrorObject *
as_unicode_error(PyObject *self, const char *expect_type)
{
int rc = check_unicode_error_type(self, expect_type);
return rc < 0 ? NULL : (PyUnicodeErrorObject *)self;
}
// --- PyUnicodeEncodeObject: 'encoding' getters ------------------------------
// Note: PyUnicodeTranslateError does not have an 'encoding' attribute.

PyObject *
PyUnicodeEncodeError_GetEncoding(PyObject *self)
Expand Down Expand Up @@ -3218,13 +3231,7 @@ PyUnicodeTranslateError_GetStart(PyObject *self, Py_ssize_t *start)
}


static inline int
unicode_error_set_start_impl(PyObject *self, Py_ssize_t start)
{
PyUnicodeErrorObject *exc = _PyUnicodeErrorObject_CAST(self);
exc->start = start;
return 0;
}
// --- PyUnicodeEncodeObject: 'start' setters ---------------------------------


int
Expand Down Expand Up @@ -3291,13 +3298,7 @@ PyUnicodeTranslateError_GetEnd(PyObject *self, Py_ssize_t *end)
}


static inline int
unicode_error_set_end_impl(PyObject *self, Py_ssize_t end)
{
PyUnicodeErrorObject *exc = _PyUnicodeErrorObject_CAST(self);
exc->end = end;
return 0;
}
// --- PyUnicodeEncodeObject: 'end' setters -----------------------------------


int
Expand Down Expand Up @@ -3865,7 +3866,7 @@ _PyErr_NoMemory(PyThreadState *tstate)
static void
MemoryError_dealloc(PyObject *op)
{
PyBaseExceptionObject *self = _PyBaseExceptionObject_CAST(op);
PyBaseExceptionObject *self = _PyBaseExceptionObject_cast(op);
_PyObject_GC_UNTRACK(self);

(void)BaseException_clear(op);
Expand Down
You are viewing a condensed version of this merge commit. You can view the full changes here.