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