xref: /third_party/python/Objects/exceptions.c (revision 7db96d56)
1/*
2 * New exceptions.c written in Iceland by Richard Jones and Georg Brandl.
3 *
4 * Thanks go to Tim Peters and Michael Hudson for debugging.
5 */
6
7#define PY_SSIZE_T_CLEAN
8#include <Python.h>
9#include <stdbool.h>
10#include "pycore_ceval.h"         // _Py_EnterRecursiveCall
11#include "pycore_exceptions.h"    // struct _Py_exc_state
12#include "pycore_initconfig.h"
13#include "pycore_object.h"
14#include "structmember.h"         // PyMemberDef
15#include "osdefs.h"               // SEP
16
17
18/* Compatibility aliases */
19PyObject *PyExc_EnvironmentError = NULL;  // borrowed ref
20PyObject *PyExc_IOError = NULL;  // borrowed ref
21#ifdef MS_WINDOWS
22PyObject *PyExc_WindowsError = NULL;  // borrowed ref
23#endif
24
25
26static struct _Py_exc_state*
27get_exc_state(void)
28{
29    PyInterpreterState *interp = _PyInterpreterState_GET();
30    return &interp->exc_state;
31}
32
33
34/* NOTE: If the exception class hierarchy changes, don't forget to update
35 * Lib/test/exception_hierarchy.txt
36 */
37
38/*
39 *    BaseException
40 */
41static PyObject *
42BaseException_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
43{
44    PyBaseExceptionObject *self;
45
46    self = (PyBaseExceptionObject *)type->tp_alloc(type, 0);
47    if (!self)
48        return NULL;
49    /* the dict is created on the fly in PyObject_GenericSetAttr */
50    self->dict = NULL;
51    self->notes = NULL;
52    self->traceback = self->cause = self->context = NULL;
53    self->suppress_context = 0;
54
55    if (args) {
56        self->args = args;
57        Py_INCREF(args);
58        return (PyObject *)self;
59    }
60
61    self->args = PyTuple_New(0);
62    if (!self->args) {
63        Py_DECREF(self);
64        return NULL;
65    }
66
67    return (PyObject *)self;
68}
69
70static int
71BaseException_init(PyBaseExceptionObject *self, PyObject *args, PyObject *kwds)
72{
73    if (!_PyArg_NoKeywords(Py_TYPE(self)->tp_name, kwds))
74        return -1;
75
76    Py_INCREF(args);
77    Py_XSETREF(self->args, args);
78
79    return 0;
80}
81
82static int
83BaseException_clear(PyBaseExceptionObject *self)
84{
85    Py_CLEAR(self->dict);
86    Py_CLEAR(self->args);
87    Py_CLEAR(self->notes);
88    Py_CLEAR(self->traceback);
89    Py_CLEAR(self->cause);
90    Py_CLEAR(self->context);
91    return 0;
92}
93
94static void
95BaseException_dealloc(PyBaseExceptionObject *self)
96{
97    PyObject_GC_UnTrack(self);
98    // bpo-44348: The trashcan mechanism prevents stack overflow when deleting
99    // long chains of exceptions. For example, exceptions can be chained
100    // through the __context__ attributes or the __traceback__ attribute.
101    Py_TRASHCAN_BEGIN(self, BaseException_dealloc)
102    BaseException_clear(self);
103    Py_TYPE(self)->tp_free((PyObject *)self);
104    Py_TRASHCAN_END
105}
106
107static int
108BaseException_traverse(PyBaseExceptionObject *self, visitproc visit, void *arg)
109{
110    Py_VISIT(self->dict);
111    Py_VISIT(self->args);
112    Py_VISIT(self->notes);
113    Py_VISIT(self->traceback);
114    Py_VISIT(self->cause);
115    Py_VISIT(self->context);
116    return 0;
117}
118
119static PyObject *
120BaseException_str(PyBaseExceptionObject *self)
121{
122    switch (PyTuple_GET_SIZE(self->args)) {
123    case 0:
124        return PyUnicode_FromString("");
125    case 1:
126        return PyObject_Str(PyTuple_GET_ITEM(self->args, 0));
127    default:
128        return PyObject_Str(self->args);
129    }
130}
131
132static PyObject *
133BaseException_repr(PyBaseExceptionObject *self)
134{
135    const char *name = _PyType_Name(Py_TYPE(self));
136    if (PyTuple_GET_SIZE(self->args) == 1)
137        return PyUnicode_FromFormat("%s(%R)", name,
138                                    PyTuple_GET_ITEM(self->args, 0));
139    else
140        return PyUnicode_FromFormat("%s%R", name, self->args);
141}
142
143/* Pickling support */
144static PyObject *
145BaseException_reduce(PyBaseExceptionObject *self, PyObject *Py_UNUSED(ignored))
146{
147    if (self->args && self->dict)
148        return PyTuple_Pack(3, Py_TYPE(self), self->args, self->dict);
149    else
150        return PyTuple_Pack(2, Py_TYPE(self), self->args);
151}
152
153/*
154 * Needed for backward compatibility, since exceptions used to store
155 * all their attributes in the __dict__. Code is taken from cPickle's
156 * load_build function.
157 */
158static PyObject *
159BaseException_setstate(PyObject *self, PyObject *state)
160{
161    PyObject *d_key, *d_value;
162    Py_ssize_t i = 0;
163
164    if (state != Py_None) {
165        if (!PyDict_Check(state)) {
166            PyErr_SetString(PyExc_TypeError, "state is not a dictionary");
167            return NULL;
168        }
169        while (PyDict_Next(state, &i, &d_key, &d_value)) {
170            Py_INCREF(d_key);
171            Py_INCREF(d_value);
172            int res = PyObject_SetAttr(self, d_key, d_value);
173            Py_DECREF(d_value);
174            Py_DECREF(d_key);
175            if (res < 0) {
176                return NULL;
177            }
178        }
179    }
180    Py_RETURN_NONE;
181}
182
183static PyObject *
184BaseException_with_traceback(PyObject *self, PyObject *tb) {
185    if (PyException_SetTraceback(self, tb))
186        return NULL;
187
188    Py_INCREF(self);
189    return self;
190}
191
192PyDoc_STRVAR(with_traceback_doc,
193"Exception.with_traceback(tb) --\n\
194    set self.__traceback__ to tb and return self.");
195
196static inline PyBaseExceptionObject*
197_PyBaseExceptionObject_cast(PyObject *exc)
198{
199    assert(PyExceptionInstance_Check(exc));
200    return (PyBaseExceptionObject *)exc;
201}
202
203static PyObject *
204BaseException_add_note(PyObject *self, PyObject *note)
205{
206    if (!PyUnicode_Check(note)) {
207        PyErr_Format(PyExc_TypeError,
208                     "note must be a str, not '%s'",
209                     Py_TYPE(note)->tp_name);
210        return NULL;
211    }
212
213    if (!PyObject_HasAttr(self, &_Py_ID(__notes__))) {
214        PyObject *new_notes = PyList_New(0);
215        if (new_notes == NULL) {
216            return NULL;
217        }
218        if (PyObject_SetAttr(self, &_Py_ID(__notes__), new_notes) < 0) {
219            Py_DECREF(new_notes);
220            return NULL;
221        }
222        Py_DECREF(new_notes);
223    }
224    PyObject *notes = PyObject_GetAttr(self, &_Py_ID(__notes__));
225    if (notes == NULL) {
226        return NULL;
227    }
228    if (!PyList_Check(notes)) {
229        Py_DECREF(notes);
230        PyErr_SetString(PyExc_TypeError, "Cannot add note: __notes__ is not a list");
231        return NULL;
232    }
233    if (PyList_Append(notes, note) < 0) {
234        Py_DECREF(notes);
235        return NULL;
236    }
237    Py_DECREF(notes);
238    Py_RETURN_NONE;
239}
240
241PyDoc_STRVAR(add_note_doc,
242"Exception.add_note(note) --\n\
243    add a note to the exception");
244
245static PyMethodDef BaseException_methods[] = {
246   {"__reduce__", (PyCFunction)BaseException_reduce, METH_NOARGS },
247   {"__setstate__", (PyCFunction)BaseException_setstate, METH_O },
248   {"with_traceback", (PyCFunction)BaseException_with_traceback, METH_O,
249    with_traceback_doc},
250   {"add_note", (PyCFunction)BaseException_add_note, METH_O,
251    add_note_doc},
252   {NULL, NULL, 0, NULL},
253};
254
255static PyObject *
256BaseException_get_args(PyBaseExceptionObject *self, void *Py_UNUSED(ignored))
257{
258    if (self->args == NULL) {
259        Py_RETURN_NONE;
260    }
261    Py_INCREF(self->args);
262    return self->args;
263}
264
265static int
266BaseException_set_args(PyBaseExceptionObject *self, PyObject *val, void *Py_UNUSED(ignored))
267{
268    PyObject *seq;
269    if (val == NULL) {
270        PyErr_SetString(PyExc_TypeError, "args may not be deleted");
271        return -1;
272    }
273    seq = PySequence_Tuple(val);
274    if (!seq)
275        return -1;
276    Py_XSETREF(self->args, seq);
277    return 0;
278}
279
280static PyObject *
281BaseException_get_tb(PyBaseExceptionObject *self, void *Py_UNUSED(ignored))
282{
283    if (self->traceback == NULL) {
284        Py_RETURN_NONE;
285    }
286    Py_INCREF(self->traceback);
287    return self->traceback;
288}
289
290static int
291BaseException_set_tb(PyBaseExceptionObject *self, PyObject *tb, void *Py_UNUSED(ignored))
292{
293    if (tb == NULL) {
294        PyErr_SetString(PyExc_TypeError, "__traceback__ may not be deleted");
295        return -1;
296    }
297    else if (!(tb == Py_None || PyTraceBack_Check(tb))) {
298        PyErr_SetString(PyExc_TypeError,
299                        "__traceback__ must be a traceback or None");
300        return -1;
301    }
302
303    Py_INCREF(tb);
304    Py_XSETREF(self->traceback, tb);
305    return 0;
306}
307
308static PyObject *
309BaseException_get_context(PyObject *self, void *Py_UNUSED(ignored))
310{
311    PyObject *res = PyException_GetContext(self);
312    if (res)
313        return res;  /* new reference already returned above */
314    Py_RETURN_NONE;
315}
316
317static int
318BaseException_set_context(PyObject *self, PyObject *arg, void *Py_UNUSED(ignored))
319{
320    if (arg == NULL) {
321        PyErr_SetString(PyExc_TypeError, "__context__ may not be deleted");
322        return -1;
323    } else if (arg == Py_None) {
324        arg = NULL;
325    } else if (!PyExceptionInstance_Check(arg)) {
326        PyErr_SetString(PyExc_TypeError, "exception context must be None "
327                        "or derive from BaseException");
328        return -1;
329    } else {
330        /* PyException_SetContext steals this reference */
331        Py_INCREF(arg);
332    }
333    PyException_SetContext(self, arg);
334    return 0;
335}
336
337static PyObject *
338BaseException_get_cause(PyObject *self, void *Py_UNUSED(ignored))
339{
340    PyObject *res = PyException_GetCause(self);
341    if (res)
342        return res;  /* new reference already returned above */
343    Py_RETURN_NONE;
344}
345
346static int
347BaseException_set_cause(PyObject *self, PyObject *arg, void *Py_UNUSED(ignored))
348{
349    if (arg == NULL) {
350        PyErr_SetString(PyExc_TypeError, "__cause__ may not be deleted");
351        return -1;
352    } else if (arg == Py_None) {
353        arg = NULL;
354    } else if (!PyExceptionInstance_Check(arg)) {
355        PyErr_SetString(PyExc_TypeError, "exception cause must be None "
356                        "or derive from BaseException");
357        return -1;
358    } else {
359        /* PyException_SetCause steals this reference */
360        Py_INCREF(arg);
361    }
362    PyException_SetCause(self, arg);
363    return 0;
364}
365
366
367static PyGetSetDef BaseException_getset[] = {
368    {"__dict__", PyObject_GenericGetDict, PyObject_GenericSetDict},
369    {"args", (getter)BaseException_get_args, (setter)BaseException_set_args},
370    {"__traceback__", (getter)BaseException_get_tb, (setter)BaseException_set_tb},
371    {"__context__", BaseException_get_context,
372     BaseException_set_context, PyDoc_STR("exception context")},
373    {"__cause__", BaseException_get_cause,
374     BaseException_set_cause, PyDoc_STR("exception cause")},
375    {NULL},
376};
377
378
379PyObject *
380PyException_GetTraceback(PyObject *self)
381{
382    PyBaseExceptionObject *base_self = _PyBaseExceptionObject_cast(self);
383    Py_XINCREF(base_self->traceback);
384    return base_self->traceback;
385}
386
387
388int
389PyException_SetTraceback(PyObject *self, PyObject *tb)
390{
391    return BaseException_set_tb(_PyBaseExceptionObject_cast(self), tb, NULL);
392}
393
394PyObject *
395PyException_GetCause(PyObject *self)
396{
397    PyObject *cause = _PyBaseExceptionObject_cast(self)->cause;
398    Py_XINCREF(cause);
399    return cause;
400}
401
402/* Steals a reference to cause */
403void
404PyException_SetCause(PyObject *self, PyObject *cause)
405{
406    PyBaseExceptionObject *base_self = _PyBaseExceptionObject_cast(self);
407    base_self->suppress_context = 1;
408    Py_XSETREF(base_self->cause, cause);
409}
410
411PyObject *
412PyException_GetContext(PyObject *self)
413{
414    PyObject *context = _PyBaseExceptionObject_cast(self)->context;
415    Py_XINCREF(context);
416    return context;
417}
418
419/* Steals a reference to context */
420void
421PyException_SetContext(PyObject *self, PyObject *context)
422{
423    Py_XSETREF(_PyBaseExceptionObject_cast(self)->context, context);
424}
425
426const char *
427PyExceptionClass_Name(PyObject *ob)
428{
429    assert(PyExceptionClass_Check(ob));
430    return ((PyTypeObject*)ob)->tp_name;
431}
432
433static struct PyMemberDef BaseException_members[] = {
434    {"__suppress_context__", T_BOOL,
435     offsetof(PyBaseExceptionObject, suppress_context)},
436    {NULL}
437};
438
439
440static PyTypeObject _PyExc_BaseException = {
441    PyVarObject_HEAD_INIT(NULL, 0)
442    "BaseException", /*tp_name*/
443    sizeof(PyBaseExceptionObject), /*tp_basicsize*/
444    0,                          /*tp_itemsize*/
445    (destructor)BaseException_dealloc, /*tp_dealloc*/
446    0,                          /*tp_vectorcall_offset*/
447    0,                          /*tp_getattr*/
448    0,                          /*tp_setattr*/
449    0,                          /*tp_as_async*/
450    (reprfunc)BaseException_repr, /*tp_repr*/
451    0,                          /*tp_as_number*/
452    0,                          /*tp_as_sequence*/
453    0,                          /*tp_as_mapping*/
454    0,                          /*tp_hash */
455    0,                          /*tp_call*/
456    (reprfunc)BaseException_str,  /*tp_str*/
457    PyObject_GenericGetAttr,    /*tp_getattro*/
458    PyObject_GenericSetAttr,    /*tp_setattro*/
459    0,                          /*tp_as_buffer*/
460    Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC |
461        Py_TPFLAGS_BASE_EXC_SUBCLASS,  /*tp_flags*/
462    PyDoc_STR("Common base class for all exceptions"), /* tp_doc */
463    (traverseproc)BaseException_traverse, /* tp_traverse */
464    (inquiry)BaseException_clear, /* tp_clear */
465    0,                          /* tp_richcompare */
466    0,                          /* tp_weaklistoffset */
467    0,                          /* tp_iter */
468    0,                          /* tp_iternext */
469    BaseException_methods,      /* tp_methods */
470    BaseException_members,      /* tp_members */
471    BaseException_getset,       /* tp_getset */
472    0,                          /* tp_base */
473    0,                          /* tp_dict */
474    0,                          /* tp_descr_get */
475    0,                          /* tp_descr_set */
476    offsetof(PyBaseExceptionObject, dict), /* tp_dictoffset */
477    (initproc)BaseException_init, /* tp_init */
478    0,                          /* tp_alloc */
479    BaseException_new,          /* tp_new */
480};
481/* the CPython API expects exceptions to be (PyObject *) - both a hold-over
482from the previous implementation and also allowing Python objects to be used
483in the API */
484PyObject *PyExc_BaseException = (PyObject *)&_PyExc_BaseException;
485
486/* note these macros omit the last semicolon so the macro invocation may
487 * include it and not look strange.
488 */
489#define SimpleExtendsException(EXCBASE, EXCNAME, EXCDOC) \
490static PyTypeObject _PyExc_ ## EXCNAME = { \
491    PyVarObject_HEAD_INIT(NULL, 0) \
492    # EXCNAME, \
493    sizeof(PyBaseExceptionObject), \
494    0, (destructor)BaseException_dealloc, 0, 0, 0, 0, 0, 0, 0, \
495    0, 0, 0, 0, 0, 0, 0, \
496    Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC, \
497    PyDoc_STR(EXCDOC), (traverseproc)BaseException_traverse, \
498    (inquiry)BaseException_clear, 0, 0, 0, 0, 0, 0, 0, &_ ## EXCBASE, \
499    0, 0, 0, offsetof(PyBaseExceptionObject, dict), \
500    (initproc)BaseException_init, 0, BaseException_new,\
501}; \
502PyObject *PyExc_ ## EXCNAME = (PyObject *)&_PyExc_ ## EXCNAME
503
504#define MiddlingExtendsException(EXCBASE, EXCNAME, EXCSTORE, EXCDOC) \
505static PyTypeObject _PyExc_ ## EXCNAME = { \
506    PyVarObject_HEAD_INIT(NULL, 0) \
507    # EXCNAME, \
508    sizeof(Py ## EXCSTORE ## Object), \
509    0, (destructor)EXCSTORE ## _dealloc, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
510    0, 0, 0, 0, 0, \
511    Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC, \
512    PyDoc_STR(EXCDOC), (traverseproc)EXCSTORE ## _traverse, \
513    (inquiry)EXCSTORE ## _clear, 0, 0, 0, 0, 0, 0, 0, &_ ## EXCBASE, \
514    0, 0, 0, offsetof(Py ## EXCSTORE ## Object, dict), \
515    (initproc)EXCSTORE ## _init, 0, 0, \
516}; \
517PyObject *PyExc_ ## EXCNAME = (PyObject *)&_PyExc_ ## EXCNAME
518
519#define ComplexExtendsException(EXCBASE, EXCNAME, EXCSTORE, EXCNEW, \
520                                EXCMETHODS, EXCMEMBERS, EXCGETSET, \
521                                EXCSTR, EXCDOC) \
522static PyTypeObject _PyExc_ ## EXCNAME = { \
523    PyVarObject_HEAD_INIT(NULL, 0) \
524    # EXCNAME, \
525    sizeof(Py ## EXCSTORE ## Object), 0, \
526    (destructor)EXCSTORE ## _dealloc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
527    (reprfunc)EXCSTR, 0, 0, 0, \
528    Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC, \
529    PyDoc_STR(EXCDOC), (traverseproc)EXCSTORE ## _traverse, \
530    (inquiry)EXCSTORE ## _clear, 0, 0, 0, 0, EXCMETHODS, \
531    EXCMEMBERS, EXCGETSET, &_ ## EXCBASE, \
532    0, 0, 0, offsetof(Py ## EXCSTORE ## Object, dict), \
533    (initproc)EXCSTORE ## _init, 0, EXCNEW,\
534}; \
535PyObject *PyExc_ ## EXCNAME = (PyObject *)&_PyExc_ ## EXCNAME
536
537
538/*
539 *    Exception extends BaseException
540 */
541SimpleExtendsException(PyExc_BaseException, Exception,
542                       "Common base class for all non-exit exceptions.");
543
544
545/*
546 *    TypeError extends Exception
547 */
548SimpleExtendsException(PyExc_Exception, TypeError,
549                       "Inappropriate argument type.");
550
551
552/*
553 *    StopAsyncIteration extends Exception
554 */
555SimpleExtendsException(PyExc_Exception, StopAsyncIteration,
556                       "Signal the end from iterator.__anext__().");
557
558
559/*
560 *    StopIteration extends Exception
561 */
562
563static PyMemberDef StopIteration_members[] = {
564    {"value", T_OBJECT, offsetof(PyStopIterationObject, value), 0,
565        PyDoc_STR("generator return value")},
566    {NULL}  /* Sentinel */
567};
568
569static int
570StopIteration_init(PyStopIterationObject *self, PyObject *args, PyObject *kwds)
571{
572    Py_ssize_t size = PyTuple_GET_SIZE(args);
573    PyObject *value;
574
575    if (BaseException_init((PyBaseExceptionObject *)self, args, kwds) == -1)
576        return -1;
577    Py_CLEAR(self->value);
578    if (size > 0)
579        value = PyTuple_GET_ITEM(args, 0);
580    else
581        value = Py_None;
582    Py_INCREF(value);
583    self->value = value;
584    return 0;
585}
586
587static int
588StopIteration_clear(PyStopIterationObject *self)
589{
590    Py_CLEAR(self->value);
591    return BaseException_clear((PyBaseExceptionObject *)self);
592}
593
594static void
595StopIteration_dealloc(PyStopIterationObject *self)
596{
597    PyObject_GC_UnTrack(self);
598    StopIteration_clear(self);
599    Py_TYPE(self)->tp_free((PyObject *)self);
600}
601
602static int
603StopIteration_traverse(PyStopIterationObject *self, visitproc visit, void *arg)
604{
605    Py_VISIT(self->value);
606    return BaseException_traverse((PyBaseExceptionObject *)self, visit, arg);
607}
608
609ComplexExtendsException(
610    PyExc_Exception,       /* base */
611    StopIteration,         /* name */
612    StopIteration,         /* prefix for *_init, etc */
613    0,                     /* new */
614    0,                     /* methods */
615    StopIteration_members, /* members */
616    0,                     /* getset */
617    0,                     /* str */
618    "Signal the end from iterator.__next__()."
619);
620
621
622/*
623 *    GeneratorExit extends BaseException
624 */
625SimpleExtendsException(PyExc_BaseException, GeneratorExit,
626                       "Request that a generator exit.");
627
628
629/*
630 *    SystemExit extends BaseException
631 */
632
633static int
634SystemExit_init(PySystemExitObject *self, PyObject *args, PyObject *kwds)
635{
636    Py_ssize_t size = PyTuple_GET_SIZE(args);
637
638    if (BaseException_init((PyBaseExceptionObject *)self, args, kwds) == -1)
639        return -1;
640
641    if (size == 0)
642        return 0;
643    if (size == 1) {
644        Py_INCREF(PyTuple_GET_ITEM(args, 0));
645        Py_XSETREF(self->code, PyTuple_GET_ITEM(args, 0));
646    }
647    else { /* size > 1 */
648        Py_INCREF(args);
649        Py_XSETREF(self->code, args);
650    }
651    return 0;
652}
653
654static int
655SystemExit_clear(PySystemExitObject *self)
656{
657    Py_CLEAR(self->code);
658    return BaseException_clear((PyBaseExceptionObject *)self);
659}
660
661static void
662SystemExit_dealloc(PySystemExitObject *self)
663{
664    _PyObject_GC_UNTRACK(self);
665    SystemExit_clear(self);
666    Py_TYPE(self)->tp_free((PyObject *)self);
667}
668
669static int
670SystemExit_traverse(PySystemExitObject *self, visitproc visit, void *arg)
671{
672    Py_VISIT(self->code);
673    return BaseException_traverse((PyBaseExceptionObject *)self, visit, arg);
674}
675
676static PyMemberDef SystemExit_members[] = {
677    {"code", T_OBJECT, offsetof(PySystemExitObject, code), 0,
678        PyDoc_STR("exception code")},
679    {NULL}  /* Sentinel */
680};
681
682ComplexExtendsException(PyExc_BaseException, SystemExit, SystemExit,
683                        0, 0, SystemExit_members, 0, 0,
684                        "Request to exit from the interpreter.");
685
686/*
687 *    BaseExceptionGroup extends BaseException
688 *    ExceptionGroup extends BaseExceptionGroup and Exception
689 */
690
691
692static inline PyBaseExceptionGroupObject*
693_PyBaseExceptionGroupObject_cast(PyObject *exc)
694{
695    assert(_PyBaseExceptionGroup_Check(exc));
696    return (PyBaseExceptionGroupObject *)exc;
697}
698
699static PyObject *
700BaseExceptionGroup_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
701{
702    struct _Py_exc_state *state = get_exc_state();
703    PyTypeObject *PyExc_ExceptionGroup =
704        (PyTypeObject*)state->PyExc_ExceptionGroup;
705
706    PyObject *message = NULL;
707    PyObject *exceptions = NULL;
708
709    if (!PyArg_ParseTuple(args,
710                          "UO:BaseExceptionGroup.__new__",
711                          &message,
712                          &exceptions)) {
713        return NULL;
714    }
715
716    if (!PySequence_Check(exceptions)) {
717        PyErr_SetString(
718            PyExc_TypeError,
719            "second argument (exceptions) must be a sequence");
720        return NULL;
721    }
722
723    exceptions = PySequence_Tuple(exceptions);
724    if (!exceptions) {
725        return NULL;
726    }
727
728    /* We are now holding a ref to the exceptions tuple */
729
730    Py_ssize_t numexcs = PyTuple_GET_SIZE(exceptions);
731    if (numexcs == 0) {
732        PyErr_SetString(
733            PyExc_ValueError,
734            "second argument (exceptions) must be a non-empty sequence");
735        goto error;
736    }
737
738    bool nested_base_exceptions = false;
739    for (Py_ssize_t i = 0; i < numexcs; i++) {
740        PyObject *exc = PyTuple_GET_ITEM(exceptions, i);
741        if (!exc) {
742            goto error;
743        }
744        if (!PyExceptionInstance_Check(exc)) {
745            PyErr_Format(
746                PyExc_ValueError,
747                "Item %d of second argument (exceptions) is not an exception",
748                i);
749            goto error;
750        }
751        int is_nonbase_exception = PyObject_IsInstance(exc, PyExc_Exception);
752        if (is_nonbase_exception < 0) {
753            goto error;
754        }
755        else if (is_nonbase_exception == 0) {
756            nested_base_exceptions = true;
757        }
758    }
759
760    PyTypeObject *cls = type;
761    if (cls == PyExc_ExceptionGroup) {
762        if (nested_base_exceptions) {
763            PyErr_SetString(PyExc_TypeError,
764                "Cannot nest BaseExceptions in an ExceptionGroup");
765            goto error;
766        }
767    }
768    else if (cls == (PyTypeObject*)PyExc_BaseExceptionGroup) {
769        if (!nested_base_exceptions) {
770            /* All nested exceptions are Exception subclasses,
771             * wrap them in an ExceptionGroup
772             */
773            cls = PyExc_ExceptionGroup;
774        }
775    }
776    else {
777        /* user-defined subclass */
778        if (nested_base_exceptions) {
779            int nonbase = PyObject_IsSubclass((PyObject*)cls, PyExc_Exception);
780            if (nonbase == -1) {
781                goto error;
782            }
783            else if (nonbase == 1) {
784                PyErr_Format(PyExc_TypeError,
785                    "Cannot nest BaseExceptions in '%.200s'",
786                    cls->tp_name);
787                goto error;
788            }
789        }
790    }
791
792    if (!cls) {
793        /* Don't crash during interpreter shutdown
794         * (PyExc_ExceptionGroup may have been cleared)
795         */
796        cls = (PyTypeObject*)PyExc_BaseExceptionGroup;
797    }
798    PyBaseExceptionGroupObject *self =
799        _PyBaseExceptionGroupObject_cast(BaseException_new(cls, args, kwds));
800    if (!self) {
801        goto error;
802    }
803
804    self->msg = Py_NewRef(message);
805    self->excs = exceptions;
806    return (PyObject*)self;
807error:
808    Py_DECREF(exceptions);
809    return NULL;
810}
811
812PyObject *
813_PyExc_CreateExceptionGroup(const char *msg_str, PyObject *excs)
814{
815    PyObject *msg = PyUnicode_FromString(msg_str);
816    if (!msg) {
817        return NULL;
818    }
819    PyObject *args = PyTuple_Pack(2, msg, excs);
820    Py_DECREF(msg);
821    if (!args) {
822        return NULL;
823    }
824    PyObject *result = PyObject_CallObject(PyExc_BaseExceptionGroup, args);
825    Py_DECREF(args);
826    return result;
827}
828
829static int
830BaseExceptionGroup_init(PyBaseExceptionGroupObject *self,
831    PyObject *args, PyObject *kwds)
832{
833    if (!_PyArg_NoKeywords(Py_TYPE(self)->tp_name, kwds)) {
834        return -1;
835    }
836    if (BaseException_init((PyBaseExceptionObject *)self, args, kwds) == -1) {
837        return -1;
838    }
839    return 0;
840}
841
842static int
843BaseExceptionGroup_clear(PyBaseExceptionGroupObject *self)
844{
845    Py_CLEAR(self->msg);
846    Py_CLEAR(self->excs);
847    return BaseException_clear((PyBaseExceptionObject *)self);
848}
849
850static void
851BaseExceptionGroup_dealloc(PyBaseExceptionGroupObject *self)
852{
853    _PyObject_GC_UNTRACK(self);
854    BaseExceptionGroup_clear(self);
855    Py_TYPE(self)->tp_free((PyObject *)self);
856}
857
858static int
859BaseExceptionGroup_traverse(PyBaseExceptionGroupObject *self,
860     visitproc visit, void *arg)
861{
862    Py_VISIT(self->msg);
863    Py_VISIT(self->excs);
864    return BaseException_traverse((PyBaseExceptionObject *)self, visit, arg);
865}
866
867static PyObject *
868BaseExceptionGroup_str(PyBaseExceptionGroupObject *self)
869{
870    assert(self->msg);
871    assert(PyUnicode_Check(self->msg));
872
873    assert(PyTuple_CheckExact(self->excs));
874    Py_ssize_t num_excs = PyTuple_Size(self->excs);
875    return PyUnicode_FromFormat(
876        "%S (%zd sub-exception%s)",
877        self->msg, num_excs, num_excs > 1 ? "s" : "");
878}
879
880static PyObject *
881BaseExceptionGroup_derive(PyObject *self_, PyObject *args)
882{
883    PyBaseExceptionGroupObject *self = _PyBaseExceptionGroupObject_cast(self_);
884    PyObject *excs = NULL;
885    if (!PyArg_ParseTuple(args, "O", &excs)) {
886        return NULL;
887    }
888    PyObject *init_args = PyTuple_Pack(2, self->msg, excs);
889    if (!init_args) {
890        return NULL;
891    }
892    PyObject *eg = PyObject_CallObject(
893        PyExc_BaseExceptionGroup, init_args);
894    Py_DECREF(init_args);
895    return eg;
896}
897
898static int
899exceptiongroup_subset(
900    PyBaseExceptionGroupObject *_orig, PyObject *excs, PyObject **result)
901{
902    /* Sets *result to an ExceptionGroup wrapping excs with metadata from
903     * _orig. If excs is empty, sets *result to NULL.
904     * Returns 0 on success and -1 on error.
905
906     * This function is used by split() to construct the match/rest parts,
907     * so excs is the matching or non-matching sub-sequence of orig->excs
908     * (this function does not verify that it is a subsequence).
909     */
910    PyObject *orig = (PyObject *)_orig;
911
912    *result = NULL;
913    Py_ssize_t num_excs = PySequence_Size(excs);
914    if (num_excs < 0) {
915        return -1;
916    }
917    else if (num_excs == 0) {
918        return 0;
919    }
920
921    PyObject *eg = PyObject_CallMethod(
922        orig, "derive", "(O)", excs);
923    if (!eg) {
924        return -1;
925    }
926
927    if (!_PyBaseExceptionGroup_Check(eg)) {
928        PyErr_SetString(PyExc_TypeError,
929            "derive must return an instance of BaseExceptionGroup");
930        goto error;
931    }
932
933    /* Now we hold a reference to the new eg */
934
935    PyObject *tb = PyException_GetTraceback(orig);
936    if (tb) {
937        int res = PyException_SetTraceback(eg, tb);
938        Py_DECREF(tb);
939        if (res < 0) {
940            goto error;
941        }
942    }
943    PyException_SetContext(eg, PyException_GetContext(orig));
944    PyException_SetCause(eg, PyException_GetCause(orig));
945
946    if (PyObject_HasAttr(orig, &_Py_ID(__notes__))) {
947        PyObject *notes = PyObject_GetAttr(orig, &_Py_ID(__notes__));
948        if (notes == NULL) {
949            goto error;
950        }
951        if (PySequence_Check(notes)) {
952            /* Make a copy so the parts have independent notes lists. */
953            PyObject *notes_copy = PySequence_List(notes);
954            Py_DECREF(notes);
955            if (notes_copy == NULL) {
956                goto error;
957            }
958            int res = PyObject_SetAttr(eg, &_Py_ID(__notes__), notes_copy);
959            Py_DECREF(notes_copy);
960            if (res < 0) {
961                goto error;
962            }
963        }
964        else {
965            /* __notes__ is supposed to be a list, and split() is not a
966             * good place to report earlier user errors, so we just ignore
967             * notes of non-sequence type.
968             */
969            Py_DECREF(notes);
970        }
971    }
972
973    *result = eg;
974    return 0;
975error:
976    Py_DECREF(eg);
977    return -1;
978}
979
980typedef enum {
981    /* Exception type or tuple of thereof */
982    EXCEPTION_GROUP_MATCH_BY_TYPE = 0,
983    /* A PyFunction returning True for matching exceptions */
984    EXCEPTION_GROUP_MATCH_BY_PREDICATE = 1,
985    /* A set of the IDs of leaf exceptions to include in the result.
986     * This matcher type is used internally by the interpreter
987     * to construct reraised exceptions.
988     */
989    EXCEPTION_GROUP_MATCH_INSTANCE_IDS = 2
990} _exceptiongroup_split_matcher_type;
991
992static int
993get_matcher_type(PyObject *value,
994                 _exceptiongroup_split_matcher_type *type)
995{
996    assert(value);
997
998    if (PyFunction_Check(value)) {
999        *type = EXCEPTION_GROUP_MATCH_BY_PREDICATE;
1000        return 0;
1001    }
1002
1003    if (PyExceptionClass_Check(value)) {
1004        *type = EXCEPTION_GROUP_MATCH_BY_TYPE;
1005        return 0;
1006    }
1007
1008    if (PyTuple_CheckExact(value)) {
1009        Py_ssize_t n = PyTuple_GET_SIZE(value);
1010        for (Py_ssize_t i=0; i<n; i++) {
1011            if (!PyExceptionClass_Check(PyTuple_GET_ITEM(value, i))) {
1012                goto error;
1013            }
1014        }
1015        *type = EXCEPTION_GROUP_MATCH_BY_TYPE;
1016        return 0;
1017    }
1018
1019error:
1020    PyErr_SetString(
1021        PyExc_TypeError,
1022        "expected a function, exception type or tuple of exception types");
1023    return -1;
1024}
1025
1026static int
1027exceptiongroup_split_check_match(PyObject *exc,
1028                                 _exceptiongroup_split_matcher_type matcher_type,
1029                                 PyObject *matcher_value)
1030{
1031    switch (matcher_type) {
1032    case EXCEPTION_GROUP_MATCH_BY_TYPE: {
1033        assert(PyExceptionClass_Check(matcher_value) ||
1034               PyTuple_CheckExact(matcher_value));
1035        return PyErr_GivenExceptionMatches(exc, matcher_value);
1036    }
1037    case EXCEPTION_GROUP_MATCH_BY_PREDICATE: {
1038        assert(PyFunction_Check(matcher_value));
1039        PyObject *exc_matches = PyObject_CallOneArg(matcher_value, exc);
1040        if (exc_matches == NULL) {
1041            return -1;
1042        }
1043        int is_true = PyObject_IsTrue(exc_matches);
1044        Py_DECREF(exc_matches);
1045        return is_true;
1046    }
1047    case EXCEPTION_GROUP_MATCH_INSTANCE_IDS: {
1048        assert(PySet_Check(matcher_value));
1049        if (!_PyBaseExceptionGroup_Check(exc)) {
1050            PyObject *exc_id = PyLong_FromVoidPtr(exc);
1051            if (exc_id == NULL) {
1052                return -1;
1053            }
1054            int res = PySet_Contains(matcher_value, exc_id);
1055            Py_DECREF(exc_id);
1056            return res;
1057        }
1058        return 0;
1059    }
1060    }
1061    return 0;
1062}
1063
1064typedef struct {
1065    PyObject *match;
1066    PyObject *rest;
1067} _exceptiongroup_split_result;
1068
1069static int
1070exceptiongroup_split_recursive(PyObject *exc,
1071                               _exceptiongroup_split_matcher_type matcher_type,
1072                               PyObject *matcher_value,
1073                               bool construct_rest,
1074                               _exceptiongroup_split_result *result)
1075{
1076    result->match = NULL;
1077    result->rest = NULL;
1078
1079    int is_match = exceptiongroup_split_check_match(
1080        exc, matcher_type, matcher_value);
1081    if (is_match < 0) {
1082        return -1;
1083    }
1084
1085    if (is_match) {
1086        /* Full match */
1087        result->match = Py_NewRef(exc);
1088        return 0;
1089    }
1090    else if (!_PyBaseExceptionGroup_Check(exc)) {
1091        /* Leaf exception and no match */
1092        if (construct_rest) {
1093            result->rest = Py_NewRef(exc);
1094        }
1095        return 0;
1096    }
1097
1098    /* Partial match */
1099
1100    PyBaseExceptionGroupObject *eg = _PyBaseExceptionGroupObject_cast(exc);
1101    assert(PyTuple_CheckExact(eg->excs));
1102    Py_ssize_t num_excs = PyTuple_Size(eg->excs);
1103    if (num_excs < 0) {
1104        return -1;
1105    }
1106    assert(num_excs > 0); /* checked in constructor, and excs is read-only */
1107
1108    int retval = -1;
1109    PyObject *match_list = PyList_New(0);
1110    if (!match_list) {
1111        return -1;
1112    }
1113
1114    PyObject *rest_list = NULL;
1115    if (construct_rest) {
1116        rest_list = PyList_New(0);
1117        if (!rest_list) {
1118            goto done;
1119        }
1120    }
1121    /* recursive calls */
1122    for (Py_ssize_t i = 0; i < num_excs; i++) {
1123        PyObject *e = PyTuple_GET_ITEM(eg->excs, i);
1124        _exceptiongroup_split_result rec_result;
1125        if (_Py_EnterRecursiveCall(" in exceptiongroup_split_recursive")) {
1126            goto done;
1127        }
1128        if (exceptiongroup_split_recursive(
1129                e, matcher_type, matcher_value,
1130                construct_rest, &rec_result) < 0) {
1131            assert(!rec_result.match);
1132            assert(!rec_result.rest);
1133            _Py_LeaveRecursiveCall();
1134            goto done;
1135        }
1136        _Py_LeaveRecursiveCall();
1137        if (rec_result.match) {
1138            assert(PyList_CheckExact(match_list));
1139            if (PyList_Append(match_list, rec_result.match) < 0) {
1140                Py_DECREF(rec_result.match);
1141                Py_XDECREF(rec_result.rest);
1142                goto done;
1143            }
1144            Py_DECREF(rec_result.match);
1145        }
1146        if (rec_result.rest) {
1147            assert(construct_rest);
1148            assert(PyList_CheckExact(rest_list));
1149            if (PyList_Append(rest_list, rec_result.rest) < 0) {
1150                Py_DECREF(rec_result.rest);
1151                goto done;
1152            }
1153            Py_DECREF(rec_result.rest);
1154        }
1155    }
1156
1157    /* construct result */
1158    if (exceptiongroup_subset(eg, match_list, &result->match) < 0) {
1159        goto done;
1160    }
1161
1162    if (construct_rest) {
1163        assert(PyList_CheckExact(rest_list));
1164        if (exceptiongroup_subset(eg, rest_list, &result->rest) < 0) {
1165            Py_CLEAR(result->match);
1166            goto done;
1167        }
1168    }
1169    retval = 0;
1170done:
1171    Py_DECREF(match_list);
1172    Py_XDECREF(rest_list);
1173    if (retval < 0) {
1174        Py_CLEAR(result->match);
1175        Py_CLEAR(result->rest);
1176    }
1177    return retval;
1178}
1179
1180static PyObject *
1181BaseExceptionGroup_split(PyObject *self, PyObject *args)
1182{
1183    PyObject *matcher_value = NULL;
1184    if (!PyArg_UnpackTuple(args, "split", 1, 1, &matcher_value)) {
1185        return NULL;
1186    }
1187
1188    _exceptiongroup_split_matcher_type matcher_type;
1189    if (get_matcher_type(matcher_value, &matcher_type) < 0) {
1190        return NULL;
1191    }
1192
1193    _exceptiongroup_split_result split_result;
1194    bool construct_rest = true;
1195    if (exceptiongroup_split_recursive(
1196            self, matcher_type, matcher_value,
1197            construct_rest, &split_result) < 0) {
1198        return NULL;
1199    }
1200
1201    PyObject *result = PyTuple_Pack(
1202            2,
1203            split_result.match ? split_result.match : Py_None,
1204            split_result.rest ? split_result.rest : Py_None);
1205
1206    Py_XDECREF(split_result.match);
1207    Py_XDECREF(split_result.rest);
1208    return result;
1209}
1210
1211static PyObject *
1212BaseExceptionGroup_subgroup(PyObject *self, PyObject *args)
1213{
1214    PyObject *matcher_value = NULL;
1215    if (!PyArg_UnpackTuple(args, "subgroup", 1, 1, &matcher_value)) {
1216        return NULL;
1217    }
1218
1219    _exceptiongroup_split_matcher_type matcher_type;
1220    if (get_matcher_type(matcher_value, &matcher_type) < 0) {
1221        return NULL;
1222    }
1223
1224    _exceptiongroup_split_result split_result;
1225    bool construct_rest = false;
1226    if (exceptiongroup_split_recursive(
1227            self, matcher_type, matcher_value,
1228            construct_rest, &split_result) < 0) {
1229        return NULL;
1230    }
1231
1232    PyObject *result = Py_NewRef(
1233            split_result.match ? split_result.match : Py_None);
1234
1235    Py_XDECREF(split_result.match);
1236    assert(!split_result.rest);
1237    return result;
1238}
1239
1240static int
1241collect_exception_group_leaf_ids(PyObject *exc, PyObject *leaf_ids)
1242{
1243    if (Py_IsNone(exc)) {
1244        return 0;
1245    }
1246
1247    assert(PyExceptionInstance_Check(exc));
1248    assert(PySet_Check(leaf_ids));
1249
1250    /* Add IDs of all leaf exceptions in exc to the leaf_ids set */
1251
1252    if (!_PyBaseExceptionGroup_Check(exc)) {
1253        PyObject *exc_id = PyLong_FromVoidPtr(exc);
1254        if (exc_id == NULL) {
1255            return -1;
1256        }
1257        int res = PySet_Add(leaf_ids, exc_id);
1258        Py_DECREF(exc_id);
1259        return res;
1260    }
1261    PyBaseExceptionGroupObject *eg = _PyBaseExceptionGroupObject_cast(exc);
1262    Py_ssize_t num_excs = PyTuple_GET_SIZE(eg->excs);
1263    /* recursive calls */
1264    for (Py_ssize_t i = 0; i < num_excs; i++) {
1265        PyObject *e = PyTuple_GET_ITEM(eg->excs, i);
1266        if (_Py_EnterRecursiveCall(" in collect_exception_group_leaf_ids")) {
1267            return -1;
1268        }
1269        int res = collect_exception_group_leaf_ids(e, leaf_ids);
1270        _Py_LeaveRecursiveCall();
1271        if (res < 0) {
1272            return -1;
1273        }
1274    }
1275    return 0;
1276}
1277
1278/* This function is used by the interpreter to construct reraised
1279 * exception groups. It takes an exception group eg and a list
1280 * of exception groups keep and returns the sub-exception group
1281 * of eg which contains all leaf exceptions that are contained
1282 * in any exception group in keep.
1283 */
1284static PyObject *
1285exception_group_projection(PyObject *eg, PyObject *keep)
1286{
1287    assert(_PyBaseExceptionGroup_Check(eg));
1288    assert(PyList_CheckExact(keep));
1289
1290    PyObject *leaf_ids = PySet_New(NULL);
1291    if (!leaf_ids) {
1292        return NULL;
1293    }
1294
1295    Py_ssize_t n = PyList_GET_SIZE(keep);
1296    for (Py_ssize_t i = 0; i < n; i++) {
1297        PyObject *e = PyList_GET_ITEM(keep, i);
1298        assert(e != NULL);
1299        assert(_PyBaseExceptionGroup_Check(e));
1300        if (collect_exception_group_leaf_ids(e, leaf_ids) < 0) {
1301            Py_DECREF(leaf_ids);
1302            return NULL;
1303        }
1304    }
1305
1306    _exceptiongroup_split_result split_result;
1307    bool construct_rest = false;
1308    int err = exceptiongroup_split_recursive(
1309                eg, EXCEPTION_GROUP_MATCH_INSTANCE_IDS, leaf_ids,
1310                construct_rest, &split_result);
1311    Py_DECREF(leaf_ids);
1312    if (err < 0) {
1313        return NULL;
1314    }
1315
1316    PyObject *result = split_result.match ?
1317        split_result.match : Py_NewRef(Py_None);
1318    assert(split_result.rest == NULL);
1319    return result;
1320}
1321
1322static bool
1323is_same_exception_metadata(PyObject *exc1, PyObject *exc2)
1324{
1325    assert(PyExceptionInstance_Check(exc1));
1326    assert(PyExceptionInstance_Check(exc2));
1327
1328    PyBaseExceptionObject *e1 = (PyBaseExceptionObject *)exc1;
1329    PyBaseExceptionObject *e2 = (PyBaseExceptionObject *)exc2;
1330
1331    return (e1->notes == e2->notes &&
1332            e1->traceback == e2->traceback &&
1333            e1->cause == e2->cause &&
1334            e1->context == e2->context);
1335}
1336
1337/*
1338   This function is used by the interpreter to calculate
1339   the exception group to be raised at the end of a
1340   try-except* construct.
1341
1342   orig: the original except that was caught.
1343   excs: a list of exceptions that were raised/reraised
1344         in the except* clauses.
1345
1346   Calculates an exception group to raise. It contains
1347   all exceptions in excs, where those that were reraised
1348   have same nesting structure as in orig, and those that
1349   were raised (if any) are added as siblings in a new EG.
1350
1351   Returns NULL and sets an exception on failure.
1352*/
1353PyObject *
1354_PyExc_PrepReraiseStar(PyObject *orig, PyObject *excs)
1355{
1356    assert(PyExceptionInstance_Check(orig));
1357    assert(PyList_Check(excs));
1358
1359    Py_ssize_t numexcs = PyList_GET_SIZE(excs);
1360
1361    if (numexcs == 0) {
1362        return Py_NewRef(Py_None);
1363    }
1364
1365    if (!_PyBaseExceptionGroup_Check(orig)) {
1366        /* a naked exception was caught and wrapped. Only one except* clause
1367         * could have executed,so there is at most one exception to raise.
1368         */
1369
1370        assert(numexcs == 1 || (numexcs == 2 && PyList_GET_ITEM(excs, 1) == Py_None));
1371
1372        PyObject *e = PyList_GET_ITEM(excs, 0);
1373        assert(e != NULL);
1374        return Py_NewRef(e);
1375    }
1376
1377    PyObject *raised_list = PyList_New(0);
1378    if (raised_list == NULL) {
1379        return NULL;
1380    }
1381    PyObject* reraised_list = PyList_New(0);
1382    if (reraised_list == NULL) {
1383        Py_DECREF(raised_list);
1384        return NULL;
1385    }
1386
1387    /* Now we are holding refs to raised_list and reraised_list */
1388
1389    PyObject *result = NULL;
1390
1391    /* Split excs into raised and reraised by comparing metadata with orig */
1392    for (Py_ssize_t i = 0; i < numexcs; i++) {
1393        PyObject *e = PyList_GET_ITEM(excs, i);
1394        assert(e != NULL);
1395        if (Py_IsNone(e)) {
1396            continue;
1397        }
1398        bool is_reraise = is_same_exception_metadata(e, orig);
1399        PyObject *append_list = is_reraise ? reraised_list : raised_list;
1400        if (PyList_Append(append_list, e) < 0) {
1401            goto done;
1402        }
1403    }
1404
1405    PyObject *reraised_eg = exception_group_projection(orig, reraised_list);
1406    if (reraised_eg == NULL) {
1407        goto done;
1408    }
1409
1410    if (!Py_IsNone(reraised_eg)) {
1411        assert(is_same_exception_metadata(reraised_eg, orig));
1412    }
1413    Py_ssize_t num_raised = PyList_GET_SIZE(raised_list);
1414    if (num_raised == 0) {
1415        result = reraised_eg;
1416    }
1417    else if (num_raised > 0) {
1418        int res = 0;
1419        if (!Py_IsNone(reraised_eg)) {
1420            res = PyList_Append(raised_list, reraised_eg);
1421        }
1422        Py_DECREF(reraised_eg);
1423        if (res < 0) {
1424            goto done;
1425        }
1426        if (PyList_GET_SIZE(raised_list) > 1) {
1427            result = _PyExc_CreateExceptionGroup("", raised_list);
1428        }
1429        else {
1430            result = Py_NewRef(PyList_GetItem(raised_list, 0));
1431        }
1432        if (result == NULL) {
1433            goto done;
1434        }
1435    }
1436
1437done:
1438    Py_XDECREF(raised_list);
1439    Py_XDECREF(reraised_list);
1440    return result;
1441}
1442
1443static PyMemberDef BaseExceptionGroup_members[] = {
1444    {"message", T_OBJECT, offsetof(PyBaseExceptionGroupObject, msg), READONLY,
1445        PyDoc_STR("exception message")},
1446    {"exceptions", T_OBJECT, offsetof(PyBaseExceptionGroupObject, excs), READONLY,
1447        PyDoc_STR("nested exceptions")},
1448    {NULL}  /* Sentinel */
1449};
1450
1451static PyMethodDef BaseExceptionGroup_methods[] = {
1452    {"__class_getitem__", (PyCFunction)Py_GenericAlias,
1453      METH_O|METH_CLASS, PyDoc_STR("See PEP 585")},
1454    {"derive", (PyCFunction)BaseExceptionGroup_derive, METH_VARARGS},
1455    {"split", (PyCFunction)BaseExceptionGroup_split, METH_VARARGS},
1456    {"subgroup", (PyCFunction)BaseExceptionGroup_subgroup, METH_VARARGS},
1457    {NULL}
1458};
1459
1460ComplexExtendsException(PyExc_BaseException, BaseExceptionGroup,
1461    BaseExceptionGroup, BaseExceptionGroup_new /* new */,
1462    BaseExceptionGroup_methods, BaseExceptionGroup_members,
1463    0 /* getset */, BaseExceptionGroup_str,
1464    "A combination of multiple unrelated exceptions.");
1465
1466/*
1467 *    ExceptionGroup extends BaseExceptionGroup, Exception
1468 */
1469static PyObject*
1470create_exception_group_class(void) {
1471    struct _Py_exc_state *state = get_exc_state();
1472
1473    PyObject *bases = PyTuple_Pack(
1474        2, PyExc_BaseExceptionGroup, PyExc_Exception);
1475    if (bases == NULL) {
1476        return NULL;
1477    }
1478
1479    assert(!state->PyExc_ExceptionGroup);
1480    state->PyExc_ExceptionGroup = PyErr_NewException(
1481        "builtins.ExceptionGroup", bases, NULL);
1482
1483    Py_DECREF(bases);
1484    return state->PyExc_ExceptionGroup;
1485}
1486
1487/*
1488 *    KeyboardInterrupt extends BaseException
1489 */
1490SimpleExtendsException(PyExc_BaseException, KeyboardInterrupt,
1491                       "Program interrupted by user.");
1492
1493
1494/*
1495 *    ImportError extends Exception
1496 */
1497
1498static int
1499ImportError_init(PyImportErrorObject *self, PyObject *args, PyObject *kwds)
1500{
1501    static char *kwlist[] = {"name", "path", 0};
1502    PyObject *empty_tuple;
1503    PyObject *msg = NULL;
1504    PyObject *name = NULL;
1505    PyObject *path = NULL;
1506
1507    if (BaseException_init((PyBaseExceptionObject *)self, args, NULL) == -1)
1508        return -1;
1509
1510    empty_tuple = PyTuple_New(0);
1511    if (!empty_tuple)
1512        return -1;
1513    if (!PyArg_ParseTupleAndKeywords(empty_tuple, kwds, "|$OO:ImportError", kwlist,
1514                                     &name, &path)) {
1515        Py_DECREF(empty_tuple);
1516        return -1;
1517    }
1518    Py_DECREF(empty_tuple);
1519
1520    Py_XINCREF(name);
1521    Py_XSETREF(self->name, name);
1522
1523    Py_XINCREF(path);
1524    Py_XSETREF(self->path, path);
1525
1526    if (PyTuple_GET_SIZE(args) == 1) {
1527        msg = PyTuple_GET_ITEM(args, 0);
1528        Py_INCREF(msg);
1529    }
1530    Py_XSETREF(self->msg, msg);
1531
1532    return 0;
1533}
1534
1535static int
1536ImportError_clear(PyImportErrorObject *self)
1537{
1538    Py_CLEAR(self->msg);
1539    Py_CLEAR(self->name);
1540    Py_CLEAR(self->path);
1541    return BaseException_clear((PyBaseExceptionObject *)self);
1542}
1543
1544static void
1545ImportError_dealloc(PyImportErrorObject *self)
1546{
1547    _PyObject_GC_UNTRACK(self);
1548    ImportError_clear(self);
1549    Py_TYPE(self)->tp_free((PyObject *)self);
1550}
1551
1552static int
1553ImportError_traverse(PyImportErrorObject *self, visitproc visit, void *arg)
1554{
1555    Py_VISIT(self->msg);
1556    Py_VISIT(self->name);
1557    Py_VISIT(self->path);
1558    return BaseException_traverse((PyBaseExceptionObject *)self, visit, arg);
1559}
1560
1561static PyObject *
1562ImportError_str(PyImportErrorObject *self)
1563{
1564    if (self->msg && PyUnicode_CheckExact(self->msg)) {
1565        Py_INCREF(self->msg);
1566        return self->msg;
1567    }
1568    else {
1569        return BaseException_str((PyBaseExceptionObject *)self);
1570    }
1571}
1572
1573static PyObject *
1574ImportError_getstate(PyImportErrorObject *self)
1575{
1576    PyObject *dict = ((PyBaseExceptionObject *)self)->dict;
1577    if (self->name || self->path) {
1578        dict = dict ? PyDict_Copy(dict) : PyDict_New();
1579        if (dict == NULL)
1580            return NULL;
1581        if (self->name && PyDict_SetItem(dict, &_Py_ID(name), self->name) < 0) {
1582            Py_DECREF(dict);
1583            return NULL;
1584        }
1585        if (self->path && PyDict_SetItem(dict, &_Py_ID(path), self->path) < 0) {
1586            Py_DECREF(dict);
1587            return NULL;
1588        }
1589        return dict;
1590    }
1591    else if (dict) {
1592        Py_INCREF(dict);
1593        return dict;
1594    }
1595    else {
1596        Py_RETURN_NONE;
1597    }
1598}
1599
1600/* Pickling support */
1601static PyObject *
1602ImportError_reduce(PyImportErrorObject *self, PyObject *Py_UNUSED(ignored))
1603{
1604    PyObject *res;
1605    PyObject *args;
1606    PyObject *state = ImportError_getstate(self);
1607    if (state == NULL)
1608        return NULL;
1609    args = ((PyBaseExceptionObject *)self)->args;
1610    if (state == Py_None)
1611        res = PyTuple_Pack(2, Py_TYPE(self), args);
1612    else
1613        res = PyTuple_Pack(3, Py_TYPE(self), args, state);
1614    Py_DECREF(state);
1615    return res;
1616}
1617
1618static PyMemberDef ImportError_members[] = {
1619    {"msg", T_OBJECT, offsetof(PyImportErrorObject, msg), 0,
1620        PyDoc_STR("exception message")},
1621    {"name", T_OBJECT, offsetof(PyImportErrorObject, name), 0,
1622        PyDoc_STR("module name")},
1623    {"path", T_OBJECT, offsetof(PyImportErrorObject, path), 0,
1624        PyDoc_STR("module path")},
1625    {NULL}  /* Sentinel */
1626};
1627
1628static PyMethodDef ImportError_methods[] = {
1629    {"__reduce__", (PyCFunction)ImportError_reduce, METH_NOARGS},
1630    {NULL}
1631};
1632
1633ComplexExtendsException(PyExc_Exception, ImportError,
1634                        ImportError, 0 /* new */,
1635                        ImportError_methods, ImportError_members,
1636                        0 /* getset */, ImportError_str,
1637                        "Import can't find module, or can't find name in "
1638                        "module.");
1639
1640/*
1641 *    ModuleNotFoundError extends ImportError
1642 */
1643
1644MiddlingExtendsException(PyExc_ImportError, ModuleNotFoundError, ImportError,
1645                         "Module not found.");
1646
1647/*
1648 *    OSError extends Exception
1649 */
1650
1651#ifdef MS_WINDOWS
1652#include "errmap.h"
1653#endif
1654
1655/* Where a function has a single filename, such as open() or some
1656 * of the os module functions, PyErr_SetFromErrnoWithFilename() is
1657 * called, giving a third argument which is the filename.  But, so
1658 * that old code using in-place unpacking doesn't break, e.g.:
1659 *
1660 * except OSError, (errno, strerror):
1661 *
1662 * we hack args so that it only contains two items.  This also
1663 * means we need our own __str__() which prints out the filename
1664 * when it was supplied.
1665 *
1666 * (If a function has two filenames, such as rename(), symlink(),
1667 * or copy(), PyErr_SetFromErrnoWithFilenameObjects() is called,
1668 * which allows passing in a second filename.)
1669 */
1670
1671/* This function doesn't cleanup on error, the caller should */
1672static int
1673oserror_parse_args(PyObject **p_args,
1674                   PyObject **myerrno, PyObject **strerror,
1675                   PyObject **filename, PyObject **filename2
1676#ifdef MS_WINDOWS
1677                   , PyObject **winerror
1678#endif
1679                  )
1680{
1681    Py_ssize_t nargs;
1682    PyObject *args = *p_args;
1683#ifndef MS_WINDOWS
1684    /*
1685     * ignored on non-Windows platforms,
1686     * but parsed so OSError has a consistent signature
1687     */
1688    PyObject *_winerror = NULL;
1689    PyObject **winerror = &_winerror;
1690#endif /* MS_WINDOWS */
1691
1692    nargs = PyTuple_GET_SIZE(args);
1693
1694    if (nargs >= 2 && nargs <= 5) {
1695        if (!PyArg_UnpackTuple(args, "OSError", 2, 5,
1696                               myerrno, strerror,
1697                               filename, winerror, filename2))
1698            return -1;
1699#ifdef MS_WINDOWS
1700        if (*winerror && PyLong_Check(*winerror)) {
1701            long errcode, winerrcode;
1702            PyObject *newargs;
1703            Py_ssize_t i;
1704
1705            winerrcode = PyLong_AsLong(*winerror);
1706            if (winerrcode == -1 && PyErr_Occurred())
1707                return -1;
1708            errcode = winerror_to_errno(winerrcode);
1709            *myerrno = PyLong_FromLong(errcode);
1710            if (!*myerrno)
1711                return -1;
1712            newargs = PyTuple_New(nargs);
1713            if (!newargs)
1714                return -1;
1715            PyTuple_SET_ITEM(newargs, 0, *myerrno);
1716            for (i = 1; i < nargs; i++) {
1717                PyObject *val = PyTuple_GET_ITEM(args, i);
1718                Py_INCREF(val);
1719                PyTuple_SET_ITEM(newargs, i, val);
1720            }
1721            Py_DECREF(args);
1722            args = *p_args = newargs;
1723        }
1724#endif /* MS_WINDOWS */
1725    }
1726
1727    return 0;
1728}
1729
1730static int
1731oserror_init(PyOSErrorObject *self, PyObject **p_args,
1732             PyObject *myerrno, PyObject *strerror,
1733             PyObject *filename, PyObject *filename2
1734#ifdef MS_WINDOWS
1735             , PyObject *winerror
1736#endif
1737             )
1738{
1739    PyObject *args = *p_args;
1740    Py_ssize_t nargs = PyTuple_GET_SIZE(args);
1741
1742    /* self->filename will remain Py_None otherwise */
1743    if (filename && filename != Py_None) {
1744        if (Py_IS_TYPE(self, (PyTypeObject *) PyExc_BlockingIOError) &&
1745            PyNumber_Check(filename)) {
1746            /* BlockingIOError's 3rd argument can be the number of
1747             * characters written.
1748             */
1749            self->written = PyNumber_AsSsize_t(filename, PyExc_ValueError);
1750            if (self->written == -1 && PyErr_Occurred())
1751                return -1;
1752        }
1753        else {
1754            Py_INCREF(filename);
1755            self->filename = filename;
1756
1757            if (filename2 && filename2 != Py_None) {
1758                Py_INCREF(filename2);
1759                self->filename2 = filename2;
1760            }
1761
1762            if (nargs >= 2 && nargs <= 5) {
1763                /* filename, filename2, and winerror are removed from the args tuple
1764                   (for compatibility purposes, see test_exceptions.py) */
1765                PyObject *subslice = PyTuple_GetSlice(args, 0, 2);
1766                if (!subslice)
1767                    return -1;
1768
1769                Py_DECREF(args);  /* replacing args */
1770                *p_args = args = subslice;
1771            }
1772        }
1773    }
1774    Py_XINCREF(myerrno);
1775    self->myerrno = myerrno;
1776
1777    Py_XINCREF(strerror);
1778    self->strerror = strerror;
1779
1780#ifdef MS_WINDOWS
1781    Py_XINCREF(winerror);
1782    self->winerror = winerror;
1783#endif
1784
1785    /* Steals the reference to args */
1786    Py_XSETREF(self->args, args);
1787    *p_args = args = NULL;
1788
1789    return 0;
1790}
1791
1792static PyObject *
1793OSError_new(PyTypeObject *type, PyObject *args, PyObject *kwds);
1794static int
1795OSError_init(PyOSErrorObject *self, PyObject *args, PyObject *kwds);
1796
1797static int
1798oserror_use_init(PyTypeObject *type)
1799{
1800    /* When __init__ is defined in an OSError subclass, we want any
1801       extraneous argument to __new__ to be ignored.  The only reasonable
1802       solution, given __new__ takes a variable number of arguments,
1803       is to defer arg parsing and initialization to __init__.
1804
1805       But when __new__ is overridden as well, it should call our __new__
1806       with the right arguments.
1807
1808       (see http://bugs.python.org/issue12555#msg148829 )
1809    */
1810    if (type->tp_init != (initproc) OSError_init &&
1811        type->tp_new == (newfunc) OSError_new) {
1812        assert((PyObject *) type != PyExc_OSError);
1813        return 1;
1814    }
1815    return 0;
1816}
1817
1818static PyObject *
1819OSError_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
1820{
1821    PyOSErrorObject *self = NULL;
1822    PyObject *myerrno = NULL, *strerror = NULL;
1823    PyObject *filename = NULL, *filename2 = NULL;
1824#ifdef MS_WINDOWS
1825    PyObject *winerror = NULL;
1826#endif
1827
1828    Py_INCREF(args);
1829
1830    if (!oserror_use_init(type)) {
1831        if (!_PyArg_NoKeywords(type->tp_name, kwds))
1832            goto error;
1833
1834        if (oserror_parse_args(&args, &myerrno, &strerror,
1835                               &filename, &filename2
1836#ifdef MS_WINDOWS
1837                               , &winerror
1838#endif
1839            ))
1840            goto error;
1841
1842        struct _Py_exc_state *state = get_exc_state();
1843        if (myerrno && PyLong_Check(myerrno) &&
1844            state->errnomap && (PyObject *) type == PyExc_OSError) {
1845            PyObject *newtype;
1846            newtype = PyDict_GetItemWithError(state->errnomap, myerrno);
1847            if (newtype) {
1848                type = _PyType_CAST(newtype);
1849            }
1850            else if (PyErr_Occurred())
1851                goto error;
1852        }
1853    }
1854
1855    self = (PyOSErrorObject *) type->tp_alloc(type, 0);
1856    if (!self)
1857        goto error;
1858
1859    self->dict = NULL;
1860    self->traceback = self->cause = self->context = NULL;
1861    self->written = -1;
1862
1863    if (!oserror_use_init(type)) {
1864        if (oserror_init(self, &args, myerrno, strerror, filename, filename2
1865#ifdef MS_WINDOWS
1866                         , winerror
1867#endif
1868            ))
1869            goto error;
1870    }
1871    else {
1872        self->args = PyTuple_New(0);
1873        if (self->args == NULL)
1874            goto error;
1875    }
1876
1877    Py_XDECREF(args);
1878    return (PyObject *) self;
1879
1880error:
1881    Py_XDECREF(args);
1882    Py_XDECREF(self);
1883    return NULL;
1884}
1885
1886static int
1887OSError_init(PyOSErrorObject *self, PyObject *args, PyObject *kwds)
1888{
1889    PyObject *myerrno = NULL, *strerror = NULL;
1890    PyObject *filename = NULL, *filename2 = NULL;
1891#ifdef MS_WINDOWS
1892    PyObject *winerror = NULL;
1893#endif
1894
1895    if (!oserror_use_init(Py_TYPE(self)))
1896        /* Everything already done in OSError_new */
1897        return 0;
1898
1899    if (!_PyArg_NoKeywords(Py_TYPE(self)->tp_name, kwds))
1900        return -1;
1901
1902    Py_INCREF(args);
1903    if (oserror_parse_args(&args, &myerrno, &strerror, &filename, &filename2
1904#ifdef MS_WINDOWS
1905                           , &winerror
1906#endif
1907        ))
1908        goto error;
1909
1910    if (oserror_init(self, &args, myerrno, strerror, filename, filename2
1911#ifdef MS_WINDOWS
1912                     , winerror
1913#endif
1914        ))
1915        goto error;
1916
1917    return 0;
1918
1919error:
1920    Py_DECREF(args);
1921    return -1;
1922}
1923
1924static int
1925OSError_clear(PyOSErrorObject *self)
1926{
1927    Py_CLEAR(self->myerrno);
1928    Py_CLEAR(self->strerror);
1929    Py_CLEAR(self->filename);
1930    Py_CLEAR(self->filename2);
1931#ifdef MS_WINDOWS
1932    Py_CLEAR(self->winerror);
1933#endif
1934    return BaseException_clear((PyBaseExceptionObject *)self);
1935}
1936
1937static void
1938OSError_dealloc(PyOSErrorObject *self)
1939{
1940    _PyObject_GC_UNTRACK(self);
1941    OSError_clear(self);
1942    Py_TYPE(self)->tp_free((PyObject *)self);
1943}
1944
1945static int
1946OSError_traverse(PyOSErrorObject *self, visitproc visit,
1947        void *arg)
1948{
1949    Py_VISIT(self->myerrno);
1950    Py_VISIT(self->strerror);
1951    Py_VISIT(self->filename);
1952    Py_VISIT(self->filename2);
1953#ifdef MS_WINDOWS
1954    Py_VISIT(self->winerror);
1955#endif
1956    return BaseException_traverse((PyBaseExceptionObject *)self, visit, arg);
1957}
1958
1959static PyObject *
1960OSError_str(PyOSErrorObject *self)
1961{
1962#define OR_NONE(x) ((x)?(x):Py_None)
1963#ifdef MS_WINDOWS
1964    /* If available, winerror has the priority over myerrno */
1965    if (self->winerror && self->filename) {
1966        if (self->filename2) {
1967            return PyUnicode_FromFormat("[WinError %S] %S: %R -> %R",
1968                                        OR_NONE(self->winerror),
1969                                        OR_NONE(self->strerror),
1970                                        self->filename,
1971                                        self->filename2);
1972        } else {
1973            return PyUnicode_FromFormat("[WinError %S] %S: %R",
1974                                        OR_NONE(self->winerror),
1975                                        OR_NONE(self->strerror),
1976                                        self->filename);
1977        }
1978    }
1979    if (self->winerror && self->strerror)
1980        return PyUnicode_FromFormat("[WinError %S] %S",
1981                                    self->winerror ? self->winerror: Py_None,
1982                                    self->strerror ? self->strerror: Py_None);
1983#endif
1984    if (self->filename) {
1985        if (self->filename2) {
1986            return PyUnicode_FromFormat("[Errno %S] %S: %R -> %R",
1987                                        OR_NONE(self->myerrno),
1988                                        OR_NONE(self->strerror),
1989                                        self->filename,
1990                                        self->filename2);
1991        } else {
1992            return PyUnicode_FromFormat("[Errno %S] %S: %R",
1993                                        OR_NONE(self->myerrno),
1994                                        OR_NONE(self->strerror),
1995                                        self->filename);
1996        }
1997    }
1998    if (self->myerrno && self->strerror)
1999        return PyUnicode_FromFormat("[Errno %S] %S",
2000                                    self->myerrno, self->strerror);
2001    return BaseException_str((PyBaseExceptionObject *)self);
2002}
2003
2004static PyObject *
2005OSError_reduce(PyOSErrorObject *self, PyObject *Py_UNUSED(ignored))
2006{
2007    PyObject *args = self->args;
2008    PyObject *res = NULL, *tmp;
2009
2010    /* self->args is only the first two real arguments if there was a
2011     * file name given to OSError. */
2012    if (PyTuple_GET_SIZE(args) == 2 && self->filename) {
2013        Py_ssize_t size = self->filename2 ? 5 : 3;
2014        args = PyTuple_New(size);
2015        if (!args)
2016            return NULL;
2017
2018        tmp = PyTuple_GET_ITEM(self->args, 0);
2019        Py_INCREF(tmp);
2020        PyTuple_SET_ITEM(args, 0, tmp);
2021
2022        tmp = PyTuple_GET_ITEM(self->args, 1);
2023        Py_INCREF(tmp);
2024        PyTuple_SET_ITEM(args, 1, tmp);
2025
2026        Py_INCREF(self->filename);
2027        PyTuple_SET_ITEM(args, 2, self->filename);
2028
2029        if (self->filename2) {
2030            /*
2031             * This tuple is essentially used as OSError(*args).
2032             * So, to recreate filename2, we need to pass in
2033             * winerror as well.
2034             */
2035            Py_INCREF(Py_None);
2036            PyTuple_SET_ITEM(args, 3, Py_None);
2037
2038            /* filename2 */
2039            Py_INCREF(self->filename2);
2040            PyTuple_SET_ITEM(args, 4, self->filename2);
2041        }
2042    } else
2043        Py_INCREF(args);
2044
2045    if (self->dict)
2046        res = PyTuple_Pack(3, Py_TYPE(self), args, self->dict);
2047    else
2048        res = PyTuple_Pack(2, Py_TYPE(self), args);
2049    Py_DECREF(args);
2050    return res;
2051}
2052
2053static PyObject *
2054OSError_written_get(PyOSErrorObject *self, void *context)
2055{
2056    if (self->written == -1) {
2057        PyErr_SetString(PyExc_AttributeError, "characters_written");
2058        return NULL;
2059    }
2060    return PyLong_FromSsize_t(self->written);
2061}
2062
2063static int
2064OSError_written_set(PyOSErrorObject *self, PyObject *arg, void *context)
2065{
2066    if (arg == NULL) {
2067        if (self->written == -1) {
2068            PyErr_SetString(PyExc_AttributeError, "characters_written");
2069            return -1;
2070        }
2071        self->written = -1;
2072        return 0;
2073    }
2074    Py_ssize_t n;
2075    n = PyNumber_AsSsize_t(arg, PyExc_ValueError);
2076    if (n == -1 && PyErr_Occurred())
2077        return -1;
2078    self->written = n;
2079    return 0;
2080}
2081
2082static PyMemberDef OSError_members[] = {
2083    {"errno", T_OBJECT, offsetof(PyOSErrorObject, myerrno), 0,
2084        PyDoc_STR("POSIX exception code")},
2085    {"strerror", T_OBJECT, offsetof(PyOSErrorObject, strerror), 0,
2086        PyDoc_STR("exception strerror")},
2087    {"filename", T_OBJECT, offsetof(PyOSErrorObject, filename), 0,
2088        PyDoc_STR("exception filename")},
2089    {"filename2", T_OBJECT, offsetof(PyOSErrorObject, filename2), 0,
2090        PyDoc_STR("second exception filename")},
2091#ifdef MS_WINDOWS
2092    {"winerror", T_OBJECT, offsetof(PyOSErrorObject, winerror), 0,
2093        PyDoc_STR("Win32 exception code")},
2094#endif
2095    {NULL}  /* Sentinel */
2096};
2097
2098static PyMethodDef OSError_methods[] = {
2099    {"__reduce__", (PyCFunction)OSError_reduce, METH_NOARGS},
2100    {NULL}
2101};
2102
2103static PyGetSetDef OSError_getset[] = {
2104    {"characters_written", (getter) OSError_written_get,
2105                           (setter) OSError_written_set, NULL},
2106    {NULL}
2107};
2108
2109
2110ComplexExtendsException(PyExc_Exception, OSError,
2111                        OSError, OSError_new,
2112                        OSError_methods, OSError_members, OSError_getset,
2113                        OSError_str,
2114                        "Base class for I/O related errors.");
2115
2116
2117/*
2118 *    Various OSError subclasses
2119 */
2120MiddlingExtendsException(PyExc_OSError, BlockingIOError, OSError,
2121                         "I/O operation would block.");
2122MiddlingExtendsException(PyExc_OSError, ConnectionError, OSError,
2123                         "Connection error.");
2124MiddlingExtendsException(PyExc_OSError, ChildProcessError, OSError,
2125                         "Child process error.");
2126MiddlingExtendsException(PyExc_ConnectionError, BrokenPipeError, OSError,
2127                         "Broken pipe.");
2128MiddlingExtendsException(PyExc_ConnectionError, ConnectionAbortedError, OSError,
2129                         "Connection aborted.");
2130MiddlingExtendsException(PyExc_ConnectionError, ConnectionRefusedError, OSError,
2131                         "Connection refused.");
2132MiddlingExtendsException(PyExc_ConnectionError, ConnectionResetError, OSError,
2133                         "Connection reset.");
2134MiddlingExtendsException(PyExc_OSError, FileExistsError, OSError,
2135                         "File already exists.");
2136MiddlingExtendsException(PyExc_OSError, FileNotFoundError, OSError,
2137                         "File not found.");
2138MiddlingExtendsException(PyExc_OSError, IsADirectoryError, OSError,
2139                         "Operation doesn't work on directories.");
2140MiddlingExtendsException(PyExc_OSError, NotADirectoryError, OSError,
2141                         "Operation only works on directories.");
2142MiddlingExtendsException(PyExc_OSError, InterruptedError, OSError,
2143                         "Interrupted by signal.");
2144MiddlingExtendsException(PyExc_OSError, PermissionError, OSError,
2145                         "Not enough permissions.");
2146MiddlingExtendsException(PyExc_OSError, ProcessLookupError, OSError,
2147                         "Process not found.");
2148MiddlingExtendsException(PyExc_OSError, TimeoutError, OSError,
2149                         "Timeout expired.");
2150
2151/*
2152 *    EOFError extends Exception
2153 */
2154SimpleExtendsException(PyExc_Exception, EOFError,
2155                       "Read beyond end of file.");
2156
2157
2158/*
2159 *    RuntimeError extends Exception
2160 */
2161SimpleExtendsException(PyExc_Exception, RuntimeError,
2162                       "Unspecified run-time error.");
2163
2164/*
2165 *    RecursionError extends RuntimeError
2166 */
2167SimpleExtendsException(PyExc_RuntimeError, RecursionError,
2168                       "Recursion limit exceeded.");
2169
2170/*
2171 *    NotImplementedError extends RuntimeError
2172 */
2173SimpleExtendsException(PyExc_RuntimeError, NotImplementedError,
2174                       "Method or function hasn't been implemented yet.");
2175
2176/*
2177 *    NameError extends Exception
2178 */
2179
2180static int
2181NameError_init(PyNameErrorObject *self, PyObject *args, PyObject *kwds)
2182{
2183    static char *kwlist[] = {"name", NULL};
2184    PyObject *name = NULL;
2185
2186    if (BaseException_init((PyBaseExceptionObject *)self, args, NULL) == -1) {
2187        return -1;
2188    }
2189
2190    PyObject *empty_tuple = PyTuple_New(0);
2191    if (!empty_tuple) {
2192        return -1;
2193    }
2194    if (!PyArg_ParseTupleAndKeywords(empty_tuple, kwds, "|$O:NameError", kwlist,
2195                                     &name)) {
2196        Py_DECREF(empty_tuple);
2197        return -1;
2198    }
2199    Py_DECREF(empty_tuple);
2200
2201    Py_XINCREF(name);
2202    Py_XSETREF(self->name, name);
2203
2204    return 0;
2205}
2206
2207static int
2208NameError_clear(PyNameErrorObject *self)
2209{
2210    Py_CLEAR(self->name);
2211    return BaseException_clear((PyBaseExceptionObject *)self);
2212}
2213
2214static void
2215NameError_dealloc(PyNameErrorObject *self)
2216{
2217    _PyObject_GC_UNTRACK(self);
2218    NameError_clear(self);
2219    Py_TYPE(self)->tp_free((PyObject *)self);
2220}
2221
2222static int
2223NameError_traverse(PyNameErrorObject *self, visitproc visit, void *arg)
2224{
2225    Py_VISIT(self->name);
2226    return BaseException_traverse((PyBaseExceptionObject *)self, visit, arg);
2227}
2228
2229static PyMemberDef NameError_members[] = {
2230        {"name", T_OBJECT, offsetof(PyNameErrorObject, name), 0, PyDoc_STR("name")},
2231        {NULL}  /* Sentinel */
2232};
2233
2234static PyMethodDef NameError_methods[] = {
2235        {NULL}  /* Sentinel */
2236};
2237
2238ComplexExtendsException(PyExc_Exception, NameError,
2239                        NameError, 0,
2240                        NameError_methods, NameError_members,
2241                        0, BaseException_str, "Name not found globally.");
2242
2243/*
2244 *    UnboundLocalError extends NameError
2245 */
2246
2247MiddlingExtendsException(PyExc_NameError, UnboundLocalError, NameError,
2248                       "Local name referenced but not bound to a value.");
2249
2250/*
2251 *    AttributeError extends Exception
2252 */
2253
2254static int
2255AttributeError_init(PyAttributeErrorObject *self, PyObject *args, PyObject *kwds)
2256{
2257    static char *kwlist[] = {"name", "obj", NULL};
2258    PyObject *name = NULL;
2259    PyObject *obj = NULL;
2260
2261    if (BaseException_init((PyBaseExceptionObject *)self, args, NULL) == -1) {
2262        return -1;
2263    }
2264
2265    PyObject *empty_tuple = PyTuple_New(0);
2266    if (!empty_tuple) {
2267        return -1;
2268    }
2269    if (!PyArg_ParseTupleAndKeywords(empty_tuple, kwds, "|$OO:AttributeError", kwlist,
2270                                     &name, &obj)) {
2271        Py_DECREF(empty_tuple);
2272        return -1;
2273    }
2274    Py_DECREF(empty_tuple);
2275
2276    Py_XINCREF(name);
2277    Py_XSETREF(self->name, name);
2278
2279    Py_XINCREF(obj);
2280    Py_XSETREF(self->obj, obj);
2281
2282    return 0;
2283}
2284
2285static int
2286AttributeError_clear(PyAttributeErrorObject *self)
2287{
2288    Py_CLEAR(self->obj);
2289    Py_CLEAR(self->name);
2290    return BaseException_clear((PyBaseExceptionObject *)self);
2291}
2292
2293static void
2294AttributeError_dealloc(PyAttributeErrorObject *self)
2295{
2296    _PyObject_GC_UNTRACK(self);
2297    AttributeError_clear(self);
2298    Py_TYPE(self)->tp_free((PyObject *)self);
2299}
2300
2301static int
2302AttributeError_traverse(PyAttributeErrorObject *self, visitproc visit, void *arg)
2303{
2304    Py_VISIT(self->obj);
2305    Py_VISIT(self->name);
2306    return BaseException_traverse((PyBaseExceptionObject *)self, visit, arg);
2307}
2308
2309static PyMemberDef AttributeError_members[] = {
2310    {"name", T_OBJECT, offsetof(PyAttributeErrorObject, name), 0, PyDoc_STR("attribute name")},
2311    {"obj", T_OBJECT, offsetof(PyAttributeErrorObject, obj), 0, PyDoc_STR("object")},
2312    {NULL}  /* Sentinel */
2313};
2314
2315static PyMethodDef AttributeError_methods[] = {
2316    {NULL}  /* Sentinel */
2317};
2318
2319ComplexExtendsException(PyExc_Exception, AttributeError,
2320                        AttributeError, 0,
2321                        AttributeError_methods, AttributeError_members,
2322                        0, BaseException_str, "Attribute not found.");
2323
2324/*
2325 *    SyntaxError extends Exception
2326 */
2327
2328static int
2329SyntaxError_init(PySyntaxErrorObject *self, PyObject *args, PyObject *kwds)
2330{
2331    PyObject *info = NULL;
2332    Py_ssize_t lenargs = PyTuple_GET_SIZE(args);
2333
2334    if (BaseException_init((PyBaseExceptionObject *)self, args, kwds) == -1)
2335        return -1;
2336
2337    if (lenargs >= 1) {
2338        Py_INCREF(PyTuple_GET_ITEM(args, 0));
2339        Py_XSETREF(self->msg, PyTuple_GET_ITEM(args, 0));
2340    }
2341    if (lenargs == 2) {
2342        info = PyTuple_GET_ITEM(args, 1);
2343        info = PySequence_Tuple(info);
2344        if (!info) {
2345            return -1;
2346        }
2347
2348        self->end_lineno = NULL;
2349        self->end_offset = NULL;
2350        if (!PyArg_ParseTuple(info, "OOOO|OO",
2351                              &self->filename, &self->lineno,
2352                              &self->offset, &self->text,
2353                              &self->end_lineno, &self->end_offset)) {
2354            Py_DECREF(info);
2355            return -1;
2356        }
2357
2358        Py_INCREF(self->filename);
2359        Py_INCREF(self->lineno);
2360        Py_INCREF(self->offset);
2361        Py_INCREF(self->text);
2362        Py_XINCREF(self->end_lineno);
2363        Py_XINCREF(self->end_offset);
2364        Py_DECREF(info);
2365
2366        if (self->end_lineno != NULL && self->end_offset == NULL) {
2367            PyErr_SetString(PyExc_TypeError, "end_offset must be provided when end_lineno is provided");
2368            return -1;
2369        }
2370    }
2371    return 0;
2372}
2373
2374static int
2375SyntaxError_clear(PySyntaxErrorObject *self)
2376{
2377    Py_CLEAR(self->msg);
2378    Py_CLEAR(self->filename);
2379    Py_CLEAR(self->lineno);
2380    Py_CLEAR(self->offset);
2381    Py_CLEAR(self->end_lineno);
2382    Py_CLEAR(self->end_offset);
2383    Py_CLEAR(self->text);
2384    Py_CLEAR(self->print_file_and_line);
2385    return BaseException_clear((PyBaseExceptionObject *)self);
2386}
2387
2388static void
2389SyntaxError_dealloc(PySyntaxErrorObject *self)
2390{
2391    _PyObject_GC_UNTRACK(self);
2392    SyntaxError_clear(self);
2393    Py_TYPE(self)->tp_free((PyObject *)self);
2394}
2395
2396static int
2397SyntaxError_traverse(PySyntaxErrorObject *self, visitproc visit, void *arg)
2398{
2399    Py_VISIT(self->msg);
2400    Py_VISIT(self->filename);
2401    Py_VISIT(self->lineno);
2402    Py_VISIT(self->offset);
2403    Py_VISIT(self->end_lineno);
2404    Py_VISIT(self->end_offset);
2405    Py_VISIT(self->text);
2406    Py_VISIT(self->print_file_and_line);
2407    return BaseException_traverse((PyBaseExceptionObject *)self, visit, arg);
2408}
2409
2410/* This is called "my_basename" instead of just "basename" to avoid name
2411   conflicts with glibc; basename is already prototyped if _GNU_SOURCE is
2412   defined, and Python does define that. */
2413static PyObject*
2414my_basename(PyObject *name)
2415{
2416    Py_ssize_t i, size, offset;
2417    int kind;
2418    const void *data;
2419
2420    if (PyUnicode_READY(name))
2421        return NULL;
2422    kind = PyUnicode_KIND(name);
2423    data = PyUnicode_DATA(name);
2424    size = PyUnicode_GET_LENGTH(name);
2425    offset = 0;
2426    for(i=0; i < size; i++) {
2427        if (PyUnicode_READ(kind, data, i) == SEP) {
2428            offset = i + 1;
2429        }
2430    }
2431    if (offset != 0) {
2432        return PyUnicode_Substring(name, offset, size);
2433    }
2434    else {
2435        Py_INCREF(name);
2436        return name;
2437    }
2438}
2439
2440
2441static PyObject *
2442SyntaxError_str(PySyntaxErrorObject *self)
2443{
2444    int have_lineno = 0;
2445    PyObject *filename;
2446    PyObject *result;
2447    /* Below, we always ignore overflow errors, just printing -1.
2448       Still, we cannot allow an OverflowError to be raised, so
2449       we need to call PyLong_AsLongAndOverflow. */
2450    int overflow;
2451
2452    /* XXX -- do all the additional formatting with filename and
2453       lineno here */
2454
2455    if (self->filename && PyUnicode_Check(self->filename)) {
2456        filename = my_basename(self->filename);
2457        if (filename == NULL)
2458            return NULL;
2459    } else {
2460        filename = NULL;
2461    }
2462    have_lineno = (self->lineno != NULL) && PyLong_CheckExact(self->lineno);
2463
2464    if (!filename && !have_lineno)
2465        return PyObject_Str(self->msg ? self->msg : Py_None);
2466
2467    if (filename && have_lineno)
2468        result = PyUnicode_FromFormat("%S (%U, line %ld)",
2469                   self->msg ? self->msg : Py_None,
2470                   filename,
2471                   PyLong_AsLongAndOverflow(self->lineno, &overflow));
2472    else if (filename)
2473        result = PyUnicode_FromFormat("%S (%U)",
2474                   self->msg ? self->msg : Py_None,
2475                   filename);
2476    else /* only have_lineno */
2477        result = PyUnicode_FromFormat("%S (line %ld)",
2478                   self->msg ? self->msg : Py_None,
2479                   PyLong_AsLongAndOverflow(self->lineno, &overflow));
2480    Py_XDECREF(filename);
2481    return result;
2482}
2483
2484static PyMemberDef SyntaxError_members[] = {
2485    {"msg", T_OBJECT, offsetof(PySyntaxErrorObject, msg), 0,
2486        PyDoc_STR("exception msg")},
2487    {"filename", T_OBJECT, offsetof(PySyntaxErrorObject, filename), 0,
2488        PyDoc_STR("exception filename")},
2489    {"lineno", T_OBJECT, offsetof(PySyntaxErrorObject, lineno), 0,
2490        PyDoc_STR("exception lineno")},
2491    {"offset", T_OBJECT, offsetof(PySyntaxErrorObject, offset), 0,
2492        PyDoc_STR("exception offset")},
2493    {"text", T_OBJECT, offsetof(PySyntaxErrorObject, text), 0,
2494        PyDoc_STR("exception text")},
2495    {"end_lineno", T_OBJECT, offsetof(PySyntaxErrorObject, end_lineno), 0,
2496                   PyDoc_STR("exception end lineno")},
2497    {"end_offset", T_OBJECT, offsetof(PySyntaxErrorObject, end_offset), 0,
2498                   PyDoc_STR("exception end offset")},
2499    {"print_file_and_line", T_OBJECT,
2500        offsetof(PySyntaxErrorObject, print_file_and_line), 0,
2501        PyDoc_STR("exception print_file_and_line")},
2502    {NULL}  /* Sentinel */
2503};
2504
2505ComplexExtendsException(PyExc_Exception, SyntaxError, SyntaxError,
2506                        0, 0, SyntaxError_members, 0,
2507                        SyntaxError_str, "Invalid syntax.");
2508
2509
2510/*
2511 *    IndentationError extends SyntaxError
2512 */
2513MiddlingExtendsException(PyExc_SyntaxError, IndentationError, SyntaxError,
2514                         "Improper indentation.");
2515
2516
2517/*
2518 *    TabError extends IndentationError
2519 */
2520MiddlingExtendsException(PyExc_IndentationError, TabError, SyntaxError,
2521                         "Improper mixture of spaces and tabs.");
2522
2523
2524/*
2525 *    LookupError extends Exception
2526 */
2527SimpleExtendsException(PyExc_Exception, LookupError,
2528                       "Base class for lookup errors.");
2529
2530
2531/*
2532 *    IndexError extends LookupError
2533 */
2534SimpleExtendsException(PyExc_LookupError, IndexError,
2535                       "Sequence index out of range.");
2536
2537
2538/*
2539 *    KeyError extends LookupError
2540 */
2541static PyObject *
2542KeyError_str(PyBaseExceptionObject *self)
2543{
2544    /* If args is a tuple of exactly one item, apply repr to args[0].
2545       This is done so that e.g. the exception raised by {}[''] prints
2546         KeyError: ''
2547       rather than the confusing
2548         KeyError
2549       alone.  The downside is that if KeyError is raised with an explanatory
2550       string, that string will be displayed in quotes.  Too bad.
2551       If args is anything else, use the default BaseException__str__().
2552    */
2553    if (PyTuple_GET_SIZE(self->args) == 1) {
2554        return PyObject_Repr(PyTuple_GET_ITEM(self->args, 0));
2555    }
2556    return BaseException_str(self);
2557}
2558
2559ComplexExtendsException(PyExc_LookupError, KeyError, BaseException,
2560                        0, 0, 0, 0, KeyError_str, "Mapping key not found.");
2561
2562
2563/*
2564 *    ValueError extends Exception
2565 */
2566SimpleExtendsException(PyExc_Exception, ValueError,
2567                       "Inappropriate argument value (of correct type).");
2568
2569/*
2570 *    UnicodeError extends ValueError
2571 */
2572
2573SimpleExtendsException(PyExc_ValueError, UnicodeError,
2574                       "Unicode related error.");
2575
2576static PyObject *
2577get_string(PyObject *attr, const char *name)
2578{
2579    if (!attr) {
2580        PyErr_Format(PyExc_TypeError, "%.200s attribute not set", name);
2581        return NULL;
2582    }
2583
2584    if (!PyBytes_Check(attr)) {
2585        PyErr_Format(PyExc_TypeError, "%.200s attribute must be bytes", name);
2586        return NULL;
2587    }
2588    Py_INCREF(attr);
2589    return attr;
2590}
2591
2592static PyObject *
2593get_unicode(PyObject *attr, const char *name)
2594{
2595    if (!attr) {
2596        PyErr_Format(PyExc_TypeError, "%.200s attribute not set", name);
2597        return NULL;
2598    }
2599
2600    if (!PyUnicode_Check(attr)) {
2601        PyErr_Format(PyExc_TypeError,
2602                     "%.200s attribute must be unicode", name);
2603        return NULL;
2604    }
2605    Py_INCREF(attr);
2606    return attr;
2607}
2608
2609static int
2610set_unicodefromstring(PyObject **attr, const char *value)
2611{
2612    PyObject *obj = PyUnicode_FromString(value);
2613    if (!obj)
2614        return -1;
2615    Py_XSETREF(*attr, obj);
2616    return 0;
2617}
2618
2619PyObject *
2620PyUnicodeEncodeError_GetEncoding(PyObject *exc)
2621{
2622    return get_unicode(((PyUnicodeErrorObject *)exc)->encoding, "encoding");
2623}
2624
2625PyObject *
2626PyUnicodeDecodeError_GetEncoding(PyObject *exc)
2627{
2628    return get_unicode(((PyUnicodeErrorObject *)exc)->encoding, "encoding");
2629}
2630
2631PyObject *
2632PyUnicodeEncodeError_GetObject(PyObject *exc)
2633{
2634    return get_unicode(((PyUnicodeErrorObject *)exc)->object, "object");
2635}
2636
2637PyObject *
2638PyUnicodeDecodeError_GetObject(PyObject *exc)
2639{
2640    return get_string(((PyUnicodeErrorObject *)exc)->object, "object");
2641}
2642
2643PyObject *
2644PyUnicodeTranslateError_GetObject(PyObject *exc)
2645{
2646    return get_unicode(((PyUnicodeErrorObject *)exc)->object, "object");
2647}
2648
2649int
2650PyUnicodeEncodeError_GetStart(PyObject *exc, Py_ssize_t *start)
2651{
2652    Py_ssize_t size;
2653    PyObject *obj = get_unicode(((PyUnicodeErrorObject *)exc)->object,
2654                                "object");
2655    if (!obj)
2656        return -1;
2657    *start = ((PyUnicodeErrorObject *)exc)->start;
2658    size = PyUnicode_GET_LENGTH(obj);
2659    if (*start<0)
2660        *start = 0; /*XXX check for values <0*/
2661    if (*start>=size)
2662        *start = size-1;
2663    Py_DECREF(obj);
2664    return 0;
2665}
2666
2667
2668int
2669PyUnicodeDecodeError_GetStart(PyObject *exc, Py_ssize_t *start)
2670{
2671    Py_ssize_t size;
2672    PyObject *obj = get_string(((PyUnicodeErrorObject *)exc)->object, "object");
2673    if (!obj)
2674        return -1;
2675    size = PyBytes_GET_SIZE(obj);
2676    *start = ((PyUnicodeErrorObject *)exc)->start;
2677    if (*start<0)
2678        *start = 0;
2679    if (*start>=size)
2680        *start = size-1;
2681    Py_DECREF(obj);
2682    return 0;
2683}
2684
2685
2686int
2687PyUnicodeTranslateError_GetStart(PyObject *exc, Py_ssize_t *start)
2688{
2689    return PyUnicodeEncodeError_GetStart(exc, start);
2690}
2691
2692
2693int
2694PyUnicodeEncodeError_SetStart(PyObject *exc, Py_ssize_t start)
2695{
2696    ((PyUnicodeErrorObject *)exc)->start = start;
2697    return 0;
2698}
2699
2700
2701int
2702PyUnicodeDecodeError_SetStart(PyObject *exc, Py_ssize_t start)
2703{
2704    ((PyUnicodeErrorObject *)exc)->start = start;
2705    return 0;
2706}
2707
2708
2709int
2710PyUnicodeTranslateError_SetStart(PyObject *exc, Py_ssize_t start)
2711{
2712    ((PyUnicodeErrorObject *)exc)->start = start;
2713    return 0;
2714}
2715
2716
2717int
2718PyUnicodeEncodeError_GetEnd(PyObject *exc, Py_ssize_t *end)
2719{
2720    Py_ssize_t size;
2721    PyObject *obj = get_unicode(((PyUnicodeErrorObject *)exc)->object,
2722                                "object");
2723    if (!obj)
2724        return -1;
2725    *end = ((PyUnicodeErrorObject *)exc)->end;
2726    size = PyUnicode_GET_LENGTH(obj);
2727    if (*end<1)
2728        *end = 1;
2729    if (*end>size)
2730        *end = size;
2731    Py_DECREF(obj);
2732    return 0;
2733}
2734
2735
2736int
2737PyUnicodeDecodeError_GetEnd(PyObject *exc, Py_ssize_t *end)
2738{
2739    Py_ssize_t size;
2740    PyObject *obj = get_string(((PyUnicodeErrorObject *)exc)->object, "object");
2741    if (!obj)
2742        return -1;
2743    size = PyBytes_GET_SIZE(obj);
2744    *end = ((PyUnicodeErrorObject *)exc)->end;
2745    if (*end<1)
2746        *end = 1;
2747    if (*end>size)
2748        *end = size;
2749    Py_DECREF(obj);
2750    return 0;
2751}
2752
2753
2754int
2755PyUnicodeTranslateError_GetEnd(PyObject *exc, Py_ssize_t *end)
2756{
2757    return PyUnicodeEncodeError_GetEnd(exc, end);
2758}
2759
2760
2761int
2762PyUnicodeEncodeError_SetEnd(PyObject *exc, Py_ssize_t end)
2763{
2764    ((PyUnicodeErrorObject *)exc)->end = end;
2765    return 0;
2766}
2767
2768
2769int
2770PyUnicodeDecodeError_SetEnd(PyObject *exc, Py_ssize_t end)
2771{
2772    ((PyUnicodeErrorObject *)exc)->end = end;
2773    return 0;
2774}
2775
2776
2777int
2778PyUnicodeTranslateError_SetEnd(PyObject *exc, Py_ssize_t end)
2779{
2780    ((PyUnicodeErrorObject *)exc)->end = end;
2781    return 0;
2782}
2783
2784PyObject *
2785PyUnicodeEncodeError_GetReason(PyObject *exc)
2786{
2787    return get_unicode(((PyUnicodeErrorObject *)exc)->reason, "reason");
2788}
2789
2790
2791PyObject *
2792PyUnicodeDecodeError_GetReason(PyObject *exc)
2793{
2794    return get_unicode(((PyUnicodeErrorObject *)exc)->reason, "reason");
2795}
2796
2797
2798PyObject *
2799PyUnicodeTranslateError_GetReason(PyObject *exc)
2800{
2801    return get_unicode(((PyUnicodeErrorObject *)exc)->reason, "reason");
2802}
2803
2804
2805int
2806PyUnicodeEncodeError_SetReason(PyObject *exc, const char *reason)
2807{
2808    return set_unicodefromstring(&((PyUnicodeErrorObject *)exc)->reason,
2809                                 reason);
2810}
2811
2812
2813int
2814PyUnicodeDecodeError_SetReason(PyObject *exc, const char *reason)
2815{
2816    return set_unicodefromstring(&((PyUnicodeErrorObject *)exc)->reason,
2817                                 reason);
2818}
2819
2820
2821int
2822PyUnicodeTranslateError_SetReason(PyObject *exc, const char *reason)
2823{
2824    return set_unicodefromstring(&((PyUnicodeErrorObject *)exc)->reason,
2825                                 reason);
2826}
2827
2828
2829static int
2830UnicodeError_clear(PyUnicodeErrorObject *self)
2831{
2832    Py_CLEAR(self->encoding);
2833    Py_CLEAR(self->object);
2834    Py_CLEAR(self->reason);
2835    return BaseException_clear((PyBaseExceptionObject *)self);
2836}
2837
2838static void
2839UnicodeError_dealloc(PyUnicodeErrorObject *self)
2840{
2841    _PyObject_GC_UNTRACK(self);
2842    UnicodeError_clear(self);
2843    Py_TYPE(self)->tp_free((PyObject *)self);
2844}
2845
2846static int
2847UnicodeError_traverse(PyUnicodeErrorObject *self, visitproc visit, void *arg)
2848{
2849    Py_VISIT(self->encoding);
2850    Py_VISIT(self->object);
2851    Py_VISIT(self->reason);
2852    return BaseException_traverse((PyBaseExceptionObject *)self, visit, arg);
2853}
2854
2855static PyMemberDef UnicodeError_members[] = {
2856    {"encoding", T_OBJECT, offsetof(PyUnicodeErrorObject, encoding), 0,
2857        PyDoc_STR("exception encoding")},
2858    {"object", T_OBJECT, offsetof(PyUnicodeErrorObject, object), 0,
2859        PyDoc_STR("exception object")},
2860    {"start", T_PYSSIZET, offsetof(PyUnicodeErrorObject, start), 0,
2861        PyDoc_STR("exception start")},
2862    {"end", T_PYSSIZET, offsetof(PyUnicodeErrorObject, end), 0,
2863        PyDoc_STR("exception end")},
2864    {"reason", T_OBJECT, offsetof(PyUnicodeErrorObject, reason), 0,
2865        PyDoc_STR("exception reason")},
2866    {NULL}  /* Sentinel */
2867};
2868
2869
2870/*
2871 *    UnicodeEncodeError extends UnicodeError
2872 */
2873
2874static int
2875UnicodeEncodeError_init(PyObject *self, PyObject *args, PyObject *kwds)
2876{
2877    PyUnicodeErrorObject *err;
2878
2879    if (BaseException_init((PyBaseExceptionObject *)self, args, kwds) == -1)
2880        return -1;
2881
2882    err = (PyUnicodeErrorObject *)self;
2883
2884    Py_CLEAR(err->encoding);
2885    Py_CLEAR(err->object);
2886    Py_CLEAR(err->reason);
2887
2888    if (!PyArg_ParseTuple(args, "UUnnU",
2889                          &err->encoding, &err->object,
2890                          &err->start, &err->end, &err->reason)) {
2891        err->encoding = err->object = err->reason = NULL;
2892        return -1;
2893    }
2894
2895    Py_INCREF(err->encoding);
2896    Py_INCREF(err->object);
2897    Py_INCREF(err->reason);
2898
2899    return 0;
2900}
2901
2902static PyObject *
2903UnicodeEncodeError_str(PyObject *self)
2904{
2905    PyUnicodeErrorObject *uself = (PyUnicodeErrorObject *)self;
2906    PyObject *result = NULL;
2907    PyObject *reason_str = NULL;
2908    PyObject *encoding_str = NULL;
2909
2910    if (!uself->object)
2911        /* Not properly initialized. */
2912        return PyUnicode_FromString("");
2913
2914    /* Get reason and encoding as strings, which they might not be if
2915       they've been modified after we were constructed. */
2916    reason_str = PyObject_Str(uself->reason);
2917    if (reason_str == NULL)
2918        goto done;
2919    encoding_str = PyObject_Str(uself->encoding);
2920    if (encoding_str == NULL)
2921        goto done;
2922
2923    if (uself->start < PyUnicode_GET_LENGTH(uself->object) && uself->end == uself->start+1) {
2924        Py_UCS4 badchar = PyUnicode_ReadChar(uself->object, uself->start);
2925        const char *fmt;
2926        if (badchar <= 0xff)
2927            fmt = "'%U' codec can't encode character '\\x%02x' in position %zd: %U";
2928        else if (badchar <= 0xffff)
2929            fmt = "'%U' codec can't encode character '\\u%04x' in position %zd: %U";
2930        else
2931            fmt = "'%U' codec can't encode character '\\U%08x' in position %zd: %U";
2932        result = PyUnicode_FromFormat(
2933            fmt,
2934            encoding_str,
2935            (int)badchar,
2936            uself->start,
2937            reason_str);
2938    }
2939    else {
2940        result = PyUnicode_FromFormat(
2941            "'%U' codec can't encode characters in position %zd-%zd: %U",
2942            encoding_str,
2943            uself->start,
2944            uself->end-1,
2945            reason_str);
2946    }
2947done:
2948    Py_XDECREF(reason_str);
2949    Py_XDECREF(encoding_str);
2950    return result;
2951}
2952
2953static PyTypeObject _PyExc_UnicodeEncodeError = {
2954    PyVarObject_HEAD_INIT(NULL, 0)
2955    "UnicodeEncodeError",
2956    sizeof(PyUnicodeErrorObject), 0,
2957    (destructor)UnicodeError_dealloc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2958    (reprfunc)UnicodeEncodeError_str, 0, 0, 0,
2959    Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC,
2960    PyDoc_STR("Unicode encoding error."), (traverseproc)UnicodeError_traverse,
2961    (inquiry)UnicodeError_clear, 0, 0, 0, 0, 0, UnicodeError_members,
2962    0, &_PyExc_UnicodeError, 0, 0, 0, offsetof(PyUnicodeErrorObject, dict),
2963    (initproc)UnicodeEncodeError_init, 0, BaseException_new,
2964};
2965PyObject *PyExc_UnicodeEncodeError = (PyObject *)&_PyExc_UnicodeEncodeError;
2966
2967
2968/*
2969 *    UnicodeDecodeError extends UnicodeError
2970 */
2971
2972static int
2973UnicodeDecodeError_init(PyObject *self, PyObject *args, PyObject *kwds)
2974{
2975    PyUnicodeErrorObject *ude;
2976
2977    if (BaseException_init((PyBaseExceptionObject *)self, args, kwds) == -1)
2978        return -1;
2979
2980    ude = (PyUnicodeErrorObject *)self;
2981
2982    Py_CLEAR(ude->encoding);
2983    Py_CLEAR(ude->object);
2984    Py_CLEAR(ude->reason);
2985
2986    if (!PyArg_ParseTuple(args, "UOnnU",
2987                          &ude->encoding, &ude->object,
2988                          &ude->start, &ude->end, &ude->reason)) {
2989             ude->encoding = ude->object = ude->reason = NULL;
2990             return -1;
2991    }
2992
2993    Py_INCREF(ude->encoding);
2994    Py_INCREF(ude->object);
2995    Py_INCREF(ude->reason);
2996
2997    if (!PyBytes_Check(ude->object)) {
2998        Py_buffer view;
2999        if (PyObject_GetBuffer(ude->object, &view, PyBUF_SIMPLE) != 0)
3000            goto error;
3001        Py_XSETREF(ude->object, PyBytes_FromStringAndSize(view.buf, view.len));
3002        PyBuffer_Release(&view);
3003        if (!ude->object)
3004            goto error;
3005    }
3006    return 0;
3007
3008error:
3009    Py_CLEAR(ude->encoding);
3010    Py_CLEAR(ude->object);
3011    Py_CLEAR(ude->reason);
3012    return -1;
3013}
3014
3015static PyObject *
3016UnicodeDecodeError_str(PyObject *self)
3017{
3018    PyUnicodeErrorObject *uself = (PyUnicodeErrorObject *)self;
3019    PyObject *result = NULL;
3020    PyObject *reason_str = NULL;
3021    PyObject *encoding_str = NULL;
3022
3023    if (!uself->object)
3024        /* Not properly initialized. */
3025        return PyUnicode_FromString("");
3026
3027    /* Get reason and encoding as strings, which they might not be if
3028       they've been modified after we were constructed. */
3029    reason_str = PyObject_Str(uself->reason);
3030    if (reason_str == NULL)
3031        goto done;
3032    encoding_str = PyObject_Str(uself->encoding);
3033    if (encoding_str == NULL)
3034        goto done;
3035
3036    if (uself->start < PyBytes_GET_SIZE(uself->object) && uself->end == uself->start+1) {
3037        int byte = (int)(PyBytes_AS_STRING(((PyUnicodeErrorObject *)self)->object)[uself->start]&0xff);
3038        result = PyUnicode_FromFormat(
3039            "'%U' codec can't decode byte 0x%02x in position %zd: %U",
3040            encoding_str,
3041            byte,
3042            uself->start,
3043            reason_str);
3044    }
3045    else {
3046        result = PyUnicode_FromFormat(
3047            "'%U' codec can't decode bytes in position %zd-%zd: %U",
3048            encoding_str,
3049            uself->start,
3050            uself->end-1,
3051            reason_str
3052            );
3053    }
3054done:
3055    Py_XDECREF(reason_str);
3056    Py_XDECREF(encoding_str);
3057    return result;
3058}
3059
3060static PyTypeObject _PyExc_UnicodeDecodeError = {
3061    PyVarObject_HEAD_INIT(NULL, 0)
3062    "UnicodeDecodeError",
3063    sizeof(PyUnicodeErrorObject), 0,
3064    (destructor)UnicodeError_dealloc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
3065    (reprfunc)UnicodeDecodeError_str, 0, 0, 0,
3066    Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC,
3067    PyDoc_STR("Unicode decoding error."), (traverseproc)UnicodeError_traverse,
3068    (inquiry)UnicodeError_clear, 0, 0, 0, 0, 0, UnicodeError_members,
3069    0, &_PyExc_UnicodeError, 0, 0, 0, offsetof(PyUnicodeErrorObject, dict),
3070    (initproc)UnicodeDecodeError_init, 0, BaseException_new,
3071};
3072PyObject *PyExc_UnicodeDecodeError = (PyObject *)&_PyExc_UnicodeDecodeError;
3073
3074PyObject *
3075PyUnicodeDecodeError_Create(
3076    const char *encoding, const char *object, Py_ssize_t length,
3077    Py_ssize_t start, Py_ssize_t end, const char *reason)
3078{
3079    return PyObject_CallFunction(PyExc_UnicodeDecodeError, "sy#nns",
3080                                 encoding, object, length, start, end, reason);
3081}
3082
3083
3084/*
3085 *    UnicodeTranslateError extends UnicodeError
3086 */
3087
3088static int
3089UnicodeTranslateError_init(PyUnicodeErrorObject *self, PyObject *args,
3090                           PyObject *kwds)
3091{
3092    if (BaseException_init((PyBaseExceptionObject *)self, args, kwds) == -1)
3093        return -1;
3094
3095    Py_CLEAR(self->object);
3096    Py_CLEAR(self->reason);
3097
3098    if (!PyArg_ParseTuple(args, "UnnU",
3099                          &self->object,
3100                          &self->start, &self->end, &self->reason)) {
3101        self->object = self->reason = NULL;
3102        return -1;
3103    }
3104
3105    Py_INCREF(self->object);
3106    Py_INCREF(self->reason);
3107
3108    return 0;
3109}
3110
3111
3112static PyObject *
3113UnicodeTranslateError_str(PyObject *self)
3114{
3115    PyUnicodeErrorObject *uself = (PyUnicodeErrorObject *)self;
3116    PyObject *result = NULL;
3117    PyObject *reason_str = NULL;
3118
3119    if (!uself->object)
3120        /* Not properly initialized. */
3121        return PyUnicode_FromString("");
3122
3123    /* Get reason as a string, which it might not be if it's been
3124       modified after we were constructed. */
3125    reason_str = PyObject_Str(uself->reason);
3126    if (reason_str == NULL)
3127        goto done;
3128
3129    if (uself->start < PyUnicode_GET_LENGTH(uself->object) && uself->end == uself->start+1) {
3130        Py_UCS4 badchar = PyUnicode_ReadChar(uself->object, uself->start);
3131        const char *fmt;
3132        if (badchar <= 0xff)
3133            fmt = "can't translate character '\\x%02x' in position %zd: %U";
3134        else if (badchar <= 0xffff)
3135            fmt = "can't translate character '\\u%04x' in position %zd: %U";
3136        else
3137            fmt = "can't translate character '\\U%08x' in position %zd: %U";
3138        result = PyUnicode_FromFormat(
3139            fmt,
3140            (int)badchar,
3141            uself->start,
3142            reason_str
3143        );
3144    } else {
3145        result = PyUnicode_FromFormat(
3146            "can't translate characters in position %zd-%zd: %U",
3147            uself->start,
3148            uself->end-1,
3149            reason_str
3150            );
3151    }
3152done:
3153    Py_XDECREF(reason_str);
3154    return result;
3155}
3156
3157static PyTypeObject _PyExc_UnicodeTranslateError = {
3158    PyVarObject_HEAD_INIT(NULL, 0)
3159    "UnicodeTranslateError",
3160    sizeof(PyUnicodeErrorObject), 0,
3161    (destructor)UnicodeError_dealloc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
3162    (reprfunc)UnicodeTranslateError_str, 0, 0, 0,
3163    Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC,
3164    PyDoc_STR("Unicode translation error."), (traverseproc)UnicodeError_traverse,
3165    (inquiry)UnicodeError_clear, 0, 0, 0, 0, 0, UnicodeError_members,
3166    0, &_PyExc_UnicodeError, 0, 0, 0, offsetof(PyUnicodeErrorObject, dict),
3167    (initproc)UnicodeTranslateError_init, 0, BaseException_new,
3168};
3169PyObject *PyExc_UnicodeTranslateError = (PyObject *)&_PyExc_UnicodeTranslateError;
3170
3171PyObject *
3172_PyUnicodeTranslateError_Create(
3173    PyObject *object,
3174    Py_ssize_t start, Py_ssize_t end, const char *reason)
3175{
3176    return PyObject_CallFunction(PyExc_UnicodeTranslateError, "Onns",
3177                                 object, start, end, reason);
3178}
3179
3180/*
3181 *    AssertionError extends Exception
3182 */
3183SimpleExtendsException(PyExc_Exception, AssertionError,
3184                       "Assertion failed.");
3185
3186
3187/*
3188 *    ArithmeticError extends Exception
3189 */
3190SimpleExtendsException(PyExc_Exception, ArithmeticError,
3191                       "Base class for arithmetic errors.");
3192
3193
3194/*
3195 *    FloatingPointError extends ArithmeticError
3196 */
3197SimpleExtendsException(PyExc_ArithmeticError, FloatingPointError,
3198                       "Floating point operation failed.");
3199
3200
3201/*
3202 *    OverflowError extends ArithmeticError
3203 */
3204SimpleExtendsException(PyExc_ArithmeticError, OverflowError,
3205                       "Result too large to be represented.");
3206
3207
3208/*
3209 *    ZeroDivisionError extends ArithmeticError
3210 */
3211SimpleExtendsException(PyExc_ArithmeticError, ZeroDivisionError,
3212          "Second argument to a division or modulo operation was zero.");
3213
3214
3215/*
3216 *    SystemError extends Exception
3217 */
3218SimpleExtendsException(PyExc_Exception, SystemError,
3219    "Internal error in the Python interpreter.\n"
3220    "\n"
3221    "Please report this to the Python maintainer, along with the traceback,\n"
3222    "the Python version, and the hardware/OS platform and version.");
3223
3224
3225/*
3226 *    ReferenceError extends Exception
3227 */
3228SimpleExtendsException(PyExc_Exception, ReferenceError,
3229                       "Weak ref proxy used after referent went away.");
3230
3231
3232/*
3233 *    MemoryError extends Exception
3234 */
3235
3236#define MEMERRORS_SAVE 16
3237
3238static PyObject *
3239MemoryError_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
3240{
3241    PyBaseExceptionObject *self;
3242
3243    /* If this is a subclass of MemoryError, don't use the freelist
3244     * and just return a fresh object */
3245    if (type != (PyTypeObject *) PyExc_MemoryError) {
3246        return BaseException_new(type, args, kwds);
3247    }
3248
3249    struct _Py_exc_state *state = get_exc_state();
3250    if (state->memerrors_freelist == NULL) {
3251        return BaseException_new(type, args, kwds);
3252    }
3253
3254    /* Fetch object from freelist and revive it */
3255    self = state->memerrors_freelist;
3256    self->args = PyTuple_New(0);
3257    /* This shouldn't happen since the empty tuple is persistent */
3258
3259    if (self->args == NULL) {
3260        return NULL;
3261    }
3262
3263    state->memerrors_freelist = (PyBaseExceptionObject *) self->dict;
3264    state->memerrors_numfree--;
3265    self->dict = NULL;
3266    _Py_NewReference((PyObject *)self);
3267    _PyObject_GC_TRACK(self);
3268    return (PyObject *)self;
3269}
3270
3271static void
3272MemoryError_dealloc(PyBaseExceptionObject *self)
3273{
3274    _PyObject_GC_UNTRACK(self);
3275
3276    BaseException_clear(self);
3277
3278    /* If this is a subclass of MemoryError, we don't need to
3279     * do anything in the free-list*/
3280    if (!Py_IS_TYPE(self, (PyTypeObject *) PyExc_MemoryError)) {
3281        Py_TYPE(self)->tp_free((PyObject *)self);
3282        return;
3283    }
3284
3285    struct _Py_exc_state *state = get_exc_state();
3286    if (state->memerrors_numfree >= MEMERRORS_SAVE) {
3287        Py_TYPE(self)->tp_free((PyObject *)self);
3288    }
3289    else {
3290        self->dict = (PyObject *) state->memerrors_freelist;
3291        state->memerrors_freelist = self;
3292        state->memerrors_numfree++;
3293    }
3294}
3295
3296static int
3297preallocate_memerrors(void)
3298{
3299    /* We create enough MemoryErrors and then decref them, which will fill
3300       up the freelist. */
3301    int i;
3302    PyObject *errors[MEMERRORS_SAVE];
3303    for (i = 0; i < MEMERRORS_SAVE; i++) {
3304        errors[i] = MemoryError_new((PyTypeObject *) PyExc_MemoryError,
3305                                    NULL, NULL);
3306        if (!errors[i]) {
3307            return -1;
3308        }
3309    }
3310    for (i = 0; i < MEMERRORS_SAVE; i++) {
3311        Py_DECREF(errors[i]);
3312    }
3313    return 0;
3314}
3315
3316static void
3317free_preallocated_memerrors(struct _Py_exc_state *state)
3318{
3319    while (state->memerrors_freelist != NULL) {
3320        PyObject *self = (PyObject *) state->memerrors_freelist;
3321        state->memerrors_freelist = (PyBaseExceptionObject *)state->memerrors_freelist->dict;
3322        Py_TYPE(self)->tp_free((PyObject *)self);
3323    }
3324}
3325
3326
3327static PyTypeObject _PyExc_MemoryError = {
3328    PyVarObject_HEAD_INIT(NULL, 0)
3329    "MemoryError",
3330    sizeof(PyBaseExceptionObject),
3331    0, (destructor)MemoryError_dealloc, 0, 0, 0, 0, 0, 0, 0,
3332    0, 0, 0, 0, 0, 0, 0,
3333    Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC,
3334    PyDoc_STR("Out of memory."), (traverseproc)BaseException_traverse,
3335    (inquiry)BaseException_clear, 0, 0, 0, 0, 0, 0, 0, &_PyExc_Exception,
3336    0, 0, 0, offsetof(PyBaseExceptionObject, dict),
3337    (initproc)BaseException_init, 0, MemoryError_new
3338};
3339PyObject *PyExc_MemoryError = (PyObject *) &_PyExc_MemoryError;
3340
3341
3342/*
3343 *    BufferError extends Exception
3344 */
3345SimpleExtendsException(PyExc_Exception, BufferError, "Buffer error.");
3346
3347
3348/* Warning category docstrings */
3349
3350/*
3351 *    Warning extends Exception
3352 */
3353SimpleExtendsException(PyExc_Exception, Warning,
3354                       "Base class for warning categories.");
3355
3356
3357/*
3358 *    UserWarning extends Warning
3359 */
3360SimpleExtendsException(PyExc_Warning, UserWarning,
3361                       "Base class for warnings generated by user code.");
3362
3363
3364/*
3365 *    DeprecationWarning extends Warning
3366 */
3367SimpleExtendsException(PyExc_Warning, DeprecationWarning,
3368                       "Base class for warnings about deprecated features.");
3369
3370
3371/*
3372 *    PendingDeprecationWarning extends Warning
3373 */
3374SimpleExtendsException(PyExc_Warning, PendingDeprecationWarning,
3375    "Base class for warnings about features which will be deprecated\n"
3376    "in the future.");
3377
3378
3379/*
3380 *    SyntaxWarning extends Warning
3381 */
3382SimpleExtendsException(PyExc_Warning, SyntaxWarning,
3383                       "Base class for warnings about dubious syntax.");
3384
3385
3386/*
3387 *    RuntimeWarning extends Warning
3388 */
3389SimpleExtendsException(PyExc_Warning, RuntimeWarning,
3390                 "Base class for warnings about dubious runtime behavior.");
3391
3392
3393/*
3394 *    FutureWarning extends Warning
3395 */
3396SimpleExtendsException(PyExc_Warning, FutureWarning,
3397    "Base class for warnings about constructs that will change semantically\n"
3398    "in the future.");
3399
3400
3401/*
3402 *    ImportWarning extends Warning
3403 */
3404SimpleExtendsException(PyExc_Warning, ImportWarning,
3405          "Base class for warnings about probable mistakes in module imports");
3406
3407
3408/*
3409 *    UnicodeWarning extends Warning
3410 */
3411SimpleExtendsException(PyExc_Warning, UnicodeWarning,
3412    "Base class for warnings about Unicode related problems, mostly\n"
3413    "related to conversion problems.");
3414
3415
3416/*
3417 *    BytesWarning extends Warning
3418 */
3419SimpleExtendsException(PyExc_Warning, BytesWarning,
3420    "Base class for warnings about bytes and buffer related problems, mostly\n"
3421    "related to conversion from str or comparing to str.");
3422
3423
3424/*
3425 *    EncodingWarning extends Warning
3426 */
3427SimpleExtendsException(PyExc_Warning, EncodingWarning,
3428    "Base class for warnings about encodings.");
3429
3430
3431/*
3432 *    ResourceWarning extends Warning
3433 */
3434SimpleExtendsException(PyExc_Warning, ResourceWarning,
3435    "Base class for warnings about resource usage.");
3436
3437
3438
3439#ifdef MS_WINDOWS
3440#include <winsock2.h>
3441/* The following constants were added to errno.h in VS2010 but have
3442   preferred WSA equivalents. */
3443#undef EADDRINUSE
3444#undef EADDRNOTAVAIL
3445#undef EAFNOSUPPORT
3446#undef EALREADY
3447#undef ECONNABORTED
3448#undef ECONNREFUSED
3449#undef ECONNRESET
3450#undef EDESTADDRREQ
3451#undef EHOSTUNREACH
3452#undef EINPROGRESS
3453#undef EISCONN
3454#undef ELOOP
3455#undef EMSGSIZE
3456#undef ENETDOWN
3457#undef ENETRESET
3458#undef ENETUNREACH
3459#undef ENOBUFS
3460#undef ENOPROTOOPT
3461#undef ENOTCONN
3462#undef ENOTSOCK
3463#undef EOPNOTSUPP
3464#undef EPROTONOSUPPORT
3465#undef EPROTOTYPE
3466#undef ETIMEDOUT
3467#undef EWOULDBLOCK
3468
3469#if defined(WSAEALREADY) && !defined(EALREADY)
3470#define EALREADY WSAEALREADY
3471#endif
3472#if defined(WSAECONNABORTED) && !defined(ECONNABORTED)
3473#define ECONNABORTED WSAECONNABORTED
3474#endif
3475#if defined(WSAECONNREFUSED) && !defined(ECONNREFUSED)
3476#define ECONNREFUSED WSAECONNREFUSED
3477#endif
3478#if defined(WSAECONNRESET) && !defined(ECONNRESET)
3479#define ECONNRESET WSAECONNRESET
3480#endif
3481#if defined(WSAEINPROGRESS) && !defined(EINPROGRESS)
3482#define EINPROGRESS WSAEINPROGRESS
3483#endif
3484#if defined(WSAESHUTDOWN) && !defined(ESHUTDOWN)
3485#define ESHUTDOWN WSAESHUTDOWN
3486#endif
3487#if defined(WSAETIMEDOUT) && !defined(ETIMEDOUT)
3488#define ETIMEDOUT WSAETIMEDOUT
3489#endif
3490#if defined(WSAEWOULDBLOCK) && !defined(EWOULDBLOCK)
3491#define EWOULDBLOCK WSAEWOULDBLOCK
3492#endif
3493#endif /* MS_WINDOWS */
3494
3495struct static_exception {
3496    PyTypeObject *exc;
3497    const char *name;
3498};
3499
3500static struct static_exception static_exceptions[] = {
3501#define ITEM(NAME) {&_PyExc_##NAME, #NAME}
3502    // Level 1
3503    ITEM(BaseException),
3504
3505    // Level 2: BaseException subclasses
3506    ITEM(BaseExceptionGroup),
3507    ITEM(Exception),
3508    ITEM(GeneratorExit),
3509    ITEM(KeyboardInterrupt),
3510    ITEM(SystemExit),
3511
3512    // Level 3: Exception(BaseException) subclasses
3513    ITEM(ArithmeticError),
3514    ITEM(AssertionError),
3515    ITEM(AttributeError),
3516    ITEM(BufferError),
3517    ITEM(EOFError),
3518    //ITEM(ExceptionGroup),
3519    ITEM(ImportError),
3520    ITEM(LookupError),
3521    ITEM(MemoryError),
3522    ITEM(NameError),
3523    ITEM(OSError),
3524    ITEM(ReferenceError),
3525    ITEM(RuntimeError),
3526    ITEM(StopAsyncIteration),
3527    ITEM(StopIteration),
3528    ITEM(SyntaxError),
3529    ITEM(SystemError),
3530    ITEM(TypeError),
3531    ITEM(ValueError),
3532    ITEM(Warning),
3533
3534    // Level 4: ArithmeticError(Exception) subclasses
3535    ITEM(FloatingPointError),
3536    ITEM(OverflowError),
3537    ITEM(ZeroDivisionError),
3538
3539    // Level 4: Warning(Exception) subclasses
3540    ITEM(BytesWarning),
3541    ITEM(DeprecationWarning),
3542    ITEM(EncodingWarning),
3543    ITEM(FutureWarning),
3544    ITEM(ImportWarning),
3545    ITEM(PendingDeprecationWarning),
3546    ITEM(ResourceWarning),
3547    ITEM(RuntimeWarning),
3548    ITEM(SyntaxWarning),
3549    ITEM(UnicodeWarning),
3550    ITEM(UserWarning),
3551
3552    // Level 4: OSError(Exception) subclasses
3553    ITEM(BlockingIOError),
3554    ITEM(ChildProcessError),
3555    ITEM(ConnectionError),
3556    ITEM(FileExistsError),
3557    ITEM(FileNotFoundError),
3558    ITEM(InterruptedError),
3559    ITEM(IsADirectoryError),
3560    ITEM(NotADirectoryError),
3561    ITEM(PermissionError),
3562    ITEM(ProcessLookupError),
3563    ITEM(TimeoutError),
3564
3565    // Level 4: Other subclasses
3566    ITEM(IndentationError), // base: SyntaxError(Exception)
3567    ITEM(IndexError),  // base: LookupError(Exception)
3568    ITEM(KeyError),  // base: LookupError(Exception)
3569    ITEM(ModuleNotFoundError), // base: ImportError(Exception)
3570    ITEM(NotImplementedError),  // base: RuntimeError(Exception)
3571    ITEM(RecursionError),  // base: RuntimeError(Exception)
3572    ITEM(UnboundLocalError), // base: NameError(Exception)
3573    ITEM(UnicodeError),  // base: ValueError(Exception)
3574
3575    // Level 5: ConnectionError(OSError) subclasses
3576    ITEM(BrokenPipeError),
3577    ITEM(ConnectionAbortedError),
3578    ITEM(ConnectionRefusedError),
3579    ITEM(ConnectionResetError),
3580
3581    // Level 5: IndentationError(SyntaxError) subclasses
3582    ITEM(TabError),  // base: IndentationError
3583
3584    // Level 5: UnicodeError(ValueError) subclasses
3585    ITEM(UnicodeDecodeError),
3586    ITEM(UnicodeEncodeError),
3587    ITEM(UnicodeTranslateError),
3588#undef ITEM
3589};
3590
3591
3592int
3593_PyExc_InitTypes(PyInterpreterState *interp)
3594{
3595    if (!_Py_IsMainInterpreter(interp)) {
3596        return 0;
3597    }
3598
3599    for (size_t i=0; i < Py_ARRAY_LENGTH(static_exceptions); i++) {
3600        PyTypeObject *exc = static_exceptions[i].exc;
3601
3602        if (PyType_Ready(exc) < 0) {
3603            return -1;
3604        }
3605    }
3606    return 0;
3607}
3608
3609
3610static void
3611_PyExc_FiniTypes(PyInterpreterState *interp)
3612{
3613    if (!_Py_IsMainInterpreter(interp)) {
3614        return;
3615    }
3616
3617    for (Py_ssize_t i=Py_ARRAY_LENGTH(static_exceptions) - 1; i >= 0; i--) {
3618        PyTypeObject *exc = static_exceptions[i].exc;
3619        _PyStaticType_Dealloc(exc);
3620    }
3621}
3622
3623
3624PyStatus
3625_PyExc_InitGlobalObjects(PyInterpreterState *interp)
3626{
3627    if (!_Py_IsMainInterpreter(interp)) {
3628        return _PyStatus_OK();
3629    }
3630
3631    if (preallocate_memerrors() < 0) {
3632        return _PyStatus_NO_MEMORY();
3633    }
3634    return _PyStatus_OK();
3635}
3636
3637PyStatus
3638_PyExc_InitState(PyInterpreterState *interp)
3639{
3640    struct _Py_exc_state *state = &interp->exc_state;
3641
3642#define ADD_ERRNO(TYPE, CODE) \
3643    do { \
3644        PyObject *_code = PyLong_FromLong(CODE); \
3645        assert(_PyObject_RealIsSubclass(PyExc_ ## TYPE, PyExc_OSError)); \
3646        if (!_code || PyDict_SetItem(state->errnomap, _code, PyExc_ ## TYPE)) { \
3647            Py_XDECREF(_code); \
3648            return _PyStatus_ERR("errmap insertion problem."); \
3649        } \
3650        Py_DECREF(_code); \
3651    } while (0)
3652
3653    /* Add exceptions to errnomap */
3654    assert(state->errnomap == NULL);
3655    state->errnomap = PyDict_New();
3656    if (!state->errnomap) {
3657        return _PyStatus_NO_MEMORY();
3658    }
3659
3660    ADD_ERRNO(BlockingIOError, EAGAIN);
3661    ADD_ERRNO(BlockingIOError, EALREADY);
3662    ADD_ERRNO(BlockingIOError, EINPROGRESS);
3663    ADD_ERRNO(BlockingIOError, EWOULDBLOCK);
3664    ADD_ERRNO(BrokenPipeError, EPIPE);
3665#ifdef ESHUTDOWN
3666    ADD_ERRNO(BrokenPipeError, ESHUTDOWN);
3667#endif
3668    ADD_ERRNO(ChildProcessError, ECHILD);
3669    ADD_ERRNO(ConnectionAbortedError, ECONNABORTED);
3670    ADD_ERRNO(ConnectionRefusedError, ECONNREFUSED);
3671    ADD_ERRNO(ConnectionResetError, ECONNRESET);
3672    ADD_ERRNO(FileExistsError, EEXIST);
3673    ADD_ERRNO(FileNotFoundError, ENOENT);
3674    ADD_ERRNO(IsADirectoryError, EISDIR);
3675    ADD_ERRNO(NotADirectoryError, ENOTDIR);
3676    ADD_ERRNO(InterruptedError, EINTR);
3677    ADD_ERRNO(PermissionError, EACCES);
3678    ADD_ERRNO(PermissionError, EPERM);
3679#ifdef ENOTCAPABLE
3680    // Extension for WASI capability-based security. Process lacks
3681    // capability to access a resource.
3682    ADD_ERRNO(PermissionError, ENOTCAPABLE);
3683#endif
3684    ADD_ERRNO(ProcessLookupError, ESRCH);
3685    ADD_ERRNO(TimeoutError, ETIMEDOUT);
3686
3687    return _PyStatus_OK();
3688
3689#undef ADD_ERRNO
3690}
3691
3692
3693/* Add exception types to the builtins module */
3694int
3695_PyBuiltins_AddExceptions(PyObject *bltinmod)
3696{
3697    PyObject *mod_dict = PyModule_GetDict(bltinmod);
3698    if (mod_dict == NULL) {
3699        return -1;
3700    }
3701
3702    for (size_t i=0; i < Py_ARRAY_LENGTH(static_exceptions); i++) {
3703        struct static_exception item = static_exceptions[i];
3704
3705        if (PyDict_SetItemString(mod_dict, item.name, (PyObject*)item.exc)) {
3706            return -1;
3707        }
3708    }
3709
3710    PyObject *PyExc_ExceptionGroup = create_exception_group_class();
3711    if (!PyExc_ExceptionGroup) {
3712        return -1;
3713    }
3714    if (PyDict_SetItemString(mod_dict, "ExceptionGroup", PyExc_ExceptionGroup)) {
3715        return -1;
3716    }
3717
3718#define INIT_ALIAS(NAME, TYPE) \
3719    do { \
3720        PyExc_ ## NAME = PyExc_ ## TYPE; \
3721        if (PyDict_SetItemString(mod_dict, # NAME, PyExc_ ## TYPE)) { \
3722            return -1; \
3723        } \
3724    } while (0)
3725
3726    INIT_ALIAS(EnvironmentError, OSError);
3727    INIT_ALIAS(IOError, OSError);
3728#ifdef MS_WINDOWS
3729    INIT_ALIAS(WindowsError, OSError);
3730#endif
3731
3732#undef INIT_ALIAS
3733
3734    return 0;
3735}
3736
3737void
3738_PyExc_ClearExceptionGroupType(PyInterpreterState *interp)
3739{
3740    struct _Py_exc_state *state = &interp->exc_state;
3741    Py_CLEAR(state->PyExc_ExceptionGroup);
3742}
3743
3744void
3745_PyExc_Fini(PyInterpreterState *interp)
3746{
3747    struct _Py_exc_state *state = &interp->exc_state;
3748    free_preallocated_memerrors(state);
3749    Py_CLEAR(state->errnomap);
3750
3751    _PyExc_FiniTypes(interp);
3752}
3753
3754/* Helper to do the equivalent of "raise X from Y" in C, but always using
3755 * the current exception rather than passing one in.
3756 *
3757 * We currently limit this to *only* exceptions that use the BaseException
3758 * tp_init and tp_new methods, since we can be reasonably sure we can wrap
3759 * those correctly without losing data and without losing backwards
3760 * compatibility.
3761 *
3762 * We also aim to rule out *all* exceptions that might be storing additional
3763 * state, whether by having a size difference relative to BaseException,
3764 * additional arguments passed in during construction or by having a
3765 * non-empty instance dict.
3766 *
3767 * We need to be very careful with what we wrap, since changing types to
3768 * a broader exception type would be backwards incompatible for
3769 * existing codecs, and with different init or new method implementations
3770 * may either not support instantiation with PyErr_Format or lose
3771 * information when instantiated that way.
3772 *
3773 * XXX (ncoghlan): This could be made more comprehensive by exploiting the
3774 * fact that exceptions are expected to support pickling. If more builtin
3775 * exceptions (e.g. AttributeError) start to be converted to rich
3776 * exceptions with additional attributes, that's probably a better approach
3777 * to pursue over adding special cases for particular stateful subclasses.
3778 *
3779 * Returns a borrowed reference to the new exception (if any), NULL if the
3780 * existing exception was left in place.
3781 */
3782PyObject *
3783_PyErr_TrySetFromCause(const char *format, ...)
3784{
3785    PyObject* msg_prefix;
3786    PyObject *exc, *val, *tb;
3787    PyTypeObject *caught_type;
3788    PyObject *instance_args;
3789    Py_ssize_t num_args, caught_type_size, base_exc_size;
3790    PyObject *new_exc, *new_val, *new_tb;
3791    va_list vargs;
3792    int same_basic_size;
3793
3794    PyErr_Fetch(&exc, &val, &tb);
3795    caught_type = (PyTypeObject *)exc;
3796    /* Ensure type info indicates no extra state is stored at the C level
3797     * and that the type can be reinstantiated using PyErr_Format
3798     */
3799    caught_type_size = caught_type->tp_basicsize;
3800    base_exc_size = _PyExc_BaseException.tp_basicsize;
3801    same_basic_size = (
3802        caught_type_size == base_exc_size ||
3803        (_PyType_SUPPORTS_WEAKREFS(caught_type) &&
3804            (caught_type_size == base_exc_size + (Py_ssize_t)sizeof(PyObject *))
3805        )
3806    );
3807    if (caught_type->tp_init != (initproc)BaseException_init ||
3808        caught_type->tp_new != BaseException_new ||
3809        !same_basic_size ||
3810        caught_type->tp_itemsize != _PyExc_BaseException.tp_itemsize) {
3811        /* We can't be sure we can wrap this safely, since it may contain
3812         * more state than just the exception type. Accordingly, we just
3813         * leave it alone.
3814         */
3815        PyErr_Restore(exc, val, tb);
3816        return NULL;
3817    }
3818
3819    /* Check the args are empty or contain a single string */
3820    PyErr_NormalizeException(&exc, &val, &tb);
3821    instance_args = ((PyBaseExceptionObject *)val)->args;
3822    num_args = PyTuple_GET_SIZE(instance_args);
3823    if (num_args > 1 ||
3824        (num_args == 1 &&
3825         !PyUnicode_CheckExact(PyTuple_GET_ITEM(instance_args, 0)))) {
3826        /* More than 1 arg, or the one arg we do have isn't a string
3827         */
3828        PyErr_Restore(exc, val, tb);
3829        return NULL;
3830    }
3831
3832    /* Ensure the instance dict is also empty */
3833    if (!_PyObject_IsInstanceDictEmpty(val)) {
3834        /* While we could potentially copy a non-empty instance dictionary
3835         * to the replacement exception, for now we take the more
3836         * conservative path of leaving exceptions with attributes set
3837         * alone.
3838         */
3839        PyErr_Restore(exc, val, tb);
3840        return NULL;
3841    }
3842
3843    /* For exceptions that we can wrap safely, we chain the original
3844     * exception to a new one of the exact same type with an
3845     * error message that mentions the additional details and the
3846     * original exception.
3847     *
3848     * It would be nice to wrap OSError and various other exception
3849     * types as well, but that's quite a bit trickier due to the extra
3850     * state potentially stored on OSError instances.
3851     */
3852    /* Ensure the traceback is set correctly on the existing exception */
3853    if (tb != NULL) {
3854        PyException_SetTraceback(val, tb);
3855        Py_DECREF(tb);
3856    }
3857
3858#ifdef HAVE_STDARG_PROTOTYPES
3859    va_start(vargs, format);
3860#else
3861    va_start(vargs);
3862#endif
3863    msg_prefix = PyUnicode_FromFormatV(format, vargs);
3864    va_end(vargs);
3865    if (msg_prefix == NULL) {
3866        Py_DECREF(exc);
3867        Py_DECREF(val);
3868        return NULL;
3869    }
3870
3871    PyErr_Format(exc, "%U (%s: %S)",
3872                 msg_prefix, Py_TYPE(val)->tp_name, val);
3873    Py_DECREF(exc);
3874    Py_DECREF(msg_prefix);
3875    PyErr_Fetch(&new_exc, &new_val, &new_tb);
3876    PyErr_NormalizeException(&new_exc, &new_val, &new_tb);
3877    PyException_SetCause(new_val, val);
3878    PyErr_Restore(new_exc, new_val, new_tb);
3879    return new_val;
3880}
3881