• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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