Coverage Report

Created: 2026-02-26 06:53

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