bpo-45635: standardize error handling in traceback.c (GH-29905)

Co-authored-by: Erlend Egeberg Aasland <erlend.aasland@innova.no>
This commit is contained in:
Irit Katriel 2021-12-07 16:17:22 +00:00 committed by GitHub
parent 8319114fee
commit d596acbd3b
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23

View file

@ -385,16 +385,14 @@ finally:
int int
_Py_WriteIndent(int indent, PyObject *f) _Py_WriteIndent(int indent, PyObject *f)
{ {
int err = 0;
char buf[11] = " "; char buf[11] = " ";
assert(strlen(buf) == 10); assert(strlen(buf) == 10);
while (indent > 0) { while (indent > 0) {
if (indent < 10) { if (indent < 10) {
buf[indent] = '\0'; buf[indent] = '\0';
} }
err = PyFile_WriteString(buf, f); if (PyFile_WriteString(buf, f) < 0) {
if (err != 0) { return -1;
return err;
} }
indent -= 10; indent -= 10;
} }
@ -407,11 +405,15 @@ _Py_WriteIndent(int indent, PyObject *f)
int int
_Py_WriteIndentedMargin(int indent, const char *margin, PyObject *f) _Py_WriteIndentedMargin(int indent, const char *margin, PyObject *f)
{ {
int err = _Py_WriteIndent(indent, f); if (_Py_WriteIndent(indent, f) < 0) {
if (err == 0 && margin) { return -1;
err = PyFile_WriteString(margin, f);
} }
return err; if (margin) {
if (PyFile_WriteString(margin, f) < 0) {
return -1;
}
}
return 0;
} }
static int static int
@ -419,7 +421,6 @@ display_source_line_with_margin(PyObject *f, PyObject *filename, int lineno, int
int margin_indent, const char *margin, int margin_indent, const char *margin,
int *truncation, PyObject **line) int *truncation, PyObject **line)
{ {
int err = 0;
int fd; int fd;
int i; int i;
char *found_encoding; char *found_encoding;
@ -502,19 +503,20 @@ display_source_line_with_margin(PyObject *f, PyObject *filename, int lineno, int
lineobj = PyFile_GetLine(fob, -1); lineobj = PyFile_GetLine(fob, -1);
if (!lineobj) { if (!lineobj) {
PyErr_Clear(); PyErr_Clear();
err = -1;
break; break;
} }
} }
res = _PyObject_CallMethodIdNoArgs(fob, &PyId_close); res = _PyObject_CallMethodIdNoArgs(fob, &PyId_close);
if (res) if (res) {
Py_DECREF(res); Py_DECREF(res);
else }
else {
PyErr_Clear(); PyErr_Clear();
}
Py_DECREF(fob); Py_DECREF(fob);
if (!lineobj || !PyUnicode_Check(lineobj)) { if (!lineobj || !PyUnicode_Check(lineobj)) {
Py_XDECREF(lineobj); Py_XDECREF(lineobj);
return err; return -1;
} }
if (line) { if (line) {
@ -545,23 +547,29 @@ display_source_line_with_margin(PyObject *f, PyObject *filename, int lineno, int
*truncation = i - indent; *truncation = i - indent;
} }
if (err == 0) { if (_Py_WriteIndentedMargin(margin_indent, margin, f) < 0) {
err = _Py_WriteIndentedMargin(margin_indent, margin, f); goto error;
} }
/* Write some spaces before the line */ /* Write some spaces before the line */
if (err == 0) { if (_Py_WriteIndent(indent, f) < 0) {
err = _Py_WriteIndent(indent, f); goto error;
} }
/* finally display the line */ /* finally display the line */
if (err == 0) { if (PyFile_WriteObject(lineobj, f, Py_PRINT_RAW) < 0) {
err = PyFile_WriteObject(lineobj, f, Py_PRINT_RAW); goto error;
} }
if (PyFile_WriteString("\n", f) < 0) {
goto error;
}
Py_DECREF(lineobj); Py_DECREF(lineobj);
if (err == 0) { return 0;
err = PyFile_WriteString("\n", f); error:
} Py_DECREF(lineobj);
return err; return -1;
} }
int int
@ -723,41 +731,51 @@ static inline int
print_error_location_carets(PyObject *f, int offset, Py_ssize_t start_offset, Py_ssize_t end_offset, print_error_location_carets(PyObject *f, int offset, Py_ssize_t start_offset, Py_ssize_t end_offset,
Py_ssize_t right_start_offset, Py_ssize_t left_end_offset, Py_ssize_t right_start_offset, Py_ssize_t left_end_offset,
const char *primary, const char *secondary) { const char *primary, const char *secondary) {
int err = 0;
int special_chars = (left_end_offset != -1 || right_start_offset != -1); int special_chars = (left_end_offset != -1 || right_start_offset != -1);
const char *str;
while (++offset <= end_offset) { while (++offset <= end_offset) {
if (offset <= start_offset || offset > end_offset) { if (offset <= start_offset || offset > end_offset) {
err = PyFile_WriteString(" ", f); str = " ";
} else if (special_chars && left_end_offset < offset && offset <= right_start_offset) { } else if (special_chars && left_end_offset < offset && offset <= right_start_offset) {
err = PyFile_WriteString(secondary, f); str = secondary;
} else { } else {
err = PyFile_WriteString(primary, f); str = primary;
}
if (PyFile_WriteString(str, f) < 0) {
return -1;
} }
} }
err = PyFile_WriteString("\n", f); if (PyFile_WriteString("\n", f) < 0) {
return err; return -1;
}
return 0;
} }
static int static int
tb_displayline(PyTracebackObject* tb, PyObject *f, PyObject *filename, int lineno, tb_displayline(PyTracebackObject* tb, PyObject *f, PyObject *filename, int lineno,
PyFrameObject *frame, PyObject *name, int margin_indent, const char *margin) PyFrameObject *frame, PyObject *name, int margin_indent, const char *margin)
{ {
int err; if (filename == NULL || name == NULL) {
PyObject *line;
if (filename == NULL || name == NULL)
return -1; return -1;
line = PyUnicode_FromFormat(" File \"%U\", line %d, in %U\n",
filename, lineno, name);
if (line == NULL)
return -1;
err = _Py_WriteIndentedMargin(margin_indent, margin, f);
if (err == 0) {
err = PyFile_WriteObject(line, f, Py_PRINT_RAW);
} }
if (_Py_WriteIndentedMargin(margin_indent, margin, f) < 0) {
return -1;
}
PyObject *line = PyUnicode_FromFormat(" File \"%U\", line %d, in %U\n",
filename, lineno, name);
if (line == NULL) {
return -1;
}
int res = PyFile_WriteObject(line, f, Py_PRINT_RAW);
Py_DECREF(line); Py_DECREF(line);
if (err != 0) if (res < 0) {
return err; return -1;
}
int err = 0;
int truncation = _TRACEBACK_SOURCE_LINE_INDENT; int truncation = _TRACEBACK_SOURCE_LINE_INDENT;
PyObject* source_line = NULL; PyObject* source_line = NULL;
@ -849,11 +867,16 @@ tb_displayline(PyTracebackObject* tb, PyObject *f, PyObject *filename, int linen
end_offset = i + 1; end_offset = i + 1;
} }
err = _Py_WriteIndentedMargin(margin_indent, margin, f); if (_Py_WriteIndentedMargin(margin_indent, margin, f) < 0) {
if (err == 0) { err = -1;
err = print_error_location_carets(f, truncation, start_offset, end_offset, goto done;
right_start_offset, left_end_offset, }
primary_error_char, secondary_error_char);
if (print_error_location_carets(f, truncation, start_offset, end_offset,
right_start_offset, left_end_offset,
primary_error_char, secondary_error_char) < 0) {
err = -1;
goto done;
} }
done: done:
@ -884,7 +907,7 @@ static int
tb_printinternal(PyTracebackObject *tb, PyObject *f, long limit, tb_printinternal(PyTracebackObject *tb, PyObject *f, long limit,
int indent, const char *margin) int indent, const char *margin)
{ {
int err = 0; PyCodeObject *code = NULL;
Py_ssize_t depth = 0; Py_ssize_t depth = 0;
PyObject *last_file = NULL; PyObject *last_file = NULL;
int last_line = -1; int last_line = -1;
@ -899,14 +922,16 @@ tb_printinternal(PyTracebackObject *tb, PyObject *f, long limit,
depth--; depth--;
tb = tb->tb_next; tb = tb->tb_next;
} }
while (tb != NULL && err == 0) { while (tb != NULL) {
PyCodeObject *code = PyFrame_GetCode(tb->tb_frame); code = PyFrame_GetCode(tb->tb_frame);
if (last_file == NULL || if (last_file == NULL ||
code->co_filename != last_file || code->co_filename != last_file ||
last_line == -1 || tb->tb_lineno != last_line || last_line == -1 || tb->tb_lineno != last_line ||
last_name == NULL || code->co_name != last_name) { last_name == NULL || code->co_name != last_name) {
if (cnt > TB_RECURSIVE_CUTOFF) { if (cnt > TB_RECURSIVE_CUTOFF) {
err = tb_print_line_repeated(f, cnt); if (tb_print_line_repeated(f, cnt) < 0) {
goto error;
}
} }
last_file = code->co_filename; last_file = code->co_filename;
last_line = tb->tb_lineno; last_line = tb->tb_lineno;
@ -914,20 +939,28 @@ tb_printinternal(PyTracebackObject *tb, PyObject *f, long limit,
cnt = 0; cnt = 0;
} }
cnt++; cnt++;
if (err == 0 && cnt <= TB_RECURSIVE_CUTOFF) { if (cnt <= TB_RECURSIVE_CUTOFF) {
err = tb_displayline(tb, f, code->co_filename, tb->tb_lineno, if (tb_displayline(tb, f, code->co_filename, tb->tb_lineno,
tb->tb_frame, code->co_name, indent, margin); tb->tb_frame, code->co_name, indent, margin) < 0) {
if (err == 0) { goto error;
err = PyErr_CheckSignals(); }
if (PyErr_CheckSignals() < 0) {
goto error;
} }
} }
Py_DECREF(code); Py_CLEAR(code);
tb = tb->tb_next; tb = tb->tb_next;
} }
if (err == 0 && cnt > TB_RECURSIVE_CUTOFF) { if (cnt > TB_RECURSIVE_CUTOFF) {
err = tb_print_line_repeated(f, cnt); if (tb_print_line_repeated(f, cnt) < 0) {
goto error;
}
} }
return err; return 0;
error:
Py_XDECREF(code);
return -1;
} }
#define PyTraceBack_LIMIT 1000 #define PyTraceBack_LIMIT 1000
@ -936,12 +969,12 @@ int
_PyTraceBack_Print_Indented(PyObject *v, int indent, const char *margin, _PyTraceBack_Print_Indented(PyObject *v, int indent, const char *margin,
const char *header_margin, const char *header, PyObject *f) const char *header_margin, const char *header, PyObject *f)
{ {
int err;
PyObject *limitv; PyObject *limitv;
long limit = PyTraceBack_LIMIT; long limit = PyTraceBack_LIMIT;
if (v == NULL) if (v == NULL) {
return 0; return 0;
}
if (!PyTraceBack_Check(v)) { if (!PyTraceBack_Check(v)) {
PyErr_BadInternalCall(); PyErr_BadInternalCall();
return -1; return -1;
@ -957,14 +990,19 @@ _PyTraceBack_Print_Indented(PyObject *v, int indent, const char *margin,
return 0; return 0;
} }
} }
err = _Py_WriteIndentedMargin(indent, header_margin, f); if (_Py_WriteIndentedMargin(indent, header_margin, f) < 0) {
if (err == 0) { return -1;
err = PyFile_WriteString(header, f);
} }
if (err == 0) {
err = tb_printinternal((PyTracebackObject *)v, f, limit, indent, margin); if (PyFile_WriteString(header, f) < 0) {
return -1;
} }
return err;
if (tb_printinternal((PyTracebackObject *)v, f, limit, indent, margin) < 0) {
return -1;
}
return 0;
} }
int int