Coverage Report

Created: 2026-08-28 06:28

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/cpython3/Python/traceback.c
Line
Count
Source
1
2
/* Traceback implementation */
3
4
#include "Python.h"
5
#include "pycore_call.h"          // _PyObject_CallMethodFormat()
6
#include "pycore_fileutils.h"     // _Py_BEGIN_SUPPRESS_IPH
7
#include "pycore_frame.h"         // PyFrameObject
8
#include "pycore_interp.h"        // PyInterpreterState.gc
9
#include "pycore_interpframe.h"   // _PyFrame_GetCode()
10
#include "pycore_pyerrors.h"      // _PyErr_GetRaisedException()
11
#include "pycore_pystate.h"       // _PyThreadState_GET()
12
#include "pycore_traceback.h"     // EXCEPTION_TB_HEADER
13
14
#include "frameobject.h"          // PyFrame_New()
15
16
#include "osdefs.h"               // SEP
17
#ifdef HAVE_UNISTD_H
18
#  include <unistd.h>             // lseek()
19
#endif
20
21
#if (defined(HAVE_EXECINFO_H) && defined(HAVE_DLFCN_H) && defined(HAVE_LINK_H))
22
#  define _PY_HAS_BACKTRACE_HEADERS 1
23
#endif
24
25
#if (defined(__APPLE__) && defined(HAVE_EXECINFO_H) && defined(HAVE_DLFCN_H))
26
#  define _PY_HAS_BACKTRACE_HEADERS 1
27
#endif
28
29
#ifdef _PY_HAS_BACKTRACE_HEADERS
30
#  include <execinfo.h>           // backtrace(), backtrace_symbols()
31
#  include <dlfcn.h>              // dladdr1()
32
#ifdef HAVE_LINK_H
33
#    include <link.h>               // struct DL_info
34
#endif
35
#  if defined(__APPLE__) && defined(HAVE_BACKTRACE) && defined(HAVE_DLADDR)
36
#    define CAN_C_BACKTRACE
37
#  elif defined(HAVE_BACKTRACE) && defined(HAVE_DLADDR1)
38
#    define CAN_C_BACKTRACE
39
#  endif
40
#endif
41
42
#if defined(__STDC_NO_VLA__) && (__STDC_NO_VLA__ == 1)
43
/* Use alloca() for VLAs. */
44
#  define VLA(type, name, size) type *name = alloca(sizeof(type) * (size))
45
#elif !defined(__STDC_NO_VLA__) || (__STDC_NO_VLA__ == 0)
46
/* Use actual C VLAs.*/
47
0
#  define VLA(type, name, size) type name[size]
48
#elif defined(CAN_C_BACKTRACE)
49
/* VLAs are not possible. Disable C stack trace functions. */
50
#  undef CAN_C_BACKTRACE
51
#endif
52
53
#define OFF(x) offsetof(PyTracebackObject, x)
54
0
#define PUTS(fd, str) (void)_Py_write_noraise(fd, str, strlen(str))
55
56
0
#define MAX_STRING_LENGTH 500
57
0
#define MAX_FRAME_DEPTH 100
58
0
#define DEFAULT_MAX_NTHREADS 100
59
60
/* Function from Parser/tokenizer/file_tokenizer.c */
61
extern char* _PyTokenizer_FindEncodingFilename(int, PyObject *);
62
63
/*[clinic input]
64
class traceback "PyTracebackObject *" "&PyTraceback_Type"
65
[clinic start generated code]*/
66
/*[clinic end generated code: output=da39a3ee5e6b4b0d input=cf96294b2bebc811]*/
67
68
3.44M
#define _PyTracebackObject_CAST(op)   ((PyTracebackObject *)(op))
69
70
#include "clinic/traceback.c.h"
71
72
73
#ifdef MS_WINDOWS
74
typedef HRESULT (WINAPI *PF_GET_THREAD_DESCRIPTION)(HANDLE, PWSTR*);
75
static PF_GET_THREAD_DESCRIPTION pGetThreadDescription = NULL;
76
#endif
77
78
79
static PyObject *
80
tb_create_raw(PyTracebackObject *next, PyFrameObject *frame, int lasti,
81
              int lineno)
82
3.44M
{
83
3.44M
    PyTracebackObject *tb;
84
3.44M
    if ((next != NULL && !PyTraceBack_Check(next)) ||
85
3.44M
                    frame == NULL || !PyFrame_Check(frame)) {
86
0
        PyErr_BadInternalCall();
87
0
        return NULL;
88
0
    }
89
3.44M
    tb = PyObject_GC_New(PyTracebackObject, &PyTraceBack_Type);
90
3.44M
    if (tb != NULL) {
91
3.44M
        tb->tb_next = (PyTracebackObject*)Py_XNewRef(next);
92
3.44M
        tb->tb_frame = (PyFrameObject*)Py_XNewRef(frame);
93
3.44M
        tb->tb_lasti = lasti;
94
3.44M
        tb->tb_lineno = lineno;
95
3.44M
        PyObject_GC_Track(tb);
96
3.44M
    }
97
3.44M
    return (PyObject *)tb;
98
3.44M
}
99
100
/*[clinic input]
101
@classmethod
102
traceback.__new__ as tb_new
103
104
  tb_next: object
105
  tb_frame: object(type='PyFrameObject *', subclass_of='&PyFrame_Type')
106
  tb_lasti: int
107
  tb_lineno: int
108
109
Create a new traceback object.
110
[clinic start generated code]*/
111
112
static PyObject *
113
tb_new_impl(PyTypeObject *type, PyObject *tb_next, PyFrameObject *tb_frame,
114
            int tb_lasti, int tb_lineno)
