mirror of
https://github.com/python/cpython.git
synced 2025-09-04 16:01:10 +00:00
bpo-34588: Fix an off-by-one error in traceback formatting. (GH-9077)
The recursive frame pruning code always undercounted the number of elided frames by one. That is, in the "[Previous line repeated N more times]" message, N would always be one too few. Near the recursive pruning cutoff, one frame could be silently dropped. That situation is demonstrated in the OP of the bug report. The fix is to start the identical frame counter at 1.
This commit is contained in:
parent
54752533b2
commit
d545869d08
4 changed files with 96 additions and 26 deletions
|
@ -511,16 +511,21 @@ tb_displayline(PyObject *f, PyObject *filename, int lineno, PyObject *name)
|
|||
return err;
|
||||
}
|
||||
|
||||
static const int TB_RECURSIVE_CUTOFF = 3; // Also hardcoded in traceback.py.
|
||||
|
||||
static int
|
||||
tb_print_line_repeated(PyObject *f, long cnt)
|
||||
{
|
||||
int err;
|
||||
cnt -= TB_RECURSIVE_CUTOFF;
|
||||
PyObject *line = PyUnicode_FromFormat(
|
||||
" [Previous line repeated %ld more times]\n", cnt-3);
|
||||
(cnt > 1)
|
||||
? " [Previous line repeated %ld more times]\n"
|
||||
: " [Previous line repeated %ld more time]\n",
|
||||
cnt);
|
||||
if (line == NULL) {
|
||||
return -1;
|
||||
}
|
||||
err = PyFile_WriteObject(line, f, Py_PRINT_RAW);
|
||||
int err = PyFile_WriteObject(line, f, Py_PRINT_RAW);
|
||||
Py_DECREF(line);
|
||||
return err;
|
||||
}
|
||||
|
@ -544,15 +549,11 @@ tb_printinternal(PyTracebackObject *tb, PyObject *f, long limit)
|
|||
tb = tb->tb_next;
|
||||
}
|
||||
while (tb != NULL && err == 0) {
|
||||
if (last_file != NULL &&
|
||||
tb->tb_frame->f_code->co_filename == last_file &&
|
||||
last_line != -1 && tb->tb_lineno == last_line &&
|
||||
last_name != NULL && tb->tb_frame->f_code->co_name == last_name)
|
||||
{
|
||||
cnt++;
|
||||
}
|
||||
else {
|
||||
if (cnt > 3) {
|
||||
if (last_file == NULL ||
|
||||
tb->tb_frame->f_code->co_filename != last_file ||
|
||||
last_line == -1 || tb->tb_lineno != last_line ||
|
||||
last_name == NULL || tb->tb_frame->f_code->co_name != last_name) {
|
||||
if (cnt > TB_RECURSIVE_CUTOFF) {
|
||||
err = tb_print_line_repeated(f, cnt);
|
||||
}
|
||||
last_file = tb->tb_frame->f_code->co_filename;
|
||||
|
@ -560,7 +561,8 @@ tb_printinternal(PyTracebackObject *tb, PyObject *f, long limit)
|
|||
last_name = tb->tb_frame->f_code->co_name;
|
||||
cnt = 0;
|
||||
}
|
||||
if (err == 0 && cnt < 3) {
|
||||
cnt++;
|
||||
if (err == 0 && cnt <= TB_RECURSIVE_CUTOFF) {
|
||||
err = tb_displayline(f,
|
||||
tb->tb_frame->f_code->co_filename,
|
||||
tb->tb_lineno,
|
||||
|
@ -571,7 +573,7 @@ tb_printinternal(PyTracebackObject *tb, PyObject *f, long limit)
|
|||
}
|
||||
tb = tb->tb_next;
|
||||
}
|
||||
if (err == 0 && cnt > 3) {
|
||||
if (err == 0 && cnt > TB_RECURSIVE_CUTOFF) {
|
||||
err = tb_print_line_repeated(f, cnt);
|
||||
}
|
||||
return err;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue