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