115
/*[clinic end generated code: output=fa077debd72d861a input=b88143145454cb59]*/
116
0
{
117
0
    if (tb_next == Py_None) {
118
0
        tb_next = NULL;
119
0
    } else if (!PyTraceBack_Check(tb_next)) {
120
0
        return PyErr_Format(PyExc_TypeError,
121
0
                            "expected traceback object or None, got '%s'",
122
0
                            Py_TYPE(tb_next)->tp_name);
123
0
    }
124
125
0
    return tb_create_raw((PyTracebackObject *)tb_next, tb_frame, tb_lasti,
126
0
                         tb_lineno);
127
0
}
128
129
static PyObject *
130
tb_dir(PyObject *Py_UNUSED(self), PyObject *Py_UNUSED(ignored))
131
0
{
132
0
    return Py_BuildValue("[ssss]", "tb_frame", "tb_next",
133
0
                                   "tb_lasti", "tb_lineno");
134
0
}
135
136
/*[clinic input]
137
@critical_section
138
@getter
139
traceback.tb_next
140
[clinic start generated code]*/
141
142
static PyObject *
143
traceback_tb_next_get_impl(PyTracebackObject *self)
144
/*[clinic end generated code: output=963634df7d5fc837 input=8f6345f2b73cb965]*/
145
0
{
146
0
    PyObject* ret = (PyObject*)self->tb_next;
147
0
    if (!ret) {
148
0
        ret = Py_None;
149
0
    }
150
0
    return Py_NewRef(ret);
151
0
}
152
153
static int
154
tb_get_lineno(PyObject *op)
155
0
{
156
0
    PyTracebackObject *tb = _PyTracebackObject_CAST(op);
157
0
    _PyInterpreterFrame* frame = tb->tb_frame->f_frame;
158
0
    assert(frame != NULL);
159
0
    return PyCode_Addr2Line(_PyFrame_GetCode(frame), tb->tb_lasti);
160
0
}
161
162
static PyObject *
163
tb_lineno_get(PyObject *op, void *Py_UNUSED(_))
164
0
{
165
0
    PyTracebackObject *self = _PyTracebackObject_CAST(op);
166
0
    int lineno = self->tb_lineno;
167
0
    if (lineno == -1) {
168
0
        lineno = tb_get_lineno(op);
169
0
        if (lineno < 0) {
170
0
            Py_RETURN_NONE;
171
0
        }
172
0
    }
173
0
    return PyLong_FromLong(lineno);
174
0
}
175
176
/*[clinic input]
177
@critical_section
178
@setter
179
@deleter
180
traceback.tb_next
181
[clinic start generated code]*/
182
183
static int
184
traceback_tb_next_set_impl(PyTracebackObject *self, PyObject *value)
185
/*[clinic end generated code: output=d4868cbc48f2adac input=936201ff689c5700]*/
186
0
{
187
0
    if (!value) {
188
0
        PyErr_Format(PyExc_TypeError, "can't delete tb_next attribute");
189
0
        return -1;
190
0
    }
191
192
    /* We accept None or a traceback object, and map None -> NULL (inverse of
193
       tb_next_get) */
194
0
    if (value == Py_None) {
195
0
        value = NULL;
196
0
    } else if (!PyTraceBack_Check(value)) {
197
0
        PyErr_Format(PyExc_TypeError,
198
0
                     "expected traceback object, got '%s'",
199
0
                     Py_TYPE(value)->tp_name);
200
0
        return -1;
201
0
    }
202
203
    /* Check for loops */
204
0
    PyTracebackObject *cursor = (PyTracebackObject *)value;
205
0
    Py_XINCREF(cursor);
206
0
    while (cursor) {
207
0
        if (cursor == self) {
208
0
            PyErr_Format(PyExc_ValueError, "traceback loop detected");
209
0
            Py_DECREF(cursor);
210
0
            return -1;
211
0
        }
212
0
        Py_BEGIN_CRITICAL_SECTION(cursor);
213
0
        Py_XINCREF(cursor->tb_next);
214
0
        Py_SETREF(cursor, cursor->tb_next);
215
0
        Py_END_CRITICAL_SECTION();
216
0
    }
217
218
0
    Py_XSETREF(self->tb_next, (PyTracebackObject *)Py_XNewRef(value));
219
220
0
    return 0;
221
0
}
222
223
224
static PyMethodDef tb_methods[] = {
225
   {"__dir__", tb_dir, METH_NOARGS, NULL},
226
   {NULL, NULL, 0, NULL},
227
};
228
229
static PyMemberDef tb_memberlist[] = {
230
    {"tb_frame",        _Py_T_OBJECT,       OFF(tb_frame),  Py_READONLY|Py_AUDIT_READ},
231
    {"tb_lasti",        Py_T_INT,          OFF(tb_lasti),  Py_READONLY},
232
    {NULL}      /* Sentinel */
233
};
234
235
static PyGetSetDef tb_getsetters[] = {
236
    TRACEBACK_TB_NEXT_GETSETDEF
237
    {"tb_lineno", tb_lineno_get, NULL, NULL, NULL},
238
    {NULL}      /* Sentinel */
239
};
240
241
static void
242
tb_dealloc(PyObject *op)
243
3.44M
{
244
3.44M
    PyTracebackObject *tb = _PyTracebackObject_CAST(op);
245
3.44M
    PyObject_GC_UnTrack(tb);
246
3.44M
    Py_XDECREF(tb->tb_next);
247
3.44M
    Py_XDECREF(tb->tb_frame);
248
3.44M
    PyObject_GC_Del(tb);
249
3.44M
}
250
251
static int
252
tb_traverse(PyObject *op, visitproc visit, void *arg)
253
20
{
254
20
    PyTracebackObject *tb = _PyTracebackObject_CAST(op);
255
20
    Py_VISIT(tb->tb_next);
256
20
    Py_VISIT(tb->tb_frame);
257
20
    return 0;
258
20
}
259
260
static int
261
tb_clear(PyObject *op)
262
0
{
263
0
    PyTracebackObject *tb = _PyTracebackObject_CAST(op);
264
0
    Py_CLEAR(tb->tb_next);
265
0
    Py_CLEAR(tb->tb_frame);
266
0
    return 0;
267
0
}
268
269
PyTypeObject PyTraceBack_Type = {
270
    PyVarObject_HEAD_INIT(&PyType_Type, 0)
271
    "traceback",
272
    sizeof(PyTracebackObject),
273
    0,
274
    tb_dealloc,         /*tp_dealloc*/
275
    0,                  /*tp_vectorcall_offset*/
276
    0,    /*tp_getattr*/
277
    0,                  /*tp_setattr*/
278
    0,                  /*tp_as_async*/
279
    0,                  /*tp_repr*/
280
    0,                  /*tp_as_number*/
281
    0,                  /*tp_as_sequence*/
282
    0,                  /*tp_as_mapping*/
283
    0,                  /* tp_hash */
284
    0,                  /* tp_call */
285
    0,                  /* tp_str */
286
    PyObject_GenericGetAttr,                    /* tp_getattro */
287
    0,                  /* tp_setattro */
288
    0,                                          /* tp_as_buffer */
289
    Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,/* tp_flags */
290
    tb_new__doc__,                              /* tp_doc */
291
    tb_traverse,                                /* tp_traverse */
292
    tb_clear,                                   /* tp_clear */
293
    0,                                          /* tp_richcompare */
294
    0,                                          /* tp_weaklistoffset */
295
    0,                                          /* tp_iter */
296
    0,                                          /* tp_iternext */
297
    tb_methods,         /* tp_methods */
298
    tb_memberlist,      /* tp_members */
299
    tb_getsetters,                              /* tp_getset */
300
    0,                                          /* tp_base */
301
    0,                                          /* tp_dict */
302
    0,                                          /* tp_descr_get */
303
    0,                                          /* tp_descr_set */
304
    0,                                          /* tp_dictoffset */
305
    0,                                          /* tp_init */
306
    0,                                          /* tp_alloc */
307
    tb_new,                                     /* tp_new */
308
};
309
310
311
PyObject*
312
_PyTraceBack_FromFrame(PyObject *tb_next, PyFrameObject *frame)
313
3.44M
{
314
3.44M
    assert(tb_next == NULL || PyTraceBack_Check(tb_next));
315
3.44M
    assert(frame != NULL);
316
3.44M
    int addr = _PyInterpreterFrame_LASTI(frame->f_frame) * sizeof(_Py_CODEUNIT);
317
3.44M
    return tb_create_raw((PyTracebackObject *)tb_next, frame, addr, -1);
318
3.44M
}
319
320
321
int
322
PyTraceBack_Here(PyFrameObject *frame)
323
3.44M
{
324
3.44M
    PyObject *exc = PyErr_GetRaisedException();
325
3.44M
    assert(PyExceptionInstance_Check(exc));
326
3.44M
    PyObject *tb = PyException_GetTraceback(exc);
327
3.44M
    PyObject *newtb = _PyTraceBack_FromFrame(tb, frame);
328
3.44M
    Py_XDECREF(tb);
329
3.44M
    if (newtb == NULL) {
330
0
        _PyErr_ChainExceptions1(exc);
331
0
        return -1;
332
0
    }
333
3.44M
    PyException_SetTraceback(exc, newtb);
334
3.44M
    Py_XDECREF(newtb);
335
3.44M
    PyErr_SetRaisedException(exc);
336
3.44M
    return 0;
337
3.44M
}
338
339
/* Insert a frame into the traceback for (funcname, filename, lineno). */
340
void _PyTraceback_Add(const char *funcname, const char *filename, int lineno)
341
0
{
342
0
    PyObject *globals;
343
0
    PyCodeObject *code;
344
0
    PyFrameObject *frame;
345
0
    PyThreadState *tstate = _PyThreadState_GET();
346
347
    /* Save and clear the current exception. Python functions must not be
348
       called with an exception set. Calling Python functions happens when
349
       the codec of the filesystem encoding is implemented in pure Python. */
350
0
    PyObject *exc = _PyErr_GetRaisedException(tstate);
351
352
0
    globals = PyDict_New();
353
0
    if (!globals)
354
0
        goto error;
355
0
    code = PyCode_NewEmpty(filename, funcname, lineno);
356
0
    if (!code) {
357
0
        Py_DECREF(globals);
358
0
        goto error;
359
0
    }
360
0
    frame = PyFrame_New(tstate, code, globals, NULL);
361
0
    Py_DECREF(globals);
362
0
    Py_DECREF(code);
363
0
    if (!frame)
364
0
        goto error;
365
0
    frame->f_lineno = lineno;
366
367
0
    _PyErr_SetRaisedException(tstate, exc);
368
0
    PyTraceBack_Here(frame);
369
0
    Py_DECREF(frame);
370
0
    return;
371
372
0
error:
373
0
    _PyErr_ChainExceptions1(exc);
374
0
}
375
376
static PyObject *
377
_Py_FindSourceFile(PyObject *filename, char* namebuf, size_t namelen, PyObject *io)
378
0
{
379
0
    Py_ssize_t i;
380
0
    PyObject *binary;
381
0
    PyObject *v;
382
0
    Py_ssize_t npath;
383
0
    size_t taillen;
384
0
    PyObject *syspath;
385
0
    PyObject *path;
386
0
    const char* tail;
387
0
    PyObject *filebytes;
388
0
    const char* filepath;
389
0
    Py_ssize_t len;
390
0
    PyObject* result;
391
0
    PyObject *open = NULL;
392
393
0
    filebytes = PyUnicode_EncodeFSDefault(filename);
394
0
    if (filebytes == NULL) {
395
0
        PyErr_Clear();
396
0
        return NULL;
397
0
    }
398
0
    filepath = PyBytes_AS_STRING(filebytes);
399
400
    /* Search tail of filename in sys.path before giving up */
401
0
    tail = strrchr(filepath, SEP);
402
0
    if (tail == NULL)
403
0
        tail = filepath;
404
0
    else
405
0
        tail++;
406
0
    taillen = strlen(tail);
407
408
0
    PyThreadState *tstate = _PyThreadState_GET();
409
0
    if (PySys_GetOptionalAttr(&_Py_ID(path), &syspath) < 0) {
410
0
        PyErr_Clear();
411
0
        goto error;
412
0
    }
413
0
    if (syspath == NULL || !PyList_Check(syspath)) {
414
0
        goto error;
415
0
    }
416
0
    npath = PyList_Size(syspath);
417
418
0
    open = PyObject_GetAttr(io, &_Py_ID(open));
419
0
    if (open == NULL) {
420
0
        goto error;
421
0
    }
422
0
    for (i = 0; i < npath; i++) {
423
0
        v = PyList_GetItem(syspath, i);
424
0
        if (v == NULL) {
425
0
            PyErr_Clear();
426
0
            break;
427
0
        }
428
0
        if (!PyUnicode_Check(v))
429
0
            continue;
430
0
        path = PyUnicode_EncodeFSDefault(v);
431
0
        if (path == NULL) {
432
0
            PyErr_Clear();
433
0
            continue;
434
0
        }
435
0
        len = PyBytes_GET_SIZE(path);
436
0
        if (len + 1 + (Py_ssize_t)taillen >= (Py_ssize_t)namelen - 1) {
437
0
            Py_DECREF(path);
438
0
            continue; /* Too long */
439
0
        }
440
0
        strcpy(namebuf, PyBytes_AS_STRING(path));
441
0
        Py_DECREF(path);
442
0
        if (strlen(namebuf) != (size_t)len)
443
0
            continue; /* v contains '\0' */
444
0
        if (len > 0 && namebuf[len-1] != SEP)
445
0
            namebuf[len++] = SEP;
446
0
        strcpy(namebuf+len, tail);
447
448
0
        binary = _PyObject_CallMethodFormat(tstate, open, "ss", namebuf, "rb");
449
0
        if (binary != NULL) {
450
0
            result = binary;
451
0
            goto finally;
452
0
        }
453
0
        PyErr_Clear();
454
0
    }
455
0
    goto error;
456
457
0
error:
458
0
    result = NULL;
459
0
finally:
460
0
    Py_XDECREF(open);
461
0
    Py_XDECREF(syspath);
462
0
    Py_DECREF(filebytes);
463
0
    return result;
464
0
}
465
466
/* Writes indent spaces. Returns 0 on success and non-zero on failure.
467
 */
