bpo-40429: PyFrame_GetCode() result cannot be NULL (GH-19772)

Add frame_nslots() to factorize duplicate code.
This commit is contained in:
Victor Stinner 2020-04-29 00:56:58 +02:00 committed by GitHub
parent 521c8d6806
commit 6d86a2331e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 45 additions and 48 deletions

View File

@ -34,6 +34,7 @@ Reflection
.. c:function:: int PyFrame_GetCode(PyFrameObject *frame) .. c:function:: int PyFrame_GetCode(PyFrameObject *frame)
Return a borrowed reference to the *frame* code. Return a borrowed reference to the *frame* code.
The frame code cannot be ``NULL``.
*frame* must not be ``NULL``. *frame* must not be ``NULL``.

View File

@ -347,13 +347,6 @@ tracemalloc_get_frame(PyFrameObject *pyframe, frame_t *frame)
frame->lineno = (unsigned int)lineno; frame->lineno = (unsigned int)lineno;
code = PyFrame_GetCode(pyframe); code = PyFrame_GetCode(pyframe);
if (code == NULL) {
#ifdef TRACE_DEBUG
tracemalloc_error("failed to get the code object of the frame");
#endif
return;
}
if (code->co_filename == NULL) { if (code->co_filename == NULL) {
#ifdef TRACE_DEBUG #ifdef TRACE_DEBUG
tracemalloc_error("failed to get the filename of the code object"); tracemalloc_error("failed to get the filename of the code object");

View File

@ -665,12 +665,18 @@ frame_dealloc(PyFrameObject *f)
Py_TRASHCAN_SAFE_END(f) Py_TRASHCAN_SAFE_END(f)
} }
static inline Py_ssize_t
frame_nslots(PyFrameObject *frame)
{
PyCodeObject *code = frame->f_code;
return (code->co_nlocals
+ PyTuple_GET_SIZE(code->co_cellvars)
+ PyTuple_GET_SIZE(code->co_freevars));
}
static int static int
frame_traverse(PyFrameObject *f, visitproc visit, void *arg) frame_traverse(PyFrameObject *f, visitproc visit, void *arg)
{ {
PyObject **fastlocals, **p;
Py_ssize_t i, slots;
Py_VISIT(f->f_back); Py_VISIT(f->f_back);
Py_VISIT(f->f_code); Py_VISIT(f->f_code);
Py_VISIT(f->f_builtins); Py_VISIT(f->f_builtins);
@ -679,15 +685,16 @@ frame_traverse(PyFrameObject *f, visitproc visit, void *arg)
Py_VISIT(f->f_trace); Py_VISIT(f->f_trace);
/* locals */ /* locals */
slots = f->f_code->co_nlocals + PyTuple_GET_SIZE(f->f_code->co_cellvars) + PyTuple_GET_SIZE(f->f_code->co_freevars); PyObject **fastlocals = f->f_localsplus;
fastlocals = f->f_localsplus; for (Py_ssize_t i = frame_nslots(f); --i >= 0; ++fastlocals) {
for (i = slots; --i >= 0; ++fastlocals)
Py_VISIT(*fastlocals); Py_VISIT(*fastlocals);
}
/* stack */ /* stack */
if (f->f_stacktop != NULL) { if (f->f_stacktop != NULL) {
for (p = f->f_valuestack; p < f->f_stacktop; p++) for (PyObject **p = f->f_valuestack; p < f->f_stacktop; p++) {
Py_VISIT(*p); Py_VISIT(*p);
}
} }
return 0; return 0;
} }
@ -695,30 +702,28 @@ frame_traverse(PyFrameObject *f, visitproc visit, void *arg)
static int static int
frame_tp_clear(PyFrameObject *f) frame_tp_clear(PyFrameObject *f)
{ {
PyObject **fastlocals, **p, **oldtop;
Py_ssize_t i, slots;
/* Before anything else, make sure that this frame is clearly marked /* Before anything else, make sure that this frame is clearly marked
* as being defunct! Else, e.g., a generator reachable from this * as being defunct! Else, e.g., a generator reachable from this
* frame may also point to this frame, believe itself to still be * frame may also point to this frame, believe itself to still be
* active, and try cleaning up this frame again. * active, and try cleaning up this frame again.
*/ */
oldtop = f->f_stacktop; PyObject **oldtop = f->f_stacktop;
f->f_stacktop = NULL; f->f_stacktop = NULL;
f->f_executing = 0; f->f_executing = 0;
Py_CLEAR(f->f_trace); Py_CLEAR(f->f_trace);
/* locals */ /* locals */
slots = f->f_code->co_nlocals + PyTuple_GET_SIZE(f->f_code->co_cellvars) + PyTuple_GET_SIZE(f->f_code->co_freevars); PyObject **fastlocals = f->f_localsplus;
fastlocals = f->f_localsplus; for (Py_ssize_t i = frame_nslots(f); --i >= 0; ++fastlocals) {
for (i = slots; --i >= 0; ++fastlocals)
Py_CLEAR(*fastlocals); Py_CLEAR(*fastlocals);
}
/* stack */ /* stack */
if (oldtop != NULL) { if (oldtop != NULL) {
for (p = f->f_valuestack; p < oldtop; p++) for (PyObject **p = f->f_valuestack; p < oldtop; p++) {
Py_CLEAR(*p); Py_CLEAR(*p);
}
} }
return 0; return 0;
} }
@ -747,10 +752,10 @@ frame_sizeof(PyFrameObject *f, PyObject *Py_UNUSED(ignored))
{ {
Py_ssize_t res, extras, ncells, nfrees; Py_ssize_t res, extras, ncells, nfrees;
ncells = PyTuple_GET_SIZE(f->f_code->co_cellvars); PyCodeObject *code = f->f_code;
nfrees = PyTuple_GET_SIZE(f->f_code->co_freevars); ncells = PyTuple_GET_SIZE(code->co_cellvars);
extras = f->f_code->co_stacksize + f->f_code->co_nlocals + nfrees = PyTuple_GET_SIZE(code->co_freevars);
ncells + nfrees; extras = code->co_stacksize + code->co_nlocals + ncells + nfrees;
/* subtract one as it is already included in PyFrameObject */ /* subtract one as it is already included in PyFrameObject */
res = sizeof(PyFrameObject) + (extras-1) * sizeof(PyObject *); res = sizeof(PyFrameObject) + (extras-1) * sizeof(PyObject *);
@ -764,9 +769,10 @@ static PyObject *
frame_repr(PyFrameObject *f) frame_repr(PyFrameObject *f)
{ {
int lineno = PyFrame_GetLineNumber(f); int lineno = PyFrame_GetLineNumber(f);
PyCodeObject *code = f->f_code;
return PyUnicode_FromFormat( return PyUnicode_FromFormat(
"<frame at %p, file %R, line %d, code %S>", "<frame at %p, file %R, line %d, code %S>",
f, f->f_code->co_filename, lineno, f->f_code->co_name); f, code->co_filename, lineno, code->co_name);
} }
static PyMethodDef frame_methods[] = { static PyMethodDef frame_methods[] = {
@ -940,6 +946,8 @@ _PyFrame_New_NoTrack(PyThreadState *tstate, PyCodeObject *code,
f->f_trace_opcodes = 0; f->f_trace_opcodes = 0;
f->f_trace_lines = 1; f->f_trace_lines = 1;
assert(f->f_code != NULL);
return f; return f;
} }
@ -1227,5 +1235,7 @@ PyCodeObject *
PyFrame_GetCode(PyFrameObject *frame) PyFrame_GetCode(PyFrameObject *frame)
{ {
assert(frame != NULL); assert(frame != NULL);
return frame->f_code; PyCodeObject *code = frame->f_code;
assert(code != NULL);
return code;
} }

View File

@ -1117,11 +1117,11 @@ compute_cr_origin(int origin_depth)
} }
frame = PyEval_GetFrame(); frame = PyEval_GetFrame();
for (int i = 0; i < frame_count; ++i) { for (int i = 0; i < frame_count; ++i) {
PyObject *frameinfo = Py_BuildValue( PyCodeObject *code = frame->f_code;
"OiO", PyObject *frameinfo = Py_BuildValue("OiO",
frame->f_code->co_filename, code->co_filename,
PyFrame_GetLineNumber(frame), PyFrame_GetLineNumber(frame),
frame->f_code->co_name); code->co_name);
if (!frameinfo) { if (!frameinfo) {
Py_DECREF(cr_origin); Py_DECREF(cr_origin);
return NULL; return NULL;

View File

@ -8040,11 +8040,6 @@ super_init(PyObject *self, PyObject *args, PyObject *kwds)
return -1; return -1;
} }
co = PyFrame_GetCode(f); co = PyFrame_GetCode(f);
if (co == NULL) {
PyErr_SetString(PyExc_RuntimeError,
"super(): no code object");
return -1;
}
if (co->co_argcount == 0) { if (co->co_argcount == 0) {
PyErr_SetString(PyExc_RuntimeError, PyErr_SetString(PyExc_RuntimeError,
"super(): no arguments"); "super(): no arguments");

View File

@ -784,10 +784,6 @@ is_internal_frame(PyFrameObject *frame)
} }
PyCodeObject *code = PyFrame_GetCode(frame); PyCodeObject *code = PyFrame_GetCode(frame);
if (code == NULL) {
return 0;
}
PyObject *filename = code->co_filename; PyObject *filename = code->co_filename;
if (filename == NULL) { if (filename == NULL) {
return 0; return 0;

View File

@ -5580,9 +5580,10 @@ dtrace_function_entry(PyFrameObject *f)
const char *funcname; const char *funcname;
int lineno; int lineno;
filename = PyUnicode_AsUTF8(f->f_code->co_filename); PyCodeObject *code = f->f_code;
funcname = PyUnicode_AsUTF8(f->f_code->co_name); filename = PyUnicode_AsUTF8(code->co_filename);
lineno = PyCode_Addr2Line(f->f_code, f->f_lasti); funcname = PyUnicode_AsUTF8(code->co_name);
lineno = PyCode_Addr2Line(code, f->f_lasti);
PyDTrace_FUNCTION_ENTRY(filename, funcname, lineno); PyDTrace_FUNCTION_ENTRY(filename, funcname, lineno);
} }
@ -5594,9 +5595,10 @@ dtrace_function_return(PyFrameObject *f)
const char *funcname; const char *funcname;
int lineno; int lineno;
filename = PyUnicode_AsUTF8(f->f_code->co_filename); PyCodeObject *code = f->f_code;
funcname = PyUnicode_AsUTF8(f->f_code->co_name); filename = PyUnicode_AsUTF8(code->co_filename);
lineno = PyCode_Addr2Line(f->f_code, f->f_lasti); funcname = PyUnicode_AsUTF8(code->co_name);
lineno = PyCode_Addr2Line(code, f->f_lasti);
PyDTrace_FUNCTION_RETURN(filename, funcname, lineno); PyDTrace_FUNCTION_RETURN(filename, funcname, lineno);
} }