1
2 /* Traceback implementation */
3
4 #include "Python.h"
5
6 #include "pycore_ast.h" // asdl_seq_GET()
7 #include "pycore_call.h" // _PyObject_CallMethodFormat()
8 #include "pycore_fileutils.h" // _Py_BEGIN_SUPPRESS_IPH
9 #include "pycore_frame.h" // _PyFrame_GetCode()
10 #include "pycore_interp.h" // PyInterpreterState.gc
11 #include "pycore_parser.h" // _PyParser_ASTFromString
12 #include "pycore_pyarena.h" // _PyArena_Free()
13 #include "pycore_pyerrors.h" // _PyErr_GetRaisedException()
14 #include "pycore_pystate.h" // _PyThreadState_GET()
15 #include "pycore_sysmodule.h" // _PySys_GetAttr()
16 #include "pycore_traceback.h" // EXCEPTION_TB_HEADER
17
18 #include "frameobject.h" // PyFrame_New()
19
20 #include "osdefs.h" // SEP
21 #ifdef HAVE_UNISTD_H
22 # include <unistd.h> // lseek()
23 #endif
24
25
26 #define OFF(x) offsetof(PyTracebackObject, x)
27 #define PUTS(fd, str) (void)_Py_write_noraise(fd, str, (int)strlen(str))
28
29 #define MAX_STRING_LENGTH 500
30 #define MAX_FRAME_DEPTH 100
31 #define MAX_NTHREADS 100
32
33 /* Function from Parser/tokenizer/file_tokenizer.c */
34 extern char* _PyTokenizer_FindEncodingFilename(int, PyObject *);
35
36 /*[clinic input]
37 class traceback "PyTracebackObject *" "&PyTraceback_Type"
38 [clinic start generated code]*/
39 /*[clinic end generated code: output=da39a3ee5e6b4b0d input=cf96294b2bebc811]*/
40
41 #include "clinic/traceback.c.h"
42
43 static PyObject *
tb_create_raw(PyTracebackObject * next,PyFrameObject * frame,int lasti,int lineno)44 tb_create_raw(PyTracebackObject *next, PyFrameObject *frame, int lasti,
45 int lineno)
46 {
47 PyTracebackObject *tb;
48 if ((next != NULL && !PyTraceBack_Check(next)) ||
49 frame == NULL || !PyFrame_Check(frame)) {
50 PyErr_BadInternalCall();
51 return NULL;
52 }
53 tb = PyObject_GC_New(PyTracebackObject, &PyTraceBack_Type);
54 if (tb != NULL) {
55 tb->tb_next = (PyTracebackObject*)Py_XNewRef(next);
56 tb->tb_frame = (PyFrameObject*)Py_XNewRef(frame);
57 tb->tb_lasti = lasti;
58 tb->tb_lineno = lineno;
59 PyObject_GC_Track(tb);
60 }
61 return (PyObject *)tb;
62 }
63
64 /*[clinic input]
65 @classmethod
66 traceback.__new__ as tb_new
67
68 tb_next: object
69 tb_frame: object(type='PyFrameObject *', subclass_of='&PyFrame_Type')
70 tb_lasti: int
71 tb_lineno: int
72
73 Create a new traceback object.
74 [clinic start generated code]*/
75
76 static PyObject *
tb_new_impl(PyTypeObject * type,PyObject * tb_next,PyFrameObject * tb_frame,int tb_lasti,int tb_lineno)77 tb_new_impl(PyTypeObject *type, PyObject *tb_next, PyFrameObject *tb_frame,
78 int tb_lasti, int tb_lineno)
79 /*[clinic end generated code: output=fa077debd72d861a input=b88143145454cb59]*/
80 {
81 if (tb_next == Py_None) {
82 tb_next = NULL;
83 } else if (!PyTraceBack_Check(tb_next)) {
84 return PyErr_Format(PyExc_TypeError,
85 "expected traceback object or None, got '%s'",
86 Py_TYPE(tb_next)->tp_name);
87 }
88
89 return tb_create_raw((PyTracebackObject *)tb_next, tb_frame, tb_lasti,
90 tb_lineno);
91 }
92
93 static PyObject *
tb_dir(PyTracebackObject * self,PyObject * Py_UNUSED (ignored))94 tb_dir(PyTracebackObject *self, PyObject *Py_UNUSED(ignored))
95 {
96 return Py_BuildValue("[ssss]", "tb_frame", "tb_next",
97 "tb_lasti", "tb_lineno");
98 }
99
100 static PyObject *
tb_next_get(PyTracebackObject * self,void * Py_UNUSED (_))101 tb_next_get(PyTracebackObject *self, void *Py_UNUSED(_))
102 {
103 PyObject* ret = (PyObject*)self->tb_next;
104 if (!ret) {
105 ret = Py_None;
106 }
107 return Py_NewRef(ret);
108 }
109
110 static int
tb_get_lineno(PyTracebackObject * tb)111 tb_get_lineno(PyTracebackObject* tb) {
112 _PyInterpreterFrame* frame = tb->tb_frame->f_frame;
113 assert(frame != NULL);
114 return PyCode_Addr2Line(_PyFrame_GetCode(frame), tb->tb_lasti);
115 }
116
117 static PyObject *
tb_lineno_get(PyTracebackObject * self,void * Py_UNUSED (_))118 tb_lineno_get(PyTracebackObject *self, void *Py_UNUSED(_))
119 {
120 int lineno = self->tb_lineno;
121 if (lineno == -1) {
122 lineno = tb_get_lineno(self);
123 if (lineno < 0) {
124 Py_RETURN_NONE;
125 }
126 }
127 return PyLong_FromLong(lineno);
128 }
129
130 static int
tb_next_set(PyTracebackObject * self,PyObject * new_next,void * Py_UNUSED (_))131 tb_next_set(PyTracebackObject *self, PyObject *new_next, void *Py_UNUSED(_))
132 {
133 if (!new_next) {
134 PyErr_Format(PyExc_TypeError, "can't delete tb_next attribute");
135 return -1;
136 }
137
138 /* We accept None or a traceback object, and map None -> NULL (inverse of
139 tb_next_get) */
140 if (new_next == Py_None) {
141 new_next = NULL;
142 } else if (!PyTraceBack_Check(new_next)) {
143 PyErr_Format(PyExc_TypeError,
144 "expected traceback object, got '%s'",
145 Py_TYPE(new_next)->tp_name);
146 return -1;
147 }
148
149 /* Check for loops */
150 PyTracebackObject *cursor = (PyTracebackObject *)new_next;
151 while (cursor) {
152 if (cursor == self) {
153 PyErr_Format(PyExc_ValueError, "traceback loop detected");
154 return -1;
155 }
156 cursor = cursor->tb_next;
157 }
158
159 Py_XSETREF(self->tb_next, (PyTracebackObject *)Py_XNewRef(new_next));
160
161 return 0;
162 }
163
164
165 static PyMethodDef tb_methods[] = {
166 {"__dir__", _PyCFunction_CAST(tb_dir), METH_NOARGS},
167 {NULL, NULL, 0, NULL},
168 };
169
170 static PyMemberDef tb_memberlist[] = {
171 {"tb_frame", _Py_T_OBJECT, OFF(tb_frame), Py_READONLY|Py_AUDIT_READ},
172 {"tb_lasti", Py_T_INT, OFF(tb_lasti), Py_READONLY},
173 {NULL} /* Sentinel */
174 };
175
176 static PyGetSetDef tb_getsetters[] = {
177 {"tb_next", (getter)tb_next_get, (setter)tb_next_set, NULL, NULL},
178 {"tb_lineno", (getter)tb_lineno_get, NULL, NULL, NULL},
179 {NULL} /* Sentinel */
180 };
181
182 static void
tb_dealloc(PyTracebackObject * tb)183 tb_dealloc(PyTracebackObject *tb)
184 {
185 PyObject_GC_UnTrack(tb);
186 Py_TRASHCAN_BEGIN(tb, tb_dealloc)
187 Py_XDECREF(tb->tb_next);
188 Py_XDECREF(tb->tb_frame);
189 PyObject_GC_Del(tb);
190 Py_TRASHCAN_END
191 }
192
193 static int
tb_traverse(PyTracebackObject * tb,visitproc visit,void * arg)194 tb_traverse(PyTracebackObject *tb, visitproc visit, void *arg)
195 {
196 Py_VISIT(tb->tb_next);
197 Py_VISIT(tb->tb_frame);
198 return 0;
199 }
200
201 static int
tb_clear(PyTracebackObject * tb)202 tb_clear(PyTracebackObject *tb)
203 {
204 Py_CLEAR(tb->tb_next);
205 Py_CLEAR(tb->tb_frame);
206 return 0;
207 }
208
209 PyTypeObject PyTraceBack_Type = {
210 PyVarObject_HEAD_INIT(&PyType_Type, 0)
211 "traceback",
212 sizeof(PyTracebackObject),
213 0,
214 (destructor)tb_dealloc, /*tp_dealloc*/
215 0, /*tp_vectorcall_offset*/
216 0, /*tp_getattr*/
217 0, /*tp_setattr*/
218 0, /*tp_as_async*/
219 0, /*tp_repr*/
220 0, /*tp_as_number*/
221 0, /*tp_as_sequence*/
222 0, /*tp_as_mapping*/
223 0, /* tp_hash */
224 0, /* tp_call */
225 0, /* tp_str */
226 PyObject_GenericGetAttr, /* tp_getattro */
227 0, /* tp_setattro */
228 0, /* tp_as_buffer */
229 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,/* tp_flags */
230 tb_new__doc__, /* tp_doc */
231 (traverseproc)tb_traverse, /* tp_traverse */
232 (inquiry)tb_clear, /* tp_clear */
233 0, /* tp_richcompare */
234 0, /* tp_weaklistoffset */
235 0, /* tp_iter */
236 0, /* tp_iternext */
237 tb_methods, /* tp_methods */
238 tb_memberlist, /* tp_members */
239 tb_getsetters, /* tp_getset */
240 0, /* tp_base */
241 0, /* tp_dict */
242 0, /* tp_descr_get */
243 0, /* tp_descr_set */
244 0, /* tp_dictoffset */
245 0, /* tp_init */
246 0, /* tp_alloc */
247 tb_new, /* tp_new */
248 };
249
250
251 PyObject*
_PyTraceBack_FromFrame(PyObject * tb_next,PyFrameObject * frame)252 _PyTraceBack_FromFrame(PyObject *tb_next, PyFrameObject *frame)
253 {
254 assert(tb_next == NULL || PyTraceBack_Check(tb_next));
255 assert(frame != NULL);
256 int addr = _PyInterpreterFrame_LASTI(frame->f_frame) * sizeof(_Py_CODEUNIT);
257 return tb_create_raw((PyTracebackObject *)tb_next, frame, addr, -1);
258 }
259
260
261 int
PyTraceBack_Here(PyFrameObject * frame)262 PyTraceBack_Here(PyFrameObject *frame)
263 {
264 PyObject *exc = PyErr_GetRaisedException();
265 assert(PyExceptionInstance_Check(exc));
266 PyObject *tb = PyException_GetTraceback(exc);
267 PyObject *newtb = _PyTraceBack_FromFrame(tb, frame);
268 Py_XDECREF(tb);
269 if (newtb == NULL) {
270 _PyErr_ChainExceptions1(exc);
271 return -1;
272 }
273 PyException_SetTraceback(exc, newtb);
274 Py_XDECREF(newtb);
275 PyErr_SetRaisedException(exc);
276 return 0;
277 }
278
279 /* Insert a frame into the traceback for (funcname, filename, lineno). */
_PyTraceback_Add(const char * funcname,const char * filename,int lineno)280 void _PyTraceback_Add(const char *funcname, const char *filename, int lineno)
281 {
282 PyObject *globals;
283 PyCodeObject *code;
284 PyFrameObject *frame;
285 PyThreadState *tstate = _PyThreadState_GET();
286
287 /* Save and clear the current exception. Python functions must not be
288 called with an exception set. Calling Python functions happens when
289 the codec of the filesystem encoding is implemented in pure Python. */
290 PyObject *exc = _PyErr_GetRaisedException(tstate);
291
292 globals = PyDict_New();
293 if (!globals)
294 goto error;
295 code = PyCode_NewEmpty(filename, funcname, lineno);
296 if (!code) {
297 Py_DECREF(globals);
298 goto error;
299 }
300 frame = PyFrame_New(tstate, code, globals, NULL);
301 Py_DECREF(globals);
302 Py_DECREF(code);
303 if (!frame)
304 goto error;
305 frame->f_lineno = lineno;
306
307 _PyErr_SetRaisedException(tstate, exc);
308 PyTraceBack_Here(frame);
309 Py_DECREF(frame);
310 return;
311
312 error:
313 _PyErr_ChainExceptions1(exc);
314 }
315
316 static PyObject *
_Py_FindSourceFile(PyObject * filename,char * namebuf,size_t namelen,PyObject * io)317 _Py_FindSourceFile(PyObject *filename, char* namebuf, size_t namelen, PyObject *io)
318 {
319 Py_ssize_t i;
320 PyObject *binary;
321 PyObject *v;
322 Py_ssize_t npath;
323 size_t taillen;
324 PyObject *syspath;
325 PyObject *path;
326 const char* tail;
327 PyObject *filebytes;
328 const char* filepath;
329 Py_ssize_t len;
330 PyObject* result;
331 PyObject *open = NULL;
332
333 filebytes = PyUnicode_EncodeFSDefault(filename);
334 if (filebytes == NULL) {
335 PyErr_Clear();
336 return NULL;
337 }
338 filepath = PyBytes_AS_STRING(filebytes);
339
340 /* Search tail of filename in sys.path before giving up */
341 tail = strrchr(filepath, SEP);
342 if (tail == NULL)
343 tail = filepath;
344 else
345 tail++;
346 taillen = strlen(tail);
347
348 PyThreadState *tstate = _PyThreadState_GET();
349 syspath = _PySys_GetAttr(tstate, &_Py_ID(path));
350 if (syspath == NULL || !PyList_Check(syspath))
351 goto error;
352 npath = PyList_Size(syspath);
353
354 open = PyObject_GetAttr(io, &_Py_ID(open));
355 for (i = 0; i < npath; i++) {
356 v = PyList_GetItem(syspath, i);
357 if (v == NULL) {
358 PyErr_Clear();
359 break;
360 }
361 if (!PyUnicode_Check(v))
362 continue;
363 path = PyUnicode_EncodeFSDefault(v);
364 if (path == NULL) {
365 PyErr_Clear();
366 continue;
367 }
368 len = PyBytes_GET_SIZE(path);
369 if (len + 1 + (Py_ssize_t)taillen >= (Py_ssize_t)namelen - 1) {
370 Py_DECREF(path);
371 continue; /* Too long */
372 }
373 strcpy(namebuf, PyBytes_AS_STRING(path));
374 Py_DECREF(path);
375 if (strlen(namebuf) != (size_t)len)
376 continue; /* v contains '\0' */
377 if (len > 0 && namebuf[len-1] != SEP)
378 namebuf[len++] = SEP;
379 strcpy(namebuf+len, tail);
380
381 binary = _PyObject_CallMethodFormat(tstate, open, "ss", namebuf, "rb");
382 if (binary != NULL) {
383 result = binary;
384 goto finally;
385 }
386 PyErr_Clear();
387 }
388 goto error;
389
390 error:
391 result = NULL;
392 finally:
393 Py_XDECREF(open);
394 Py_DECREF(filebytes);
395 return result;
396 }
397
398 /* Writes indent spaces. Returns 0 on success and non-zero on failure.
399 */
400 int
_Py_WriteIndent(int indent,PyObject * f)401 _Py_WriteIndent(int indent, PyObject *f)
402 {
403 char buf[11] = " ";
404 assert(strlen(buf) == 10);
405 while (indent > 0) {
406 if (indent < 10) {
407 buf[indent] = '\0';
408 }
409 if (PyFile_WriteString(buf, f) < 0) {
410 return -1;
411 }
412 indent -= 10;
413 }
414 return 0;
415 }
416
417 static int
display_source_line(PyObject * f,PyObject * filename,int lineno,int indent,int * truncation,PyObject ** line)418 display_source_line(PyObject *f, PyObject *filename, int lineno, int indent,
419 int *truncation, PyObject **line)
420 {
421 int fd;
422 int i;
423 char *found_encoding;
424 const char *encoding;
425 PyObject *io;
426 PyObject *binary;
427 PyObject *fob = NULL;
428 PyObject *lineobj = NULL;
429 PyObject *res;
430 char buf[MAXPATHLEN+1];
431 int kind;
432 const void *data;
433
434 /* open the file */
435 if (filename == NULL)
436 return 0;
437
438 /* Do not attempt to open things like <string> or <stdin> */
439 assert(PyUnicode_Check(filename));
440 if (PyUnicode_READ_CHAR(filename, 0) == '<') {
441 Py_ssize_t len = PyUnicode_GET_LENGTH(filename);
442 if (len > 0 && PyUnicode_READ_CHAR(filename, len - 1) == '>') {
443 return 0;
444 }
445 }
446
447 io = PyImport_ImportModule("io");
448 if (io == NULL) {
449 return -1;
450 }
451
452 binary = _PyObject_CallMethod(io, &_Py_ID(open), "Os", filename, "rb");
453 if (binary == NULL) {
454 PyErr_Clear();
455
456 binary = _Py_FindSourceFile(filename, buf, sizeof(buf), io);
457 if (binary == NULL) {
458 Py_DECREF(io);
459 return -1;
460 }
461 }
462
463 /* use the right encoding to decode the file as unicode */
464 fd = PyObject_AsFileDescriptor(binary);
465 if (fd < 0) {
466 Py_DECREF(io);
467 Py_DECREF(binary);
468 return 0;
469 }
470 found_encoding = _PyTokenizer_FindEncodingFilename(fd, filename);
471 if (found_encoding == NULL)
472 PyErr_Clear();
473 encoding = (found_encoding != NULL) ? found_encoding : "utf-8";
474 /* Reset position */
475 if (lseek(fd, 0, SEEK_SET) == (off_t)-1) {
476 Py_DECREF(io);
477 Py_DECREF(binary);
478 PyMem_Free(found_encoding);
479 return 0;
480 }
481 fob = _PyObject_CallMethod(io, &_Py_ID(TextIOWrapper),
482 "Os", binary, encoding);
483 Py_DECREF(io);
484 PyMem_Free(found_encoding);
485
486 if (fob == NULL) {
487 PyErr_Clear();
488
489 res = PyObject_CallMethodNoArgs(binary, &_Py_ID(close));
490 Py_DECREF(binary);
491 if (res)
492 Py_DECREF(res);
493 else
494 PyErr_Clear();
495 return 0;
496 }
497 Py_DECREF(binary);
498
499 /* get the line number lineno */
500 for (i = 0; i < lineno; i++) {
501 Py_XDECREF(lineobj);
502 lineobj = PyFile_GetLine(fob, -1);
503 if (!lineobj) {
504 PyErr_Clear();
505 break;
506 }
507 }
508 res = PyObject_CallMethodNoArgs(fob, &_Py_ID(close));
509 if (res) {
510 Py_DECREF(res);
511 }
512 else {
513 PyErr_Clear();
514 }
515 Py_DECREF(fob);
516 if (!lineobj || !PyUnicode_Check(lineobj)) {
517 Py_XDECREF(lineobj);
518 return -1;
519 }
520
521 if (line) {
522 *line = Py_NewRef(lineobj);
523 }
524
525 /* remove the indentation of the line */
526 kind = PyUnicode_KIND(lineobj);
527 data = PyUnicode_DATA(lineobj);
528 for (i=0; i < PyUnicode_GET_LENGTH(lineobj); i++) {
529 Py_UCS4 ch = PyUnicode_READ(kind, data, i);
530 if (ch != ' ' && ch != '\t' && ch != '\014')
531 break;
532 }
533 if (i) {
534 PyObject *truncated;
535 truncated = PyUnicode_Substring(lineobj, i, PyUnicode_GET_LENGTH(lineobj));
536 if (truncated) {
537 Py_SETREF(lineobj, truncated);
538 } else {
539 PyErr_Clear();
540 }
541 }
542
543 if (truncation != NULL) {
544 *truncation = i - indent;
545 }
546
547 /* Write some spaces before the line */
548 if (_Py_WriteIndent(indent, f) < 0) {
549 goto error;
550 }
551
552 /* finally display the line */
553 if (PyFile_WriteObject(lineobj, f, Py_PRINT_RAW) < 0) {
554 goto error;
555 }
556
557 if (PyFile_WriteString("\n", f) < 0) {
558 goto error;
559 }
560
561 Py_DECREF(lineobj);
562 return 0;
563 error:
564 Py_DECREF(lineobj);
565 return -1;
566 }
567
568 int
_Py_DisplaySourceLine(PyObject * f,PyObject * filename,int lineno,int indent,int * truncation,PyObject ** line)569 _Py_DisplaySourceLine(PyObject *f, PyObject *filename, int lineno, int indent,
570 int *truncation, PyObject **line)
571 {
572 return display_source_line(f, filename, lineno, indent, truncation, line);
573 }
574
575
576 #define IS_WHITESPACE(c) (((c) == ' ') || ((c) == '\t') || ((c) == '\f'))
577 #define _TRACEBACK_SOURCE_LINE_INDENT 4
578
579 static inline int
ignore_source_errors(void)580 ignore_source_errors(void) {
581 if (PyErr_Occurred()) {
582 if (PyErr_ExceptionMatches(PyExc_KeyboardInterrupt)) {
583 return -1;
584 }
585 PyErr_Clear();
586 }
587 return 0;
588 }
589
590 static int
tb_displayline(PyTracebackObject * tb,PyObject * f,PyObject * filename,int lineno,PyFrameObject * frame,PyObject * name)591 tb_displayline(PyTracebackObject* tb, PyObject *f, PyObject *filename, int lineno,
592 PyFrameObject *frame, PyObject *name)
593 {
594 if (filename == NULL || name == NULL) {
595 return -1;
596 }
597
598 PyObject *line = PyUnicode_FromFormat(" File \"%U\", line %d, in %U\n",
599 filename, lineno, name);
600 if (line == NULL) {
601 return -1;
602 }
603
604 int res = PyFile_WriteObject(line, f, Py_PRINT_RAW);
605 Py_DECREF(line);
606 if (res < 0) {
607 return -1;
608 }
609
610 int err = 0;
611
612 int truncation = _TRACEBACK_SOURCE_LINE_INDENT;
613 PyObject* source_line = NULL;
614 int rc = display_source_line(
615 f, filename, lineno, _TRACEBACK_SOURCE_LINE_INDENT,
616 &truncation, &source_line);
617 if (rc != 0 || !source_line) {
618 /* ignore errors since we can't report them, can we? */
619 err = ignore_source_errors();
620 }
621 Py_XDECREF(source_line);
622 return err;
623 }
624
625 static const int TB_RECURSIVE_CUTOFF = 3; // Also hardcoded in traceback.py.
626
627 static int
tb_print_line_repeated(PyObject * f,long cnt)628 tb_print_line_repeated(PyObject *f, long cnt)
629 {
630 cnt -= TB_RECURSIVE_CUTOFF;
631 PyObject *line = PyUnicode_FromFormat(
632 (cnt > 1)
633 ? " [Previous line repeated %ld more times]\n"
634 : " [Previous line repeated %ld more time]\n",
635 cnt);
636 if (line == NULL) {
637 return -1;
638 }
639 int err = PyFile_WriteObject(line, f, Py_PRINT_RAW);
640 Py_DECREF(line);
641 return err;
642 }
643
644 static int
tb_printinternal(PyTracebackObject * tb,PyObject * f,long limit)645 tb_printinternal(PyTracebackObject *tb, PyObject *f, long limit)
646 {
647 PyCodeObject *code = NULL;
648 Py_ssize_t depth = 0;
649 PyObject *last_file = NULL;
650 int last_line = -1;
651 PyObject *last_name = NULL;
652 long cnt = 0;
653 PyTracebackObject *tb1 = tb;
654 while (tb1 != NULL) {
655 depth++;
656 tb1 = tb1->tb_next;
657 }
658 while (tb != NULL && depth > limit) {
659 depth--;
660 tb = tb->tb_next;
661 }
662 while (tb != NULL) {
663 code = PyFrame_GetCode(tb->tb_frame);
664 int tb_lineno = tb->tb_lineno;
665 if (tb_lineno == -1) {
666 tb_lineno = tb_get_lineno(tb);
667 }
668 if (last_file == NULL ||
669 code->co_filename != last_file ||
670 last_line == -1 || tb_lineno != last_line ||
671 last_name == NULL || code->co_name != last_name) {
672 if (cnt > TB_RECURSIVE_CUTOFF) {
673 if (tb_print_line_repeated(f, cnt) < 0) {
674 goto error;
675 }
676 }
677 last_file = code->co_filename;
678 last_line = tb_lineno;
679 last_name = code->co_name;
680 cnt = 0;
681 }
682 cnt++;
683 if (cnt <= TB_RECURSIVE_CUTOFF) {
684 if (tb_displayline(tb, f, code->co_filename, tb_lineno,
685 tb->tb_frame, code->co_name) < 0) {
686 goto error;
687 }
688
689 if (PyErr_CheckSignals() < 0) {
690 goto error;
691 }
692 }
693 Py_CLEAR(code);
694 tb = tb->tb_next;
695 }
696 if (cnt > TB_RECURSIVE_CUTOFF) {
697 if (tb_print_line_repeated(f, cnt) < 0) {
698 goto error;
699 }
700 }
701 return 0;
702 error:
703 Py_XDECREF(code);
704 return -1;
705 }
706
707 #define PyTraceBack_LIMIT 1000
708
709 int
_PyTraceBack_Print(PyObject * v,const char * header,PyObject * f)710 _PyTraceBack_Print(PyObject *v, const char *header, PyObject *f)
711 {
712 PyObject *limitv;
713 long limit = PyTraceBack_LIMIT;
714
715 if (v == NULL) {
716 return 0;
717 }
718 if (!PyTraceBack_Check(v)) {
719 PyErr_BadInternalCall();
720 return -1;
721 }
722 limitv = PySys_GetObject("tracebacklimit");
723 if (limitv && PyLong_Check(limitv)) {
724 int overflow;
725 limit = PyLong_AsLongAndOverflow(limitv, &overflow);
726 if (overflow > 0) {
727 limit = LONG_MAX;
728 }
729 else if (limit <= 0) {
730 return 0;
731 }
732 }
733
734 if (PyFile_WriteString(header, f) < 0) {
735 return -1;
736 }
737
738 if (tb_printinternal((PyTracebackObject *)v, f, limit) < 0) {
739 return -1;
740 }
741
742 return 0;
743 }
744
745 int
PyTraceBack_Print(PyObject * v,PyObject * f)746 PyTraceBack_Print(PyObject *v, PyObject *f)
747 {
748 const char *header = EXCEPTION_TB_HEADER;
749 return _PyTraceBack_Print(v, header, f);
750 }
751
752 /* Format an integer in range [0; 0xffffffff] to decimal and write it
753 into the file fd.
754
755 This function is signal safe. */
756
757 void
_Py_DumpDecimal(int fd,size_t value)758 _Py_DumpDecimal(int fd, size_t value)
759 {
760 /* maximum number of characters required for output of %lld or %p.
761 We need at most ceil(log10(256)*SIZEOF_LONG_LONG) digits,
762 plus 1 for the null byte. 53/22 is an upper bound for log10(256). */
763 char buffer[1 + (sizeof(size_t)*53-1) / 22 + 1];
764 char *ptr, *end;
765
766 end = &buffer[Py_ARRAY_LENGTH(buffer) - 1];
767 ptr = end;
768 *ptr = '\0';
769 do {
770 --ptr;
771 assert(ptr >= buffer);
772 *ptr = '0' + (value % 10);
773 value /= 10;
774 } while (value);
775
776 (void)_Py_write_noraise(fd, ptr, end - ptr);
777 }
778
779 /* Format an integer as hexadecimal with width digits into fd file descriptor.
780 The function is signal safe. */
781 void
_Py_DumpHexadecimal(int fd,uintptr_t value,Py_ssize_t width)782 _Py_DumpHexadecimal(int fd, uintptr_t value, Py_ssize_t width)
783 {
784 char buffer[sizeof(uintptr_t) * 2 + 1], *ptr, *end;
785 const Py_ssize_t size = Py_ARRAY_LENGTH(buffer) - 1;
786
787 if (width > size)
788 width = size;
789 /* it's ok if width is negative */
790
791 end = &buffer[size];
792 ptr = end;
793 *ptr = '\0';
794 do {
795 --ptr;
796 assert(ptr >= buffer);
797 *ptr = Py_hexdigits[value & 15];
798 value >>= 4;
799 } while ((end - ptr) < width || value);
800
801 (void)_Py_write_noraise(fd, ptr, end - ptr);
802 }
803
804 void
_Py_DumpASCII(int fd,PyObject * text)805 _Py_DumpASCII(int fd, PyObject *text)
806 {
807 PyASCIIObject *ascii = _PyASCIIObject_CAST(text);
808 Py_ssize_t i, size;
809 int truncated;
810 int kind;
811 void *data = NULL;
812 Py_UCS4 ch;
813
814 if (!PyUnicode_Check(text))
815 return;
816
817 size = ascii->length;
818 kind = ascii->state.kind;
819 if (ascii->state.compact) {
820 if (ascii->state.ascii)
821 data = ascii + 1;
822 else
823 data = _PyCompactUnicodeObject_CAST(text) + 1;
824 }
825 else {
826 data = _PyUnicodeObject_CAST(text)->data.any;
827 if (data == NULL)
828 return;
829 }
830
831 if (MAX_STRING_LENGTH < size) {
832 size = MAX_STRING_LENGTH;
833 truncated = 1;
834 }
835 else {
836 truncated = 0;
837 }
838
839 // Is an ASCII string?
840 if (ascii->state.ascii) {
841 assert(kind == PyUnicode_1BYTE_KIND);
842 char *str = data;
843
844 int need_escape = 0;
845 for (i=0; i < size; i++) {
846 ch = str[i];
847 if (!(' ' <= ch && ch <= 126)) {
848 need_escape = 1;
849 break;
850 }
851 }
852 if (!need_escape) {
853 // The string can be written with a single write() syscall
854 (void)_Py_write_noraise(fd, str, size);
855 goto done;
856 }
857 }
858
859 for (i=0; i < size; i++) {
860 ch = PyUnicode_READ(kind, data, i);
861 if (' ' <= ch && ch <= 126) {
862 /* printable ASCII character */
863 char c = (char)ch;
864 (void)_Py_write_noraise(fd, &c, 1);
865 }
866 else if (ch <= 0xff) {
867 PUTS(fd, "\\x");
868 _Py_DumpHexadecimal(fd, ch, 2);
869 }
870 else if (ch <= 0xffff) {
871 PUTS(fd, "\\u");
872 _Py_DumpHexadecimal(fd, ch, 4);
873 }
874 else {
875 PUTS(fd, "\\U");
876 _Py_DumpHexadecimal(fd, ch, 8);
877 }
878 }
879
880 done:
881 if (truncated) {
882 PUTS(fd, "...");
883 }
884 }
885
886 /* Write a frame into the file fd: "File "xxx", line xxx in xxx".
887
888 This function is signal safe. */
889
890 static void
dump_frame(int fd,_PyInterpreterFrame * frame)891 dump_frame(int fd, _PyInterpreterFrame *frame)
892 {
893 assert(frame->owner != FRAME_OWNED_BY_CSTACK);
894
895 PyCodeObject *code =_PyFrame_GetCode(frame);
896 PUTS(fd, " File ");
897 if (code->co_filename != NULL
898 && PyUnicode_Check(code->co_filename))
899 {
900 PUTS(fd, "\"");
901 _Py_DumpASCII(fd, code->co_filename);
902 PUTS(fd, "\"");
903 } else {
904 PUTS(fd, "???");
905 }
906
907 int lineno = PyUnstable_InterpreterFrame_GetLine(frame);
908 PUTS(fd, ", line ");
909 if (lineno >= 0) {
910 _Py_DumpDecimal(fd, (size_t)lineno);
911 }
912 else {
913 PUTS(fd, "???");
914 }
915 PUTS(fd, " in ");
916
917 if (code->co_name != NULL
918 && PyUnicode_Check(code->co_name)) {
919 _Py_DumpASCII(fd, code->co_name);
920 }
921 else {
922 PUTS(fd, "???");
923 }
924
925 PUTS(fd, "\n");
926 }
927
928 static int
tstate_is_freed(PyThreadState * tstate)929 tstate_is_freed(PyThreadState *tstate)
930 {
931 if (_PyMem_IsPtrFreed(tstate)) {
932 return 1;
933 }
934 if (_PyMem_IsPtrFreed(tstate->interp)) {
935 return 1;
936 }
937 return 0;
938 }
939
940
941 static int
interp_is_freed(PyInterpreterState * interp)942 interp_is_freed(PyInterpreterState *interp)
943 {
944 return _PyMem_IsPtrFreed(interp);
945 }
946
947
948 static void
dump_traceback(int fd,PyThreadState * tstate,int write_header)949 dump_traceback(int fd, PyThreadState *tstate, int write_header)
950 {
951 if (write_header) {
952 PUTS(fd, "Stack (most recent call first):\n");
953 }
954
955 if (tstate_is_freed(tstate)) {
956 PUTS(fd, " <tstate is freed>\n");
957 return;
958 }
959
960 _PyInterpreterFrame *frame = tstate->current_frame;
961 if (frame == NULL) {
962 PUTS(fd, " <no Python frame>\n");
963 return;
964 }
965
966 unsigned int depth = 0;
967 while (1) {
968 if (frame->owner == FRAME_OWNED_BY_CSTACK) {
969 /* Trampoline frame */
970 frame = frame->previous;
971 if (frame == NULL) {
972 break;
973 }
974
975 /* Can't have more than one shim frame in a row */
976 assert(frame->owner != FRAME_OWNED_BY_CSTACK);
977 }
978
979 if (MAX_FRAME_DEPTH <= depth) {
980 if (MAX_FRAME_DEPTH < depth) {
981 PUTS(fd, "plus ");
982 _Py_DumpDecimal(fd, depth);
983 PUTS(fd, " frames\n");
984 }
985 break;
986 }
987
988 dump_frame(fd, frame);
989 frame = frame->previous;
990 if (frame == NULL) {
991 break;
992 }
993 depth++;
994 }
995 }
996
997 /* Dump the traceback of a Python thread into fd. Use write() to write the
998 traceback and retry if write() is interrupted by a signal (failed with
999 EINTR), but don't call the Python signal handler.
1000
1001 The caller is responsible to call PyErr_CheckSignals() to call Python signal
1002 handlers if signals were received. */
1003 void
_Py_DumpTraceback(int fd,PyThreadState * tstate)1004 _Py_DumpTraceback(int fd, PyThreadState *tstate)
1005 {
1006 dump_traceback(fd, tstate, 1);
1007 }
1008
1009 /* Write the thread identifier into the file 'fd': "Current thread 0xHHHH:\" if
1010 is_current is true, "Thread 0xHHHH:\n" otherwise.
1011
1012 This function is signal safe. */
1013
1014 static void
write_thread_id(int fd,PyThreadState * tstate,int is_current)1015 write_thread_id(int fd, PyThreadState *tstate, int is_current)
1016 {
1017 if (is_current)
1018 PUTS(fd, "Current thread 0x");
1019 else
1020 PUTS(fd, "Thread 0x");
1021 _Py_DumpHexadecimal(fd,
1022 tstate->thread_id,
1023 sizeof(unsigned long) * 2);
1024 PUTS(fd, " (most recent call first):\n");
1025 }
1026
1027 /* Dump the traceback of all Python threads into fd. Use write() to write the
1028 traceback and retry if write() is interrupted by a signal (failed with
1029 EINTR), but don't call the Python signal handler.
1030
1031 The caller is responsible to call PyErr_CheckSignals() to call Python signal
1032 handlers if signals were received. */
1033 const char*
_Py_DumpTracebackThreads(int fd,PyInterpreterState * interp,PyThreadState * current_tstate)1034 _Py_DumpTracebackThreads(int fd, PyInterpreterState *interp,
1035 PyThreadState *current_tstate)
1036 {
1037 if (current_tstate == NULL) {
1038 /* _Py_DumpTracebackThreads() is called from signal handlers by
1039 faulthandler.
1040
1041 SIGSEGV, SIGFPE, SIGABRT, SIGBUS and SIGILL are synchronous signals
1042 and are thus delivered to the thread that caused the fault. Get the
1043 Python thread state of the current thread.
1044
1045 PyThreadState_Get() doesn't give the state of the thread that caused
1046 the fault if the thread released the GIL, and so
1047 _PyThreadState_GET() cannot be used. Read the thread specific
1048 storage (TSS) instead: call PyGILState_GetThisThreadState(). */
1049 current_tstate = PyGILState_GetThisThreadState();
1050 }
1051
1052 if (current_tstate != NULL && tstate_is_freed(current_tstate)) {
1053 return "tstate is freed";
1054 }
1055
1056 if (interp == NULL) {
1057 if (current_tstate == NULL) {
1058 interp = _PyGILState_GetInterpreterStateUnsafe();
1059 if (interp == NULL) {
1060 /* We need the interpreter state to get Python threads */
1061 return "unable to get the interpreter state";
1062 }
1063 }
1064 else {
1065 interp = current_tstate->interp;
1066 }
1067 }
1068 assert(interp != NULL);
1069
1070 if (interp_is_freed(interp)) {
1071 return "interp is freed";
1072 }
1073
1074 /* Get the current interpreter from the current thread */
1075 PyThreadState *tstate = PyInterpreterState_ThreadHead(interp);
1076 if (tstate == NULL)
1077 return "unable to get the thread head state";
1078
1079 /* Dump the traceback of each thread */
1080 tstate = PyInterpreterState_ThreadHead(interp);
1081 unsigned int nthreads = 0;
1082 _Py_BEGIN_SUPPRESS_IPH
1083 do
1084 {
1085 if (nthreads != 0)
1086 PUTS(fd, "\n");
1087 if (nthreads >= MAX_NTHREADS) {
1088 PUTS(fd, "...\n");
1089 break;
1090 }
1091 write_thread_id(fd, tstate, tstate == current_tstate);
1092 if (tstate == current_tstate && tstate->interp->gc.collecting) {
1093 PUTS(fd, " Garbage-collecting\n");
1094 }
1095 dump_traceback(fd, tstate, 0);
1096 tstate = PyThreadState_Next(tstate);
1097 nthreads++;
1098 } while (tstate != NULL);
1099 _Py_END_SUPPRESS_IPH
1100
1101 return NULL;
1102 }
1103
1104