468
int
469
_Py_WriteIndent(int indent, PyObject *f)
470
0
{
471
0
    char buf[11] = "          ";
472
0
    assert(strlen(buf) == 10);
473
0
    while (indent > 0) {
474
0
        if (indent < 10) {
475
0
            buf[indent] = '\0';
476
0
        }
477
0
        if (PyFile_WriteString(buf, f) < 0) {
478
0
            return -1;
479
0
        }
480
0
        indent -= 10;
481
0
    }
482
0
    return 0;
483
0
}
484
485
static int
486
display_source_line(PyObject *f, PyObject *filename, int lineno, int indent,
487
                    int *truncation, PyObject **line)
488
0
{
489
0
    int fd;
490
0
    int i;
491
0
    char *found_encoding;
492
0
    const char *encoding;
493
0
    PyObject *io;
494
0
    PyObject *binary;
495
0
    PyObject *fob = NULL;
496
0
    PyObject *lineobj = NULL;
497
0
    PyObject *res;
498
0
    char buf[MAXPATHLEN+1];
499
0
    int kind;
500
0
    const void *data;
501
502
    /* open the file */
503
0
    if (filename == NULL)
504
0
        return 0;
505
506
    /* Do not attempt to open things like <string> or <stdin> */
507
0
    assert(PyUnicode_Check(filename));
508
0
    if (PyUnicode_READ_CHAR(filename, 0) == '<') {
509
0
        Py_ssize_t len = PyUnicode_GET_LENGTH(filename);
510
0
        if (len > 0 && PyUnicode_READ_CHAR(filename, len - 1) == '>') {
511
0
            return 0;
512
0
        }
513
0
    }
514
515
0
    io = PyImport_ImportModule("io");
516
0
    if (io == NULL) {
517
0
        return -1;
518
0
    }
519
520
0
    binary = _PyObject_CallMethod(io, &_Py_ID(open), "Os", filename, "rb");
521
0
    if (binary == NULL) {
522
0
        PyErr_Clear();
523
524
0
        binary = _Py_FindSourceFile(filename, buf, sizeof(buf), io);
525
0
        if (binary == NULL) {
526
0
            Py_DECREF(io);
527
0
            return -1;
528
0
        }
529
0
    }
530
531
    /* use the right encoding to decode the file as unicode */
532
0
    fd = PyObject_AsFileDescriptor(binary);
533
0
    if (fd < 0) {
534
0
        Py_DECREF(io);
535
0
        Py_DECREF(binary);
536
0
        return 0;
537
0
    }
538
0
    found_encoding = _PyTokenizer_FindEncodingFilename(fd, filename);
539
0
    if (found_encoding == NULL)
540
0
        PyErr_Clear();
541
0
    encoding = (found_encoding != NULL) ? found_encoding : "utf-8";
542
    /* Reset position */
543
0
    if (lseek(fd, 0, SEEK_SET) == (off_t)-1) {
544
0
        Py_DECREF(io);
545
0
        Py_DECREF(binary);
546
0
        PyMem_Free(found_encoding);
547
0
        return 0;
548
0
    }
549
0
    fob = _PyObject_CallMethod(io, &_Py_ID(TextIOWrapper),
550
0
                               "Os", binary, encoding);
551
0
    Py_DECREF(io);
552
0
    PyMem_Free(found_encoding);
553
554
0
    if (fob == NULL) {
555
0
        PyErr_Clear();
556
557
0
        res = PyObject_CallMethodNoArgs(binary, &_Py_ID(close));
558
0
        Py_DECREF(binary);
559
0
        if (res)
560
0
            Py_DECREF(res);
561
0
        else
562
0
            PyErr_Clear();
563
0
        return 0;
564
0
    }
565
0
    Py_DECREF(binary);
566
567
    /* get the line number lineno */
568
0
    for (i = 0; i < lineno; i++) {
569
0
        Py_XDECREF(lineobj);
570
0
        lineobj = PyFile_GetLine(fob, -1);
571
0
        if (!lineobj) {
572
0
            PyErr_Clear();
573
0
            break;
574
0
        }
575
0
    }
576
0
    res = PyObject_CallMethodNoArgs(fob, &_Py_ID(close));
577
0
    if (res) {
578
0
        Py_DECREF(res);
579
0
    }
580
0
    else {
581
0
        PyErr_Clear();
582
0
    }
583
0
    Py_DECREF(fob);
584
0
    if (!lineobj || !PyUnicode_Check(lineobj)) {
585
0
        Py_XDECREF(lineobj);
586
0
        return -1;
587
0
    }
588
589
0
    if (line) {
590
0
        *line = Py_NewRef(lineobj);
591
0
    }
592
593
    /* remove the indentation of the line */
594
0
    kind = PyUnicode_KIND(lineobj);
595
0
    data = PyUnicode_DATA(lineobj);
596
0
    for (i=0; i < PyUnicode_GET_LENGTH(lineobj); i++) {
597
0
        Py_UCS4 ch = PyUnicode_READ(kind, data, i);
598
0
        if (ch != ' ' && ch != '\t' && ch != '\014')
599
0
            break;
600
0
    }
601
0
    if (i) {
602
0
        PyObject *truncated;
603
0
        truncated = PyUnicode_Substring(lineobj, i, PyUnicode_GET_LENGTH(lineobj));
604
0
        if (truncated) {
605
0
            Py_SETREF(lineobj, truncated);
606
0
        } else {
607
0
            PyErr_Clear();
608
0
        }
609
0
    }
610
611
0
    if (truncation != NULL) {
612
0
        *truncation = i - indent;
613
0
    }
614
615
    /* Write some spaces before the line */
616
0
    if (_Py_WriteIndent(indent, f) < 0) {
617
0
        goto error;
618
0
    }
619
620
    /* finally display the line */
621
0
    if (PyFile_WriteObject(lineobj, f, Py_PRINT_RAW) < 0) {
622
0
        goto error;
623
0
    }
624
625
0
    if (PyFile_WriteString("\n", f) < 0) {
626
0
        goto error;
627
0
    }
628
629
0
    Py_DECREF(lineobj);
630
0
    return 0;
631
0
error:
632
0
    Py_DECREF(lineobj);
633
0
    return -1;
634
0
}
635
636
int
637
_Py_DisplaySourceLine(PyObject *f, PyObject *filename, int lineno, int indent,
638
                      int *truncation, PyObject **line)
639
0
{
640
0
    return display_source_line(f, filename, lineno, indent, truncation, line);
641
0
}
642
643
644
#define IS_WHITESPACE(c) (((c) == ' ') || ((c) == '\t') || ((c) == '\f'))
645
0
#define _TRACEBACK_SOURCE_LINE_INDENT 4
646
647
static inline int
648
0
ignore_source_errors(void) {
649
0
    if (PyErr_Occurred()) {
650
0
        if (PyErr_ExceptionMatches(PyExc_KeyboardInterrupt)) {
651
0
            return -1;
652
0
        }
653
0
        PyErr_Clear();
654
0
    }
655
0
    return 0;
656
0
}
657
658
static int
659
tb_displayline(PyTracebackObject* tb, PyObject *f, PyObject *filename, int lineno,
660
               PyFrameObject *frame, PyObject *name)
661
0
{
662
0
    if (filename == NULL || name == NULL) {
663
0
        return -1;
664
0
    }
665
666
0
    PyObject *line = PyUnicode_FromFormat("  File \"%U\", line %d, in %U\n",
667
0
                                          filename, lineno, name);
668
0
    if (line == NULL) {
669
0
        return -1;
670
0
    }
671
672
0
    int res = PyFile_WriteObject(line, f, Py_PRINT_RAW);
673
0
    Py_DECREF(line);
674
0
    if (res < 0) {
675
0
        return -1;
676
0
    }
677
678
0
    int err = 0;
679
680
0
    int truncation = _TRACEBACK_SOURCE_LINE_INDENT;
681
0
    PyObject* source_line = NULL;
682
0
    int rc = display_source_line(
683
0
            f, filename, lineno, _TRACEBACK_SOURCE_LINE_INDENT,
684
0
            &truncation, &source_line);
685
0
    if (rc != 0 || !source_line) {
686
        /* ignore errors since we can't report them, can we? */
687
0
        err = ignore_source_errors();
688
0
    }
689
0
    Py_XDECREF(source_line);
690
0
    return err;
691
0
}
692
693
static const int TB_RECURSIVE_CUTOFF = 3; // Also hardcoded in traceback.py.
694
695
static int
696
tb_print_line_repeated(PyObject *f, long cnt)
697
0
{
698
0
    cnt -= TB_RECURSIVE_CUTOFF;
699
0
    PyObject *line = PyUnicode_FromFormat(
700
0
        (cnt > 1)
701
0
          ? "  [Previous line repeated %ld more times]\n"
702
0
          : "  [Previous line repeated %ld more time]\n",
703
0
        cnt);
704
0
    if (line == NULL) {
705
0
        return -1;
706
0
    }
707
0
    int err = PyFile_WriteObject(line, f, Py_PRINT_RAW);
708
0
    Py_DECREF(line);
709
0
    return err;
710
0
}
711
712
static int
713
tb_printinternal(PyTracebackObject *tb, PyObject *f, long limit)
714
0
{
715
0
    PyCodeObject *code = NULL;
716
0
    Py_ssize_t depth = 0;
717
0
    PyObject *last_file = NULL;
718
0
    int last_line = -1;
719
0
    PyObject *last_name = NULL;
720
0
    long cnt = 0;
721
0
    PyTracebackObject *tb1 = tb;
722
0
    while (tb1 != NULL) {
723
0
        depth++;
724
0
        tb1 = tb1->tb_next;
725
0
    }
726
0
    while (tb != NULL && depth > limit) {
727
0
        depth--;
728
0
        tb = tb->tb_next;
729
0
    }
730
0
    while (tb != NULL) {
731
0
        code = PyFrame_GetCode(tb->tb_frame);
732
0
        int tb_lineno = tb->tb_lineno;
733
0
        if (tb_lineno == -1) {
734
0
            tb_lineno = tb_get_lineno((PyObject *)tb);
735
0
        }
736
0
        if (last_file == NULL ||
737
0
            code->co_filename != last_file ||
738
0
            last_line == -1 || tb_lineno != last_line ||
739
0
            last_name == NULL || code->co_name != last_name) {
740
0
            if (cnt > TB_RECURSIVE_CUTOFF) {
741
0
                if (tb_print_line_repeated(f, cnt) < 0) {
742
0
                    goto error;
743
0
                }
744
0
            }
745
0
            last_file = code->co_filename;
746
0
            last_line = tb_lineno;
747
0
            last_name = code->co_name;
748
0
            cnt = 0;
749
0
        }
750
0
        cnt++;
751
0
        if (cnt <= TB_RECURSIVE_CUTOFF) {
752
0
            if (tb_displayline(tb, f, code->co_filename, tb_lineno,
753
0
                               tb->tb_frame, code->co_name) < 0) {
754
0
                goto error;
755
0
            }
756
757
0
            if (PyErr_CheckSignals() < 0) {
758
0
                goto error;
759
0
            }
760
0
        }
761
0
        Py_CLEAR(code);
762
0
        tb = tb->tb_next;
763
0
    }
764
0
    if (cnt > TB_RECURSIVE_CUTOFF) {
765
0
        if (tb_print_line_repeated(f, cnt) < 0) {
766
0
            goto error;
767
0
        }
768
0
    }
769
0
    return 0;
770
0
error:
771
0
    Py_XDECREF(code);
772
0
    return -1;
773
0
}
774
775
0
#define PyTraceBack_LIMIT 1000
776
777
int
778
_PyTraceBack_Print(PyObject *v, const char *header, PyObject *f)
779
0
{
780
0
    PyObject *limitv;
781
0
    long limit = PyTraceBack_LIMIT;
782
783
0
    if (v == NULL) {
784
0
        return 0;
785
0
    }
786
0
    if (!PyTraceBack_Check(v)) {
787
0
        PyErr_BadInternalCall();
788
0
        return -1;
789
0
    }
790
0
    if (PySys_GetOptionalAttrString("tracebacklimit", &limitv) < 0) {
791
0
        return -1;
792
0
    }
793
0
    else if (limitv != NULL && PyLong_Check(limitv)) {
794
0
        int overflow;
795
0
        limit = PyLong_AsLongAndOverflow(limitv, &overflow);
796
0
        if (overflow > 0) {
797
0
            limit = LONG_MAX;
798
0
        }
799
0
        else if (limit <= 0) {
800
0
            Py_DECREF(limitv);
801
0
            return 0;
802
0
        }
803
0
    }
804
0
    Py_XDECREF(limitv);
805
806
0
    if (PyFile_WriteString(header, f) < 0) {
807
0
        return -1;
808
0
    }
809
810
0
    if (tb_printinternal((PyTracebackObject *)v, f, limit) < 0) {
811
0
        return -1;
812
0
    }
813
814
0
    return 0;
815
0
}
816
817
int
818
PyTraceBack_Print(PyObject *v, PyObject *f)
819
0
{
820
0
    const char *header = EXCEPTION_TB_HEADER;
821
0
    return _PyTraceBack_Print(v, header, f);
822
0
}
823
824
/* Format an integer in range [0; 0xffffffff] to decimal and write it
825
   into the file fd.
826
827
   This function is signal safe. */
