1 #define PY_SSIZE_T_CLEAN
2 #include "parts.h"
3 #include "util.h"
4 #include "clinic/exceptions.c.h"
5
6
7 /*[clinic input]
8 module _testcapi
9 [clinic start generated code]*/
10 /*[clinic end generated code: output=da39a3ee5e6b4b0d input=6361033e795369fc]*/
11
12 /*[clinic input]
13 _testcapi.err_set_raised
14 exception as exc: object
15 /
16 [clinic start generated code]*/
17
18 static PyObject *
19 _testcapi_err_set_raised(PyObject *module, PyObject *exc)
20 /*[clinic end generated code: output=0a0c7743961fcae5 input=c5f7331864a94df9]*/
21 {
22 Py_INCREF(exc);
23 PyErr_SetRaisedException(exc);
24 assert(PyErr_Occurred());
25 return NULL;
26 }
27
28 static PyObject *
29 err_restore(PyObject *self, PyObject *args) {
30 PyObject *type = NULL, *value = NULL, *traceback = NULL;
31 switch(PyTuple_Size(args)) {
32 case 3:
33 traceback = PyTuple_GetItem(args, 2);
34 Py_INCREF(traceback);
35 /* fall through */
36 case 2:
37 value = PyTuple_GetItem(args, 1);
38 Py_INCREF(value);
39 /* fall through */
40 case 1:
41 type = PyTuple_GetItem(args, 0);
42 Py_INCREF(type);
43 break;
44 default:
45 PyErr_SetString(PyExc_TypeError,
46 "wrong number of arguments");
47 return NULL;
48 }
49 PyErr_Restore(type, value, traceback);
50 assert(PyErr_Occurred());
51 return NULL;
52 }
53
54 /*[clinic input]
55 _testcapi.exception_print
56 exception as exc: object
57 legacy: bool = False
58 /
59
60 To test the format of exceptions as printed out.
61 [clinic start generated code]*/
62
63 static PyObject *
64 _testcapi_exception_print_impl(PyObject *module, PyObject *exc, int legacy)
65 /*[clinic end generated code: output=3f04fe0c18412ae0 input=c76f42cb94136dbf]*/
66 {
67 if (legacy) {
68 PyObject *tb = NULL;
69 if (PyExceptionInstance_Check(exc)) {
70 tb = PyException_GetTraceback(exc);
71 }
72 PyErr_Display((PyObject *) Py_TYPE(exc), exc, tb);
73 Py_XDECREF(tb);
74 }
75 else {
76 PyErr_DisplayException(exc);
77 }
78 Py_RETURN_NONE;
79 }
80
81 /*[clinic input]
82 _testcapi.make_exception_with_doc
83 name: str
84 doc: str = NULL
85 base: object = NULL
86 dict: object = NULL
87
88 Test PyErr_NewExceptionWithDoc (also exercise PyErr_NewException). Run via Lib/test/test_exceptions.py
89 [clinic start generated code]*/
90
91 static PyObject *
92 _testcapi_make_exception_with_doc_impl(PyObject *module, const char *name,
93 const char *doc, PyObject *base,
94 PyObject *dict)
95 /*[clinic end generated code: output=439f0d963c1ce2c4 input=23a73013f8a8795a]*/
96 {
97 return PyErr_NewExceptionWithDoc(name, doc, base, dict);
98 }
99
100 /*[clinic input]
101 _testcapi.exc_set_object
102 exception as exc: object
103 obj: object
104 /
105 [clinic start generated code]*/
106
107 static PyObject *
108 _testcapi_exc_set_object_impl(PyObject *module, PyObject *exc, PyObject *obj)
109 /*[clinic end generated code: output=34c8c7c83e5c8463 input=fc530aafb1b0a360]*/
110 {
111 PyErr_SetObject(exc, obj);
112 return NULL;
113 }
114
115 /*[clinic input]
116 _testcapi.exc_set_object_fetch = _testcapi.exc_set_object
117 [clinic start generated code]*/
118
119 static PyObject *
120 _testcapi_exc_set_object_fetch_impl(PyObject *module, PyObject *exc,
121 PyObject *obj)
122 /*[clinic end generated code: output=7a5ff5f6d3cf687f input=77ec686f1f95fa38]*/
123 {
124 PyObject *type = UNINITIALIZED_PTR;
125 PyObject *value = UNINITIALIZED_PTR;
126 PyObject *tb = UNINITIALIZED_PTR;
127
128 PyErr_SetObject(exc, obj);
129 PyErr_Fetch(&type, &value, &tb);
130 assert(type != UNINITIALIZED_PTR);
131 assert(value != UNINITIALIZED_PTR);
132 assert(tb != UNINITIALIZED_PTR);
133 Py_XDECREF(type);
134 Py_XDECREF(tb);
135 return value;
136 }
137
138 /*[clinic input]
139 _testcapi.err_setstring
140 exc: object
141 value: str(zeroes=True, accept={robuffer, str, NoneType})
142 /
143 [clinic start generated code]*/
144
145 static PyObject *
146 _testcapi_err_setstring_impl(PyObject *module, PyObject *exc,
147 const char *value, Py_ssize_t value_length)
148 /*[clinic end generated code: output=fba8705e5703dd3f input=e8a95fad66d9004b]*/
149 {
150 NULLABLE(exc);
151 PyErr_SetString(exc, value);
152 return NULL;
153 }
154
155 /*[clinic input]
156 _testcapi.err_setfromerrnowithfilename
157 error: int
158 exc: object
159 value: str(zeroes=True, accept={robuffer, str, NoneType})
160 /
161 [clinic start generated code]*/
162
163 static PyObject *
164 _testcapi_err_setfromerrnowithfilename_impl(PyObject *module, int error,
165 PyObject *exc, const char *value,
166 Py_ssize_t value_length)
167 /*[clinic end generated code: output=d02df5749a01850e input=ff7c384234bf097f]*/
168 {
169 NULLABLE(exc);
170 errno = error;
171 PyErr_SetFromErrnoWithFilename(exc, value);
172 return NULL;
173 }
174
175 /*[clinic input]
176 _testcapi.raise_exception
177 exception as exc: object
178 num_args: int
179 /
180 [clinic start generated code]*/
181
182 static PyObject *
183 _testcapi_raise_exception_impl(PyObject *module, PyObject *exc, int num_args)
184 /*[clinic end generated code: output=eb0a9c5d69e0542d input=83d6262c3829d088]*/
185 {
186 PyObject *exc_args = PyTuple_New(num_args);
187 if (exc_args == NULL) {
188 return NULL;
189 }
190 for (int i = 0; i < num_args; ++i) {
191 PyObject *v = PyLong_FromLong(i);
192 if (v == NULL) {
193 Py_DECREF(exc_args);
194 return NULL;
195 }
196 PyTuple_SET_ITEM(exc_args, i, v);
197 }
198 PyErr_SetObject(exc, exc_args);
199 Py_DECREF(exc_args);
200 return NULL;
201 }
202
203 /*[clinic input]
204 _testcapi.raise_memoryerror
205 [clinic start generated code]*/
206
207 static PyObject *
208 _testcapi_raise_memoryerror_impl(PyObject *module)
209 /*[clinic end generated code: output=dd057803fb0131e6 input=6ca521bd07fb73cb]*/
210 {
211 return PyErr_NoMemory();
212 }
213
214 /*[clinic input]
215 _testcapi.fatal_error
216 message: str(accept={robuffer})
217 release_gil: bool = False
218 /
219 [clinic start generated code]*/
220
221 static PyObject *
222 _testcapi_fatal_error_impl(PyObject *module, const char *message,
223 int release_gil)
224 /*[clinic end generated code: output=9c3237116e6a03e8 input=1be357a2ccb04c8c]*/
225 {
226 if (release_gil) {
227 Py_BEGIN_ALLOW_THREADS
228 Py_FatalError(message);
229 Py_END_ALLOW_THREADS
230 }
231 else {
232 Py_FatalError(message);
233 }
234 // Py_FatalError() does not return, but exits the process.
235 Py_RETURN_NONE;
236 }
237
238 /*[clinic input]
239 _testcapi.set_exc_info
240 new_type: object
241 new_value: object
242 new_tb: object
243 /
244 [clinic start generated code]*/
245
246 static PyObject *
247 _testcapi_set_exc_info_impl(PyObject *module, PyObject *new_type,
248 PyObject *new_value, PyObject *new_tb)
249 /*[clinic end generated code: output=b55fa35dec31300e input=ea9f19e0f55fe5b3]*/
250 {
251 PyObject *type = UNINITIALIZED_PTR, *value = UNINITIALIZED_PTR, *tb = UNINITIALIZED_PTR;
252 PyErr_GetExcInfo(&type, &value, &tb);
253
254 Py_INCREF(new_type);
255 Py_INCREF(new_value);
256 Py_INCREF(new_tb);
257 PyErr_SetExcInfo(new_type, new_value, new_tb);
258
259 PyObject *orig_exc = PyTuple_Pack(3,
260 type ? type : Py_None,
261 value ? value : Py_None,
262 tb ? tb : Py_None);
263 Py_XDECREF(type);
264 Py_XDECREF(value);
265 Py_XDECREF(tb);
266 return orig_exc;
267 }
268
269 /*[clinic input]
270 _testcapi.set_exception
271 new_exc: object
272 /
273 [clinic start generated code]*/
274
275 static PyObject *
276 _testcapi_set_exception(PyObject *module, PyObject *new_exc)
277 /*[clinic end generated code: output=8b969b35d029e96d input=c89d4ca966c69738]*/
278 {
279 PyObject *exc = PyErr_GetHandledException();
280 assert(PyExceptionInstance_Check(exc) || exc == NULL);
281 PyErr_SetHandledException(new_exc);
282 return exc;
283 }
284
285 /*[clinic input]
286 _testcapi.write_unraisable_exc
287 exception as exc: object
288 err_msg: object
289 obj: object
290 /
291 [clinic start generated code]*/
292
293 static PyObject *
294 _testcapi_write_unraisable_exc_impl(PyObject *module, PyObject *exc,
295 PyObject *err_msg, PyObject *obj)
296 /*[clinic end generated code: output=39827c5e0a8c2092 input=582498da5b2ee6cf]*/
297 {
298
299 const char *err_msg_utf8;
300 if (err_msg != Py_None) {
301 err_msg_utf8 = PyUnicode_AsUTF8(err_msg);
302 if (err_msg_utf8 == NULL) {
303 return NULL;
304 }
305 }
306 else {
307 err_msg_utf8 = NULL;
308 }
309
310 PyErr_SetObject((PyObject *)Py_TYPE(exc), exc);
311 _PyErr_WriteUnraisableMsg(err_msg_utf8, obj);
312 Py_RETURN_NONE;
313 }
314
315 /*[clinic input]
316 _testcapi.traceback_print
317 traceback: object
318 file: object
319 /
320 To test the format of tracebacks as printed out.
321 [clinic start generated code]*/
322
323 static PyObject *
324 _testcapi_traceback_print_impl(PyObject *module, PyObject *traceback,
325 PyObject *file)
326 /*[clinic end generated code: output=17074ecf9d95cf30 input=9423f2857b008ca8]*/
327 {
328 if (PyTraceBack_Print(traceback, file) < 0) {
329 return NULL;
330 }
331 Py_RETURN_NONE;
332 }
333
334 /*[clinic input]
335 _testcapi.unstable_exc_prep_reraise_star
336 orig: object
337 excs: object
338 /
339 To test PyUnstable_Exc_PrepReraiseStar.
340 [clinic start generated code]*/
341
342 static PyObject *
343 _testcapi_unstable_exc_prep_reraise_star_impl(PyObject *module,
344 PyObject *orig, PyObject *excs)
345 /*[clinic end generated code: output=850cf008e0563c77 input=27fbcda2203eb301]*/
346 {
347 return PyUnstable_Exc_PrepReraiseStar(orig, excs);
348 }
349
350
351 /*
352 * Define the PyRecurdingInfinitelyError_Type
353 */
354
355 static PyTypeObject PyRecursingInfinitelyError_Type;
356
357 static int
358 recurse_infinitely_error_init(PyObject *self, PyObject *args, PyObject *kwds)
359 {
360 PyObject *type = (PyObject *)&PyRecursingInfinitelyError_Type;
361
362 /* Instantiating this exception starts infinite recursion. */
363 Py_INCREF(type);
364 PyErr_SetObject(type, NULL);
365 return -1;
366 }
367
368 static PyTypeObject PyRecursingInfinitelyError_Type = {
369 .tp_name = "RecursingInfinitelyError",
370 .tp_basicsize = sizeof(PyBaseExceptionObject),
371 .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
372 .tp_doc = PyDoc_STR("Instantiating this exception starts infinite recursion."),
373 .tp_init = (initproc)recurse_infinitely_error_init,
374 };
375
376 static PyMethodDef test_methods[] = {
377 {"err_restore", err_restore, METH_VARARGS},
378 _TESTCAPI_ERR_SET_RAISED_METHODDEF
379 _TESTCAPI_EXCEPTION_PRINT_METHODDEF
380 _TESTCAPI_FATAL_ERROR_METHODDEF
381 _TESTCAPI_MAKE_EXCEPTION_WITH_DOC_METHODDEF
382 _TESTCAPI_EXC_SET_OBJECT_METHODDEF
383 _TESTCAPI_EXC_SET_OBJECT_FETCH_METHODDEF
384 _TESTCAPI_ERR_SETSTRING_METHODDEF
385 _TESTCAPI_ERR_SETFROMERRNOWITHFILENAME_METHODDEF
386 _TESTCAPI_RAISE_EXCEPTION_METHODDEF
387 _TESTCAPI_RAISE_MEMORYERROR_METHODDEF
388 _TESTCAPI_SET_EXC_INFO_METHODDEF
389 _TESTCAPI_SET_EXCEPTION_METHODDEF
390 _TESTCAPI_TRACEBACK_PRINT_METHODDEF
391 _TESTCAPI_WRITE_UNRAISABLE_EXC_METHODDEF
392 _TESTCAPI_UNSTABLE_EXC_PREP_RERAISE_STAR_METHODDEF
393 {NULL},
394 };
395
396 int
397 _PyTestCapi_Init_Exceptions(PyObject *mod)
398 {
399 PyRecursingInfinitelyError_Type.tp_base = (PyTypeObject *)PyExc_Exception;
400 if (PyType_Ready(&PyRecursingInfinitelyError_Type) < 0) {
401 return -1;
402 }
403 if (PyModule_AddObjectRef(mod, "RecursingInfinitelyError",
404 (PyObject *)&PyRecursingInfinitelyError_Type) < 0)
405 {
406 return -1;
407 }
408
409 if (PyModule_AddFunctions(mod, test_methods) < 0) {
410 return -1;
411 }
412
413 return 0;
414 }