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