828
829
void
830
_Py_DumpDecimal(int fd, size_t value)
831
0
{
832
    /* maximum number of characters required for output of %lld or %p.
833
       We need at most ceil(log10(256)*SIZEOF_LONG_LONG) digits,
834
       plus 1 for the null byte.  53/22 is an upper bound for log10(256). */
835
0
    char buffer[1 + (sizeof(size_t)*53-1) / 22 + 1];
836
0
    char *ptr, *end;
837
838
0
    end = &buffer[Py_ARRAY_LENGTH(buffer) - 1];
839
0
    ptr = end;
840
0
    *ptr = '\0';
841
0
    do {
842
0
        --ptr;
843
0
        assert(ptr >= buffer);
844
0
        *ptr = '0' + (value % 10);
845
0
        value /= 10;
846
0
    } while (value);
847
848
0
    (void)_Py_write_noraise(fd, ptr, end - ptr);
849
0
}
850
851
/* Format an integer as hexadecimal with width digits into fd file descriptor.
852
   The function is signal safe. */
853
static void
854
dump_hexadecimal(int fd, uintptr_t value, Py_ssize_t width, int strip_zeros)
855
0
{
856
0
    char buffer[sizeof(uintptr_t) * 2 + 1], *ptr, *end;
857
0
    Py_ssize_t size = Py_ARRAY_LENGTH(buffer) - 1;
858
859
0
    if (width > size)
860
0
        width = size;
861
    /* it's ok if width is negative */
862
863
0
    end = &buffer[size];
864
0
    ptr = end;
865
0
    *ptr = '\0';
866
0
    do {
867
0
        --ptr;
868
0
        assert(ptr >= buffer);
869
0
        *ptr = Py_hexdigits[value & 15];
870
0
        value >>= 4;
871
0
    } while ((end - ptr) < width || value);
872
873
0
    size = end - ptr;
874
0
    if (strip_zeros) {
875
0
        while (*ptr == '0' && size >= 2) {
876
0
            ptr++;
877
0
            size--;
878
0
        }
879
0
    }
880
881
0
    (void)_Py_write_noraise(fd, ptr, size);
882
0
}
883
884
void
885
_Py_DumpHexadecimal(int fd, uintptr_t value, Py_ssize_t width)
886
0
{
887
0
    dump_hexadecimal(fd, value, width, 0);
888
0
}
889
890
#ifdef CAN_C_BACKTRACE
891
static void
892
dump_pointer(int fd, void *ptr)
893
0
{
894
0
    PUTS(fd, "0x");
895
0
    dump_hexadecimal(fd, (uintptr_t)ptr, sizeof(void*), 1);
896
0
}
897
#endif
898
899
static void
900
dump_char(int fd, char ch)
901
0
{
902
0
    char buf[1] = {ch};
903
0
    (void)_Py_write_noraise(fd, buf, 1);
904
0
}
905
906
void
907
_Py_DumpASCII(int fd, PyObject *text)
908
0
{
909
0
    PyASCIIObject *ascii = _PyASCIIObject_CAST(text);
910
0
    Py_ssize_t i, size;
911
0
    int truncated;
912
0
    int kind;
913
0
    void *data = NULL;
914
0
    Py_UCS4 ch;
915
916
0
    if (!PyUnicode_Check(text))
917
0
        return;
918
919
0
    size = ascii->length;
920
0
    kind = ascii->state.kind;
921
0
    if (ascii->state.compact) {
922
0
        if (ascii->state.ascii)
923
0
            data = ascii + 1;
924
0
        else
925
0
            data = _PyCompactUnicodeObject_CAST(text) + 1;
926
0
    }
927
0
    else {
928
0
        data = _PyUnicodeObject_CAST(text)->data.any;
929
0
        if (data == NULL)
930
0
            return;
931
0
    }
932
933
0
    if (MAX_STRING_LENGTH < size) {
934
0
        size = MAX_STRING_LENGTH;
935
0
        truncated = 1;
936
0
    }
937
0
    else {
938
0
        truncated = 0;
939
0
    }
940
941
    // Is an ASCII string?
942
0
    if (ascii->state.ascii) {
943
0
        assert(kind == PyUnicode_1BYTE_KIND);
944
0
        char *str = data;
945
946
0
        int need_escape = 0;
947
0
        for (i=0; i < size; i++) {
948
0
            ch = str[i];
949
0
            if (!(' ' <= ch && ch <= 126)) {
950
0
                need_escape = 1;
951
0
                break;
952
0
            }
953
0
        }
954
0
        if (!need_escape) {
955
            // The string can be written with a single write() syscall
956
0
            (void)_Py_write_noraise(fd, str, size);
957
0
            goto done;
958
0
        }
959
0
    }
960
961
0
    for (i=0; i < size; i++) {
962
0
        ch = PyUnicode_READ(kind, data, i);
963
0
        if (' ' <= ch && ch <= 126) {
964
            /* printable ASCII character */
965
0
            dump_char(fd, (char)ch);
966
0
        }
967
0
        else if (ch <= 0xff) {
968
0
            PUTS(fd, "\\x");
969
0
            _Py_DumpHexadecimal(fd, ch, 2);
970
0
        }
971
0
        else if (ch <= 0xffff) {
972
0
            PUTS(fd, "\\u");
973
0
            _Py_DumpHexadecimal(fd, ch, 4);
974
0
        }
975
0
        else {
976
0
            PUTS(fd, "\\U");
977
0
            _Py_DumpHexadecimal(fd, ch, 8);
978
0
        }
979
0
    }
980
981
0
done:
982
0
    if (truncated) {
983
0
        PUTS(fd, "...");
984
0
    }
985
0
}
986
987
988
#ifdef MS_WINDOWS
989
static void
990
_Py_DumpWideString(int fd, wchar_t *str)
991
{
992
    Py_ssize_t size = wcslen(str);
993
    int truncated;
994
    if (MAX_STRING_LENGTH < size) {
995
        size = MAX_STRING_LENGTH;
996
        truncated = 1;
997
    }
998
    else {
999
        truncated = 0;
1000
    }
1001
1002
    for (Py_ssize_t i=0; i < size; i++) {
1003
        Py_UCS4 ch = str[i];
1004
        if (' ' <= ch && ch <= 126) {
1005
            /* printable ASCII character */
1006
            dump_char(fd, (char)ch);
1007
        }
1008
        else if (ch <= 0xff) {
1009
            PUTS(fd, "\\x");
1010
            _Py_DumpHexadecimal(fd, ch, 2);
1011
        }
1012
        else if (Py_UNICODE_IS_HIGH_SURROGATE(ch)
1013
                 && Py_UNICODE_IS_LOW_SURROGATE(str[i+1])) {
1014
            ch = Py_UNICODE_JOIN_SURROGATES(ch, str[i+1]);
1015
            i++;  // Skip the low surrogate character
1016
            PUTS(fd, "\\U");
1017
            _Py_DumpHexadecimal(fd, ch, 8);
1018
        }
1019
        else {
1020
            Py_BUILD_ASSERT(sizeof(wchar_t) == 2);
1021
            PUTS(fd, "\\u");
1022
            _Py_DumpHexadecimal(fd, ch, 4);
1023
        }
1024
    }
1025
1026
    if (truncated) {
1027
        PUTS(fd, "...");
1028
    }
1029
}
1030
#endif
1031
1032
1033
/* Write a frame into the file fd: "File "xxx", line xxx in xxx".
1034
1035
   This function is signal safe.
1036
1037
   Return 0 on success. Return -1 if the frame is invalid. */
