• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 
2 /* Traceback implementation */
3 
4 #include "Python.h"
5 #include "internal/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)90 tb_dir(PyTracebackObject *self)
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_SAFE_BEGIN(tb)
167     Py_XDECREF(tb->tb_next);
168     Py_XDECREF(tb->tb_frame);
169     PyObject_GC_Del(tb);
170     Py_TRASHCAN_SAFE_END(tb)
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_print*/
196     0,    /*tp_getattr*/
197     0,                  /*tp_setattr*/
198     0,                  /*tp_reserved*/
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 int
PyTraceBack_Here(PyFrameObject * frame)231 PyTraceBack_Here(PyFrameObject *frame)
232 {
233     PyObject *exc, *val, *tb, *newtb;
234     PyErr_Fetch(&exc, &val, &tb);
235     newtb = tb_create_raw((PyTracebackObject *)tb, frame, frame->f_lasti,
236                           PyFrame_GetLineNumber(frame));
237     if (newtb == NULL) {
238         _PyErr_ChainExceptions(exc, val, tb);
239         return -1;
240     }
241     PyErr_Restore(exc, val, newtb);
242     Py_XDECREF(tb);
243     return 0;
244 }
245 
246 /* Insert a frame into the traceback for (funcname, filename, lineno). */
_PyTraceback_Add(const char * funcname,const char * filename,int lineno)247 void _PyTraceback_Add(const char *funcname, const char *filename, int lineno)
248 {
249     PyObject *globals;
250     PyCodeObject *code;
251     PyFrameObject *frame;
252     PyObject *exc, *val, *tb;
253 
254     /* Save and clear the current exception. Python functions must not be
255        called with an exception set. Calling Python functions happens when
256        the codec of the filesystem encoding is implemented in pure Python. */
257     PyErr_Fetch(&exc, &val, &tb);
258 
259     globals = PyDict_New();
260     if (!globals)
261         goto error;
262     code = PyCode_NewEmpty(filename, funcname, lineno);
263     if (!code) {
264         Py_DECREF(globals);
265         goto error;
266     }
267     frame = PyFrame_New(PyThreadState_Get(), code, globals, NULL);
268     Py_DECREF(globals);
269     Py_DECREF(code);
270     if (!frame)
271         goto error;
272     frame->f_lineno = lineno;
273 
274     PyErr_Restore(exc, val, tb);
275     PyTraceBack_Here(frame);
276     Py_DECREF(frame);
277     return;
278 
279 error:
280     _PyErr_ChainExceptions(exc, val, tb);
281 }
282 
283 static PyObject *
_Py_FindSourceFile(PyObject * filename,char * namebuf,size_t namelen,PyObject * io)284 _Py_FindSourceFile(PyObject *filename, char* namebuf, size_t namelen, PyObject *io)
285 {
286     Py_ssize_t i;
287     PyObject *binary;
288     PyObject *v;
289     Py_ssize_t npath;
290     size_t taillen;
291     PyObject *syspath;
292     PyObject *path;
293     const char* tail;
294     PyObject *filebytes;
295     const char* filepath;
296     Py_ssize_t len;
297     PyObject* result;
298 
299     filebytes = PyUnicode_EncodeFSDefault(filename);
300     if (filebytes == NULL) {
301         PyErr_Clear();
302         return NULL;
303     }
304     filepath = PyBytes_AS_STRING(filebytes);
305 
306     /* Search tail of filename in sys.path before giving up */
307     tail = strrchr(filepath, SEP);
308     if (tail == NULL)
309         tail = filepath;
310     else
311         tail++;
312     taillen = strlen(tail);
313 
314     syspath = _PySys_GetObjectId(&PyId_path);
315     if (syspath == NULL || !PyList_Check(syspath))
316         goto error;
317     npath = PyList_Size(syspath);
318 
319     for (i = 0; i < npath; i++) {
320         v = PyList_GetItem(syspath, i);
321         if (v == NULL) {
322             PyErr_Clear();
323             break;
324         }
325         if (!PyUnicode_Check(v))
326             continue;
327         path = PyUnicode_EncodeFSDefault(v);
328         if (path == NULL) {
329             PyErr_Clear();
330             continue;
331         }
332         len = PyBytes_GET_SIZE(path);
333         if (len + 1 + (Py_ssize_t)taillen >= (Py_ssize_t)namelen - 1) {
334             Py_DECREF(path);
335             continue; /* Too long */
336         }
337         strcpy(namebuf, PyBytes_AS_STRING(path));
338         Py_DECREF(path);
339         if (strlen(namebuf) != (size_t)len)
340             continue; /* v contains '\0' */
341         if (len > 0 && namebuf[len-1] != SEP)
342             namebuf[len++] = SEP;
343         strcpy(namebuf+len, tail);
344 
345         binary = _PyObject_CallMethodId(io, &PyId_open, "ss", namebuf, "rb");
346         if (binary != NULL) {
347             result = binary;
348             goto finally;
349         }
350         PyErr_Clear();
351     }
352     goto error;
353 
354 error:
355     result = NULL;
356 finally:
357     Py_DECREF(filebytes);
358     return result;
359 }
360 
361 int
_Py_DisplaySourceLine(PyObject * f,PyObject * filename,int lineno,int indent)362 _Py_DisplaySourceLine(PyObject *f, PyObject *filename, int lineno, int indent)
363 {
364     int err = 0;
365     int fd;
366     int i;
367     char *found_encoding;
368     char *encoding;
369     PyObject *io;
370     PyObject *binary;
371     PyObject *fob = NULL;
372     PyObject *lineobj = NULL;
373     PyObject *res;
374     char buf[MAXPATHLEN+1];
375     int kind;
376     void *data;
377 
378     /* open the file */
379     if (filename == NULL)
380         return 0;
381 
382     io = PyImport_ImportModuleNoBlock("io");
383     if (io == NULL)
384         return -1;
385     binary = _PyObject_CallMethodId(io, &PyId_open, "Os", filename, "rb");
386 
387     if (binary == NULL) {
388         PyErr_Clear();
389 
390         binary = _Py_FindSourceFile(filename, buf, sizeof(buf), io);
391         if (binary == NULL) {
392             Py_DECREF(io);
393             return -1;
394         }
395     }
396 
397     /* use the right encoding to decode the file as unicode */
398     fd = PyObject_AsFileDescriptor(binary);
399     if (fd < 0) {
400         Py_DECREF(io);
401         Py_DECREF(binary);
402         return 0;
403     }
404     found_encoding = PyTokenizer_FindEncodingFilename(fd, filename);
405     if (found_encoding == NULL)
406         PyErr_Clear();
407     encoding = (found_encoding != NULL) ? found_encoding : "utf-8";
408     /* Reset position */
409     if (lseek(fd, 0, SEEK_SET) == (off_t)-1) {
410         Py_DECREF(io);
411         Py_DECREF(binary);
412         PyMem_FREE(found_encoding);
413         return 0;
414     }
415     fob = _PyObject_CallMethodId(io, &PyId_TextIOWrapper, "Os", binary, encoding);
416     Py_DECREF(io);
417     PyMem_FREE(found_encoding);
418 
419     if (fob == NULL) {
420         PyErr_Clear();
421 
422         res = _PyObject_CallMethodId(binary, &PyId_close, NULL);
423         Py_DECREF(binary);
424         if (res)
425             Py_DECREF(res);
426         else
427             PyErr_Clear();
428         return 0;
429     }
430     Py_DECREF(binary);
431 
432     /* get the line number lineno */
433     for (i = 0; i < lineno; i++) {
434         Py_XDECREF(lineobj);
435         lineobj = PyFile_GetLine(fob, -1);
436         if (!lineobj) {
437             PyErr_Clear();
438             err = -1;
439             break;
440         }
441     }
442     res = _PyObject_CallMethodId(fob, &PyId_close, NULL);
443     if (res)
444         Py_DECREF(res);
445     else
446         PyErr_Clear();
447     Py_DECREF(fob);
448     if (!lineobj || !PyUnicode_Check(lineobj)) {
449         Py_XDECREF(lineobj);
450         return err;
451     }
452 
453     /* remove the indentation of the line */
454     kind = PyUnicode_KIND(lineobj);
455     data = PyUnicode_DATA(lineobj);
456     for (i=0; i < PyUnicode_GET_LENGTH(lineobj); i++) {
457         Py_UCS4 ch = PyUnicode_READ(kind, data, i);
458         if (ch != ' ' && ch != '\t' && ch != '\014')
459             break;
460     }
461     if (i) {
462         PyObject *truncated;
463         truncated = PyUnicode_Substring(lineobj, i, PyUnicode_GET_LENGTH(lineobj));
464         if (truncated) {
465             Py_DECREF(lineobj);
466             lineobj = truncated;
467         } else {
468             PyErr_Clear();
469         }
470     }
471 
472     /* Write some spaces before the line */
473     strcpy(buf, "          ");
474     assert (strlen(buf) == 10);
475     while (indent > 0) {
476         if (indent < 10)
477             buf[indent] = '\0';
478         err = PyFile_WriteString(buf, f);
479         if (err != 0)
480             break;
481         indent -= 10;
482     }
483 
484     /* finally display the line */
485     if (err == 0)
486         err = PyFile_WriteObject(lineobj, f, Py_PRINT_RAW);
487     Py_DECREF(lineobj);
488     if  (err == 0)
489         err = PyFile_WriteString("\n", f);
490     return err;
491 }
492 
493 static int
tb_displayline(PyObject * f,PyObject * filename,int lineno,PyObject * name)494 tb_displayline(PyObject *f, PyObject *filename, int lineno, PyObject *name)
495 {
496     int err;
497     PyObject *line;
498 
499     if (filename == NULL || name == NULL)
500         return -1;
501     line = PyUnicode_FromFormat("  File \"%U\", line %d, in %U\n",
502                                 filename, lineno, name);
503     if (line == NULL)
504         return -1;
505     err = PyFile_WriteObject(line, f, Py_PRINT_RAW);
506     Py_DECREF(line);
507     if (err != 0)
508         return err;
509     /* ignore errors since we can't report them, can we? */
510     if (_Py_DisplaySourceLine(f, filename, lineno, 4))
511         PyErr_Clear();
512     return err;
513 }
514 
515 static const int TB_RECURSIVE_CUTOFF = 3; // Also hardcoded in traceback.py.
516 
517 static int
tb_print_line_repeated(PyObject * f,long cnt)518 tb_print_line_repeated(PyObject *f, long cnt)
519 {
520     cnt -= TB_RECURSIVE_CUTOFF;
521     PyObject *line = PyUnicode_FromFormat(
522         (cnt > 1)
523           ? "  [Previous line repeated %ld more times]\n"
524           : "  [Previous line repeated %ld more time]\n",
525         cnt);
526     if (line == NULL) {
527         return -1;
528     }
529     int err = PyFile_WriteObject(line, f, Py_PRINT_RAW);
530     Py_DECREF(line);
531     return err;
532 }
533 
534 static int
tb_printinternal(PyTracebackObject * tb,PyObject * f,long limit)535 tb_printinternal(PyTracebackObject *tb, PyObject *f, long limit)
536 {
537     int err = 0;
538     Py_ssize_t depth = 0;
539     PyObject *last_file = NULL;
540     int last_line = -1;
541     PyObject *last_name = NULL;
542     long cnt = 0;
543     PyTracebackObject *tb1 = tb;
544     while (tb1 != NULL) {
545         depth++;
546         tb1 = tb1->tb_next;
547     }
548     while (tb != NULL && depth > limit) {
549         depth--;
550         tb = tb->tb_next;
551     }
552     while (tb != NULL && err == 0) {
553         if (last_file == NULL ||
554             tb->tb_frame->f_code->co_filename != last_file ||
555             last_line == -1 || tb->tb_lineno != last_line ||
556             last_name == NULL || tb->tb_frame->f_code->co_name != last_name) {
557             if (cnt > TB_RECURSIVE_CUTOFF) {
558                 err = tb_print_line_repeated(f, cnt);
559             }
560             last_file = tb->tb_frame->f_code->co_filename;
561             last_line = tb->tb_lineno;
562             last_name = tb->tb_frame->f_code->co_name;
563             cnt = 0;
564         }
565         cnt++;
566         if (err == 0 && cnt <= TB_RECURSIVE_CUTOFF) {
567             err = tb_displayline(f,
568                                  tb->tb_frame->f_code->co_filename,
569                                  tb->tb_lineno,
570                                  tb->tb_frame->f_code->co_name);
571             if (err == 0) {
572                 err = PyErr_CheckSignals();
573             }
574         }
575         tb = tb->tb_next;
576     }
577     if (err == 0 && cnt > TB_RECURSIVE_CUTOFF) {
578         err = tb_print_line_repeated(f, cnt);
579     }
580     return err;
581 }
582 
583 #define PyTraceBack_LIMIT 1000
584 
585 int
PyTraceBack_Print(PyObject * v,PyObject * f)586 PyTraceBack_Print(PyObject *v, PyObject *f)
587 {
588     int err;
589     PyObject *limitv;
590     long limit = PyTraceBack_LIMIT;
591 
592     if (v == NULL)
593         return 0;
594     if (!PyTraceBack_Check(v)) {
595         PyErr_BadInternalCall();
596         return -1;
597     }
598     limitv = PySys_GetObject("tracebacklimit");
599     if (limitv && PyLong_Check(limitv)) {
600         int overflow;
601         limit = PyLong_AsLongAndOverflow(limitv, &overflow);
602         if (overflow > 0) {
603             limit = LONG_MAX;
604         }
605         else if (limit <= 0) {
606             return 0;
607         }
608     }
609     err = PyFile_WriteString("Traceback (most recent call last):\n", f);
610     if (!err)
611         err = tb_printinternal((PyTracebackObject *)v, f, limit);
612     return err;
613 }
614 
615 /* Reverse a string. For example, "abcd" becomes "dcba".
616 
617    This function is signal safe. */
618 
619 void
_Py_DumpDecimal(int fd,unsigned long value)620 _Py_DumpDecimal(int fd, unsigned long value)
621 {
622     /* maximum number of characters required for output of %lld or %p.
623        We need at most ceil(log10(256)*SIZEOF_LONG_LONG) digits,
624        plus 1 for the null byte.  53/22 is an upper bound for log10(256). */
625     char buffer[1 + (sizeof(unsigned long)*53-1) / 22 + 1];
626     char *ptr, *end;
627 
628     end = &buffer[Py_ARRAY_LENGTH(buffer) - 1];
629     ptr = end;
630     *ptr = '\0';
631     do {
632         --ptr;
633         assert(ptr >= buffer);
634         *ptr = '0' + (value % 10);
635         value /= 10;
636     } while (value);
637 
638     _Py_write_noraise(fd, ptr, end - ptr);
639 }
640 
641 /* Format an integer in range [0; 0xffffffff] to hexadecimal of 'width' digits,
642    and write it into the file fd.
643 
644    This function is signal safe. */
645 
646 void
_Py_DumpHexadecimal(int fd,unsigned long value,Py_ssize_t width)647 _Py_DumpHexadecimal(int fd, unsigned long value, Py_ssize_t width)
648 {
649     char buffer[sizeof(unsigned long) * 2 + 1], *ptr, *end;
650     const Py_ssize_t size = Py_ARRAY_LENGTH(buffer) - 1;
651 
652     if (width > size)
653         width = size;
654     /* it's ok if width is negative */
655 
656     end = &buffer[size];
657     ptr = end;
658     *ptr = '\0';
659     do {
660         --ptr;
661         assert(ptr >= buffer);
662         *ptr = Py_hexdigits[value & 15];
663         value >>= 4;
664     } while ((end - ptr) < width || value);
665 
666     _Py_write_noraise(fd, ptr, end - ptr);
667 }
668 
669 void
_Py_DumpASCII(int fd,PyObject * text)670 _Py_DumpASCII(int fd, PyObject *text)
671 {
672     PyASCIIObject *ascii = (PyASCIIObject *)text;
673     Py_ssize_t i, size;
674     int truncated;
675     int kind;
676     void *data = NULL;
677     wchar_t *wstr = NULL;
678     Py_UCS4 ch;
679 
680     if (!PyUnicode_Check(text))
681         return;
682 
683     size = ascii->length;
684     kind = ascii->state.kind;
685     if (kind == PyUnicode_WCHAR_KIND) {
686         wstr = ((PyASCIIObject *)text)->wstr;
687         if (wstr == NULL)
688             return;
689         size = ((PyCompactUnicodeObject *)text)->wstr_length;
690     }
691     else if (ascii->state.compact) {
692         if (ascii->state.ascii)
693             data = ((PyASCIIObject*)text) + 1;
694         else
695             data = ((PyCompactUnicodeObject*)text) + 1;
696     }
697     else {
698         data = ((PyUnicodeObject *)text)->data.any;
699         if (data == NULL)
700             return;
701     }
702 
703     if (MAX_STRING_LENGTH < size) {
704         size = MAX_STRING_LENGTH;
705         truncated = 1;
706     }
707     else {
708         truncated = 0;
709     }
710 
711     for (i=0; i < size; i++) {
712         if (kind != PyUnicode_WCHAR_KIND)
713             ch = PyUnicode_READ(kind, data, i);
714         else
715             ch = wstr[i];
716         if (' ' <= ch && ch <= 126) {
717             /* printable ASCII character */
718             char c = (char)ch;
719             _Py_write_noraise(fd, &c, 1);
720         }
721         else if (ch <= 0xff) {
722             PUTS(fd, "\\x");
723             _Py_DumpHexadecimal(fd, ch, 2);
724         }
725         else if (ch <= 0xffff) {
726             PUTS(fd, "\\u");
727             _Py_DumpHexadecimal(fd, ch, 4);
728         }
729         else {
730             PUTS(fd, "\\U");
731             _Py_DumpHexadecimal(fd, ch, 8);
732         }
733     }
734     if (truncated) {
735         PUTS(fd, "...");
736     }
737 }
738 
739 /* Write a frame into the file fd: "File "xxx", line xxx in xxx".
740 
741    This function is signal safe. */
742 
743 static void
dump_frame(int fd,PyFrameObject * frame)744 dump_frame(int fd, PyFrameObject *frame)
745 {
746     PyCodeObject *code;
747     int lineno;
748 
749     code = frame->f_code;
750     PUTS(fd, "  File ");
751     if (code != NULL && code->co_filename != NULL
752         && PyUnicode_Check(code->co_filename))
753     {
754         PUTS(fd, "\"");
755         _Py_DumpASCII(fd, code->co_filename);
756         PUTS(fd, "\"");
757     } else {
758         PUTS(fd, "???");
759     }
760 
761     /* PyFrame_GetLineNumber() was introduced in Python 2.7.0 and 3.2.0 */
762     lineno = PyCode_Addr2Line(code, frame->f_lasti);
763     PUTS(fd, ", line ");
764     if (lineno >= 0) {
765         _Py_DumpDecimal(fd, (unsigned long)lineno);
766     }
767     else {
768         PUTS(fd, "???");
769     }
770     PUTS(fd, " in ");
771 
772     if (code != NULL && code->co_name != NULL
773        && PyUnicode_Check(code->co_name)) {
774         _Py_DumpASCII(fd, code->co_name);
775     }
776     else {
777         PUTS(fd, "???");
778     }
779 
780     PUTS(fd, "\n");
781 }
782 
783 static void
dump_traceback(int fd,PyThreadState * tstate,int write_header)784 dump_traceback(int fd, PyThreadState *tstate, int write_header)
785 {
786     PyFrameObject *frame;
787     unsigned int depth;
788 
789     if (write_header)
790         PUTS(fd, "Stack (most recent call first):\n");
791 
792     frame = _PyThreadState_GetFrame(tstate);
793     if (frame == NULL)
794         return;
795 
796     depth = 0;
797     while (frame != NULL) {
798         if (MAX_FRAME_DEPTH <= depth) {
799             PUTS(fd, "  ...\n");
800             break;
801         }
802         if (!PyFrame_Check(frame))
803             break;
804         dump_frame(fd, frame);
805         frame = frame->f_back;
806         depth++;
807     }
808 }
809 
810 /* Dump the traceback of a Python thread into fd. Use write() to write the
811    traceback and retry if write() is interrupted by a signal (failed with
812    EINTR), but don't call the Python signal handler.
813 
814    The caller is responsible to call PyErr_CheckSignals() to call Python signal
815    handlers if signals were received. */
816 void
_Py_DumpTraceback(int fd,PyThreadState * tstate)817 _Py_DumpTraceback(int fd, PyThreadState *tstate)
818 {
819     dump_traceback(fd, tstate, 1);
820 }
821 
822 /* Write the thread identifier into the file 'fd': "Current thread 0xHHHH:\" if
823    is_current is true, "Thread 0xHHHH:\n" otherwise.
824 
825    This function is signal safe. */
826 
827 static void
write_thread_id(int fd,PyThreadState * tstate,int is_current)828 write_thread_id(int fd, PyThreadState *tstate, int is_current)
829 {
830     if (is_current)
831         PUTS(fd, "Current thread 0x");
832     else
833         PUTS(fd, "Thread 0x");
834     _Py_DumpHexadecimal(fd,
835                         tstate->thread_id,
836                         sizeof(unsigned long) * 2);
837     PUTS(fd, " (most recent call first):\n");
838 }
839 
840 /* Dump the traceback of all Python threads into fd. Use write() to write the
841    traceback and retry if write() is interrupted by a signal (failed with
842    EINTR), but don't call the Python signal handler.
843 
844    The caller is responsible to call PyErr_CheckSignals() to call Python signal
845    handlers if signals were received. */
846 const char*
_Py_DumpTracebackThreads(int fd,PyInterpreterState * interp,PyThreadState * current_tstate)847 _Py_DumpTracebackThreads(int fd, PyInterpreterState *interp,
848                          PyThreadState *current_tstate)
849 {
850     PyThreadState *tstate;
851     unsigned int nthreads;
852 
853     if (current_tstate == NULL) {
854         /* _Py_DumpTracebackThreads() is called from signal handlers by
855            faulthandler.
856 
857            SIGSEGV, SIGFPE, SIGABRT, SIGBUS and SIGILL are synchronous signals
858            and are thus delivered to the thread that caused the fault. Get the
859            Python thread state of the current thread.
860 
861            PyThreadState_Get() doesn't give the state of the thread that caused
862            the fault if the thread released the GIL, and so this function
863            cannot be used. Read the thread specific storage (TSS) instead: call
864            PyGILState_GetThisThreadState(). */
865         current_tstate = PyGILState_GetThisThreadState();
866     }
867 
868     if (interp == NULL) {
869         if (current_tstate == NULL) {
870             interp = _PyGILState_GetInterpreterStateUnsafe();
871             if (interp == NULL) {
872                 /* We need the interpreter state to get Python threads */
873                 return "unable to get the interpreter state";
874             }
875         }
876         else {
877             interp = current_tstate->interp;
878         }
879     }
880     assert(interp != NULL);
881 
882     /* Get the current interpreter from the current thread */
883     tstate = PyInterpreterState_ThreadHead(interp);
884     if (tstate == NULL)
885         return "unable to get the thread head state";
886 
887     /* Dump the traceback of each thread */
888     tstate = PyInterpreterState_ThreadHead(interp);
889     nthreads = 0;
890     _Py_BEGIN_SUPPRESS_IPH
891     do
892     {
893         if (nthreads != 0)
894             PUTS(fd, "\n");
895         if (nthreads >= MAX_NTHREADS) {
896             PUTS(fd, "...\n");
897             break;
898         }
899         write_thread_id(fd, tstate, tstate == current_tstate);
900         dump_traceback(fd, tstate, 0);
901         tstate = PyThreadState_Next(tstate);
902         nthreads++;
903     } while (tstate != NULL);
904     _Py_END_SUPPRESS_IPH
905 
906     return NULL;
907 }
908 
909