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