1038
1039
static int _Py_NO_SANITIZE_THREAD
1040
dump_frame(int fd, _PyInterpreterFrame *frame)
1041
0
{
1042
0
    if (frame->owner == FRAME_OWNED_BY_INTERPRETER) {
1043
        /* Ignore trampoline frames and base frame sentinel */
1044
0
        return 0;
1045
0
    }
1046
1047
0
    PyCodeObject *code = _PyFrame_SafeGetCode(frame);
1048
0
    if (code == NULL) {
1049
0
        return -1;
1050
0
    }
1051
1052
0
    int res = 0;
1053
0
    PUTS(fd, "  File ");
1054
0
    if (code->co_filename != NULL
1055
0
        && PyUnicode_Check(code->co_filename))
1056
0
    {
1057
0
        PUTS(fd, "\"");
1058
0
        _Py_DumpASCII(fd, code->co_filename);
1059
0
        PUTS(fd, "\"");
1060
0
    }
1061
0
    else {
1062
0
        PUTS(fd, "???");
1063
0
        res = -1;
1064
0
    }
1065
1066
0
    PUTS(fd, ", line ");
1067
0
    int lasti = _PyFrame_SafeGetLasti(frame);
1068
0
    int lineno = -1;
1069
0
    if (lasti >= 0) {
1070
0
        lineno = _PyCode_SafeAddr2Line(code, lasti);
1071
0
    }
1072
0
    if (lineno >= 0) {
1073
0
        _Py_DumpDecimal(fd, (size_t)lineno);
1074
0
    }
1075
0
    else {
1076
0
        PUTS(fd, "???");
1077
0
        res = -1;
1078
0
    }
1079
1080
0
    PUTS(fd, " in ");
1081
0
    if (code->co_name != NULL && PyUnicode_Check(code->co_name)) {
1082
0
        _Py_DumpASCII(fd, code->co_name);
1083
0
    }
1084
0
    else {
1085
0
        PUTS(fd, "???");
1086
0
        res = -1;
1087
0
    }
1088
0
    PUTS(fd, "\n");
1089
0
    return res;
1090
0
}
1091
1092
static int _Py_NO_SANITIZE_THREAD
1093
tstate_is_freed(PyThreadState *tstate)
1094
0
{
1095
0
    if (_PyMem_IsPtrFreed(tstate)) {
1096
0
        return 1;
1097
0
    }
1098
0
    if (_PyMem_IsPtrFreed(tstate->interp)) {
1099
0
        return 1;
1100
0
    }
1101
0
    if (_PyMem_IsULongFreed(tstate->thread_id)) {
1102
0
        return 1;
1103
0
    }
1104
0
    return 0;
1105
0
}
1106
1107
1108
static int _Py_NO_SANITIZE_THREAD
1109
interp_is_freed(PyInterpreterState *interp)
1110
0
{
1111
0
    return _PyMem_IsPtrFreed(interp);
1112
0
}
1113
1114
1115
static void _Py_NO_SANITIZE_THREAD
1116
dump_traceback(int fd, PyThreadState *tstate, int write_header)
1117
0
{
1118
0
    if (write_header) {
1119
0
        PUTS(fd, "Stack (most recent call first):\n");
1120
0
    }
1121
1122
0
    if (tstate_is_freed(tstate)) {
1123
0
        PUTS(fd, "  <freed thread state>\n");
1124
0
        return;
1125
0
    }
1126
1127
0
    _PyInterpreterFrame *frame = tstate->current_frame;
1128
0
    if (frame == NULL) {
1129
0
        PUTS(fd, "  <no Python frame>\n");
1130
0
        return;
1131
0
    }
1132
1133
0
    unsigned int depth = 0;
1134
0
    while (1) {
1135
0
        if (MAX_FRAME_DEPTH <= depth) {
1136
0
            if (MAX_FRAME_DEPTH < depth) {
1137
0
                PUTS(fd, "plus ");
1138
0
                _Py_DumpDecimal(fd, depth);
1139
0
                PUTS(fd, " frames\n");
1140
0
            }
1141
0
            break;
1142
0
        }
1143
1144
0
        if (_PyMem_IsPtrFreed(frame)) {
1145
0
            PUTS(fd, "  <freed frame>\n");
1146
0
            break;
1147
0
        }
1148
        // Read frame->previous early since memory can be freed during
1149
        // dump_frame()
1150
0
        _PyInterpreterFrame *previous = frame->previous;
1151
1152
0
        if (dump_frame(fd, frame) < 0) {
1153
0
            PUTS(fd, "  <invalid frame>\n");
1154
0
            break;
1155
0
        }
1156
1157
0
        frame = previous;
1158
0
        if (frame == NULL) {
1159
0
            break;
1160
0
        }
1161
0
        depth++;
1162
0
    }
1163
0
}
1164
1165
/* Dump the traceback of a Python thread into fd. Use write() to write the
1166
   traceback and retry if write() is interrupted by a signal (failed with
1167
   EINTR), but don't call the Python signal handler.
1168
1169
   The caller is responsible to call PyErr_CheckSignals() to call Python signal
1170
   handlers if signals were received. */
1171
const char*
1172
PyUnstable_DumpTraceback(int fd, PyThreadState *tstate)
1173
0
{
1174
0
    dump_traceback(fd, tstate, 1);
1175
0
    return NULL;
1176
0
}
1177
1178
#if defined(HAVE_PTHREAD_GETNAME_NP) || defined(HAVE_PTHREAD_GET_NAME_NP)
1179
# if defined(__OpenBSD__)
1180
    /* pthread_*_np functions, especially pthread_{get,set}_name_np().
1181
       pthread_np.h exists on both OpenBSD and FreeBSD but the latter declares
1182
       pthread_getname_np() and pthread_setname_np() in pthread.h as long as
1183
       __BSD_VISIBLE remains set.
1184
     */
1185
#   include <pthread_np.h>
1186
# endif
1187
#endif
1188
1189
1190
// Write the thread name
1191
static void _Py_NO_SANITIZE_THREAD
1192
write_thread_name(int fd, PyThreadState *tstate)
1193
0
{
1194
0
#ifndef MS_WINDOWS
1195
0
#if defined(HAVE_PTHREAD_GETNAME_NP) || defined(HAVE_PTHREAD_GET_NAME_NP)
1196
0
    char name[100];
1197
0
    pthread_t thread = (pthread_t)tstate->thread_id;
1198
0
#ifdef HAVE_PTHREAD_GETNAME_NP
1199
0
    int rc = pthread_getname_np(thread, name, Py_ARRAY_LENGTH(name));
1200
#else /* defined(HAVE_PTHREAD_GET_NAME_NP) */
1201
    int rc = 0; /* pthread_get_name_np() returns void */
1202
    pthread_get_name_np(thread, name, Py_ARRAY_LENGTH(name));
1203
#endif
1204
0
    if (!rc) {
1205
0
        size_t len = strlen(name);
1206
0
        if (len) {
1207
0
            PUTS(fd, " [");
1208
0
            (void)_Py_write_noraise(fd, name, len);
1209
0
            PUTS(fd, "]");
1210
0
        }
1211
0
    }
1212
0
#endif
1213
#else
1214
    // Windows implementation
1215
    if (pGetThreadDescription == NULL) {
1216
        return;
1217
    }
1218
1219
    HANDLE thread = OpenThread(THREAD_QUERY_LIMITED_INFORMATION, FALSE, tstate->thread_id);
1220
    if (thread == NULL) {
1221
        return;
1222
    }
1223
1224
    wchar_t *name;
1225
    HRESULT hr = pGetThreadDescription(thread, &name);
1226
    if (!FAILED(hr)) {
1227
        if (name[0] != 0) {
1228
            PUTS(fd, " [");
1229
            _Py_DumpWideString(fd, name);
1230
            PUTS(fd, "]");
1231
        }
1232
        LocalFree(name);
1233
    }
1234
    CloseHandle(thread);
1235
#endif
1236
0
}
1237
1238
1239
/* Write the thread identifier into the file 'fd': "Current thread 0xHHHH:\" if
1240
   is_current is true, "Thread 0xHHHH:\n" otherwise.
1241
1242
   This function is signal safe (except on Windows). */
1243
1244
static void _Py_NO_SANITIZE_THREAD
1245
write_thread_id(int fd, PyThreadState *tstate, int is_current)
1246
0
{
1247
0
    if (is_current)
1248
0
        PUTS(fd, "Current thread 0x");
1249
0
    else
1250
0
        PUTS(fd, "Thread 0x");
1251
0
    _Py_DumpHexadecimal(fd,
1252
0
                        tstate->thread_id,
1253
0
                        sizeof(unsigned long) * 2);
1254
1255
0
    if (!_PyMem_IsULongFreed(tstate->thread_id)) {
1256
0
        write_thread_name(fd, tstate);
1257
0
    }
1258
1259
0
    PUTS(fd, " (most recent call first):\n");
1260
0
}
1261
1262
/* Dump the traceback of all Python threads into fd. Use write() to write the
1263
   traceback and retry if write() is interrupted by a signal (failed with
1264
   EINTR), but don't call the Python signal handler.
1265
1266
   The caller is responsible to call PyErr_CheckSignals() to call Python signal
1267
   handlers if signals were received. */
1268
const char* _Py_NO_SANITIZE_THREAD
1269
PyUnstable_DumpTracebackThreads(int fd, PyInterpreterState *interp,
1270
                                PyThreadState *current_tstate,
1271
                                Py_ssize_t max_threads)
1272
0
{
1273
0
    if (max_threads == 0) {
1274
0
        max_threads = DEFAULT_MAX_NTHREADS;
1275
0
    }
1276
1277
0
    if (current_tstate == NULL) {
1278
        /* PyUnstable_DumpTracebackThreads() is called from signal handlers by
1279
           faulthandler.
1280
1281
           SIGSEGV, SIGFPE, SIGABRT, SIGBUS and SIGILL are synchronous signals
1282
           and are thus delivered to the thread that caused the fault. Get the
1283
           Python thread state of the current thread.
1284
1285
           PyThreadState_Get() doesn't give the state of the thread that caused
1286
           the fault if the thread released the GIL, and so
1287
           _PyThreadState_GET() cannot be used. Read the thread specific
1288
           storage (TSS) instead: call PyGILState_GetThisThreadState(). */
1289
0
        current_tstate = PyGILState_GetThisThreadState();
1290
0
    }
1291
1292
0
    if (current_tstate != NULL && tstate_is_freed(current_tstate)) {
1293
0
        return "tstate is freed";
1294
0
    }
1295
1296
0
    if (interp == NULL) {
1297
0
        if (current_tstate == NULL) {
1298
0
            interp = _PyGILState_GetInterpreterStateUnsafe();
1299
0
            if (interp == NULL) {
1300
                /* We need the interpreter state to get Python threads */
1301
0
                return "unable to get the interpreter state";
1302
0
            }
1303
0
        }
1304
0
        else {
1305
0
            interp = current_tstate->interp;
1306
0
        }
1307
0
    }
1308
0
    assert(interp != NULL);
1309
1310
0
    if (interp_is_freed(interp)) {
1311
0
        return "interp is freed";
1312
0
    }
1313
1314
    /* Get the current interpreter from the current thread */
1315
0
    PyThreadState *tstate = PyInterpreterState_ThreadHead(interp);
1316
0
    if (tstate == NULL)
1317
0
        return "unable to get the thread head state";
1318
1319
    /* Dump the traceback of each thread */
1320
0
    Py_ssize_t nthreads = 0;
1321
0
    _Py_BEGIN_SUPPRESS_IPH
1322
0
    do
1323
0
    {
1324
0
        if (nthreads != 0)
1325
0
            PUTS(fd, "\n");
1326
0
        if (nthreads >= max_threads) {
1327
0
            PUTS(fd, "...\n");
1328
0
            break;
1329
0
        }
1330
1331
0
        if (tstate_is_freed(tstate)) {
1332
0
            PUTS(fd, "<freed thread state>\n");
1333
0
            break;
1334
0
        }
1335
1336
0
        write_thread_id(fd, tstate, tstate == current_tstate);
1337
0
        if (tstate == current_tstate && tstate->interp->gc.collecting) {
1338
0
            PUTS(fd, "  Garbage-collecting\n");
1339
0
        }
1340
0
        dump_traceback(fd, tstate, 0);
1341
1342
0
        tstate = tstate->next;
1343
0
        nthreads++;
1344
0
    } while (tstate != NULL);
1345
0
    _Py_END_SUPPRESS_IPH
1346
1347
0
    return NULL;
1348
0
}
1349
1350
#ifdef CAN_C_BACKTRACE
1351
/* Based on glibc's implementation of backtrace_symbols(), but only uses stack memory. */
1352
void
1353
_Py_backtrace_symbols_fd(int fd, void *const *array, Py_ssize_t size)
1354
0
{
1355
0
    VLA(Dl_info, info, size);
1356
0
    VLA(int, status, size);
1357
    /* Fill in the information we can get from dladdr() */
1358
0
    for (Py_ssize_t i = 0; i < size; ++i) {
1359
#ifdef __APPLE__
1360
        status[i] = dladdr(array[i], &info[i]);
1361
#else
1362
0
        struct link_map *map;
1363
0
        status[i] = dladdr1(array[i], &info[i], (void **)&map, RTLD_DL_LINKMAP);
1364
0
        if (status[i] != 0
1365
0
            && info[i].dli_fname != NULL
1366
0
            && info[i].dli_fname[0] != '\0') {
1367
            /* The load bias is more useful to the user than the load
1368
               address. The use of these addresses is to calculate an
1369
               address in the ELF file, so its prelinked bias is not
1370
               something we want to subtract out */
1371
0
            info[i].dli_fbase = (void *) map->l_addr;
1372
0
        }
1373
0
#endif
1374
0
    }
1375
0
    for (Py_ssize_t i = 0; i < size; ++i) {
1376
0
        if (status[i] == 0
1377
0
            || info[i].dli_fname == NULL
1378
0
            || info[i].dli_fname[0] == '\0'
1379
0
        ) {
1380
0
            PUTS(fd, "  Binary file '<unknown>' [");
1381
0
            dump_pointer(fd, array[i]);
1382
0
            PUTS(fd, "]\n");
1383
0
            continue;
1384
0
        }
1385
1386
0
        if (info[i].dli_sname == NULL) {
1387
            /* We found no symbol name to use, so describe it as
1388
               relative to the file. */
1389
0
            info[i].dli_saddr = info[i].dli_fbase;
1390
0
        }
1391
1392
0
        if (info[i].dli_sname == NULL && info[i].dli_saddr == 0) {
1393
0
            PUTS(fd, "  Binary file \"");
1394
0
            PUTS(fd, info[i].dli_fname);
1395
0
            PUTS(fd, "\" [");
1396
0
            dump_pointer(fd, array[i]);
1397
0
            PUTS(fd, "]\n");
1398
0
        }
1399
0
        else {
1400
0
            char sign;
1401
0
            ptrdiff_t offset;
1402
0
            if (array[i] >= (void *) info[i].dli_saddr) {
1403
0
                sign = '+';
1404
0
                offset = array[i] - info[i].dli_saddr;
1405
0
            }
1406
0
            else {
1407
0
                sign = '-';
1408
0
                offset = info[i].dli_saddr - array[i];
1409
0
            }
1410
0
            const char *symbol_name = info[i].dli_sname != NULL ? info[i].dli_sname : "";
1411
0
            PUTS(fd, "  Binary file \"");
1412
0
            PUTS(fd, info[i].dli_fname);
1413
0
            PUTS(fd, "\", at ");
1414
0
            PUTS(fd, symbol_name);
1415
0
            dump_char(fd, sign);
1416
0
            PUTS(fd, "0x");
1417
0
            dump_hexadecimal(fd, offset, sizeof(offset), 1);
1418
0
            PUTS(fd, " [");
1419
0
            dump_pointer(fd, array[i]);
1420
0
            PUTS(fd, "]\n");
1421
0
        }
1422
0
    }
1423
0
}
1424
1425
void
1426
_Py_DumpStack(int fd)
1427
0
{
1428
0
#define BACKTRACE_SIZE 32
1429
0
    PUTS(fd, "Current thread's C stack trace (most recent call first):\n");
1430
0
    VLA(void *, callstack, BACKTRACE_SIZE);
1431
0
    int frames = backtrace(callstack, BACKTRACE_SIZE);
1432
0
    if (frames == 0) {
1433
        // Some systems won't return anything for the stack trace
1434
0
        PUTS(fd, "  <system returned no stack trace>\n");
1435
0
        return;
1436
0
    }
1437
1438
0
    _Py_backtrace_symbols_fd(fd, callstack, frames);
1439
0
    if (frames == BACKTRACE_SIZE) {
1440
0
        PUTS(fd, "  <truncated rest of calls>\n");
1441
0
    }
1442
1443
0
#undef BACKTRACE_SIZE
1444
0
}
1445
#else
1446
void
1447
_Py_DumpStack(int fd)
1448
{
1449
    PUTS(fd, "Current thread's C stack trace (most recent call first):\n");
1450
    PUTS(fd, "  <cannot get C stack on this system>\n");
1451
}
1452
#endif
1453
1454
void
1455
_Py_InitDumpStack(void)
1456
0
{
1457
0
#ifdef CAN_C_BACKTRACE
1458
    // gh-137185: Call backtrace() once to force libgcc to be loaded early.
1459
0
    void *callstack[1];
1460
0
    (void)backtrace(callstack, 1);
1461
0
#endif
1462
0
}
1463
1464
1465
void
1466
_Py_DumpTraceback_Init(void)
1467
21
{
1468
#ifdef MS_WINDOWS
1469
    if (pGetThreadDescription != NULL) {
1470
        return;
1471
    }
1472
1473
    HMODULE kernelbase = GetModuleHandleW(L"kernelbase.dll");
1474
    if (kernelbase != NULL) {
1475
        pGetThreadDescription = (PF_GET_THREAD_DESCRIPTION)GetProcAddress(
1476
                                    kernelbase, "GetThreadDescription");
1477
    }
1478
#endif
1479
21
}