diff options
author | Eric Snow <ericsnowcurrently@gmail.com> | 2021-05-26 19:15:40 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-05-26 19:15:40 (GMT) |
commit | 6cc800d3634fdd002b986c3ffe6a3d5540f311a0 (patch) | |
tree | c6e67a6f76549102011931f2ee929b455ab40918 /Objects | |
parent | e6c815d2e34be5fdf6dbe773f0781691746d2289 (diff) | |
download | cpython-6cc800d3634fdd002b986c3ffe6a3d5540f311a0.zip cpython-6cc800d3634fdd002b986c3ffe6a3d5540f311a0.tar.gz cpython-6cc800d3634fdd002b986c3ffe6a3d5540f311a0.tar.bz2 |
bpo-43693: Clean up the PyCodeObject fields. (GH-26364)
* Move up the comment about fields using in hashing/comparision.
* Group the fields more clearly.
* Add co_ncellvars and co_nfreevars.
* Raise ValueError if nlocals != len(varnames), rather than aborting.
Diffstat (limited to 'Objects')
-rw-r--r-- | Objects/codeobject.c | 51 | ||||
-rw-r--r-- | Objects/frameobject.c | 24 | ||||
-rw-r--r-- | Objects/funcobject.c | 14 | ||||
-rw-r--r-- | Objects/typeobject.c | 18 |
4 files changed, 50 insertions, 57 deletions
diff --git a/Objects/codeobject.c b/Objects/codeobject.c index 8b2cee2..65df3e3 100644 --- a/Objects/codeobject.c +++ b/Objects/codeobject.c @@ -164,7 +164,8 @@ PyCode_NewWithPosOnlyArgs(int argcount, int posonlyargcount, int kwonlyargcount, { PyCodeObject *co; Py_ssize_t *cell2arg = NULL; - Py_ssize_t i, n_cellvars, n_varnames, total_args; + Py_ssize_t i, total_args; + int ncellvars, nfreevars; /* Check argument types */ if (argcount < posonlyargcount || posonlyargcount < 0 || @@ -184,6 +185,19 @@ PyCode_NewWithPosOnlyArgs(int argcount, int posonlyargcount, int kwonlyargcount, return NULL; } + /* Make sure that code is indexable with an int, this is + a long running assumption in ceval.c and many parts of + the interpreter. */ + if (PyBytes_GET_SIZE(code) > INT_MAX) { + PyErr_SetString(PyExc_OverflowError, "co_code larger than INT_MAX"); + return NULL; + } + + if (nlocals != PyTuple_GET_SIZE(varnames)) { + PyErr_SetString(PyExc_ValueError, "co_nlocals != len(co_varnames)"); + return NULL; + } + /* Ensure that strings are ready Unicode string */ if (PyUnicode_READY(name) < 0) { return NULL; @@ -208,46 +222,40 @@ PyCode_NewWithPosOnlyArgs(int argcount, int posonlyargcount, int kwonlyargcount, return NULL; } - /* Make sure that code is indexable with an int, this is - a long running assumption in ceval.c and many parts of - the interpreter. */ - if (PyBytes_GET_SIZE(code) > INT_MAX) { - PyErr_SetString(PyExc_OverflowError, "co_code larger than INT_MAX"); - return NULL; - } - /* Check for any inner or outer closure references */ - n_cellvars = PyTuple_GET_SIZE(cellvars); - if (!n_cellvars && !PyTuple_GET_SIZE(freevars)) { + assert(PyTuple_GET_SIZE(cellvars) < INT_MAX); + ncellvars = (int)PyTuple_GET_SIZE(cellvars); + assert(PyTuple_GET_SIZE(freevars) < INT_MAX); + nfreevars = (int)PyTuple_GET_SIZE(freevars); + if (!ncellvars && !nfreevars) { flags |= CO_NOFREE; } else { flags &= ~CO_NOFREE; } - n_varnames = PyTuple_GET_SIZE(varnames); - if (argcount <= n_varnames && kwonlyargcount <= n_varnames) { + if (argcount <= nlocals && kwonlyargcount <= nlocals) { /* Never overflows. */ total_args = (Py_ssize_t)argcount + (Py_ssize_t)kwonlyargcount + ((flags & CO_VARARGS) != 0) + ((flags & CO_VARKEYWORDS) != 0); } else { - total_args = n_varnames + 1; + total_args = nlocals + 1; } - if (total_args > n_varnames) { + if (total_args > nlocals) { PyErr_SetString(PyExc_ValueError, "code: varnames is too small"); return NULL; } /* Create mapping between cells and arguments if needed. */ - if (n_cellvars) { + if (ncellvars) { bool used_cell2arg = false; - cell2arg = PyMem_NEW(Py_ssize_t, n_cellvars); + cell2arg = PyMem_NEW(Py_ssize_t, ncellvars); if (cell2arg == NULL) { PyErr_NoMemory(); return NULL; } /* Find cells which are also arguments. */ - for (i = 0; i < n_cellvars; i++) { + for (i = 0; i < ncellvars; i++) { Py_ssize_t j; PyObject *cell = PyTuple_GET_ITEM(cellvars, i); cell2arg[i] = CO_CELL_NOT_AN_ARG; @@ -279,9 +287,10 @@ PyCode_NewWithPosOnlyArgs(int argcount, int posonlyargcount, int kwonlyargcount, co->co_argcount = argcount; co->co_posonlyargcount = posonlyargcount; co->co_kwonlyargcount = kwonlyargcount; + co->co_nlocalsplus = nlocals + ncellvars + nfreevars; co->co_nlocals = nlocals; - co->co_nlocalsplus = nlocals + - (int)PyTuple_GET_SIZE(freevars) + (int)PyTuple_GET_SIZE(cellvars); + co->co_ncellvars = ncellvars; + co->co_nfreevars = nfreevars; co->co_stacksize = stacksize; co->co_flags = flags; Py_INCREF(code); @@ -1139,7 +1148,7 @@ code_sizeof(PyCodeObject *co, PyObject *Py_UNUSED(args)) _PyCodeObjectExtra *co_extra = (_PyCodeObjectExtra*) co->co_extra; if (co->co_cell2arg != NULL && co->co_cellvars != NULL) { - res += PyTuple_GET_SIZE(co->co_cellvars) * sizeof(Py_ssize_t); + res += co->co_ncellvars * sizeof(Py_ssize_t); } if (co_extra != NULL) { res += sizeof(_PyCodeObjectExtra) + diff --git a/Objects/frameobject.c b/Objects/frameobject.c index 87c4852..1bfae90 100644 --- a/Objects/frameobject.c +++ b/Objects/frameobject.c @@ -1023,7 +1023,6 @@ PyFrame_FastToLocalsWithError(PyFrameObject *f) PyObject **fast; PyCodeObject *co; Py_ssize_t j; - Py_ssize_t ncells, nfreevars; if (f == NULL) { PyErr_BadInternalCall(); @@ -1051,10 +1050,8 @@ PyFrame_FastToLocalsWithError(PyFrameObject *f) if (map_to_dict(map, j, locals, fast, 0) < 0) return -1; } - ncells = PyTuple_GET_SIZE(co->co_cellvars); - nfreevars = PyTuple_GET_SIZE(co->co_freevars); - if (ncells || nfreevars) { - if (map_to_dict(co->co_cellvars, ncells, + if (co->co_ncellvars || co->co_nfreevars) { + if (map_to_dict(co->co_cellvars, co->co_ncellvars, locals, fast + co->co_nlocals, 1)) return -1; @@ -1067,8 +1064,8 @@ PyFrame_FastToLocalsWithError(PyFrameObject *f) into the locals dict used by the class. */ if (co->co_flags & CO_OPTIMIZED) { - if (map_to_dict(co->co_freevars, nfreevars, - locals, fast + co->co_nlocals + ncells, 1) < 0) + if (map_to_dict(co->co_freevars, co->co_nfreevars, locals, + fast + co->co_nlocals + co->co_ncellvars, 1) < 0) return -1; } } @@ -1096,7 +1093,6 @@ PyFrame_LocalsToFast(PyFrameObject *f, int clear) PyObject *error_type, *error_value, *error_traceback; PyCodeObject *co; Py_ssize_t j; - Py_ssize_t ncells, nfreevars; if (f == NULL) return; locals = _PyFrame_Specials(f)[FRAME_SPECIALS_LOCALS_OFFSET]; @@ -1113,16 +1109,14 @@ PyFrame_LocalsToFast(PyFrameObject *f, int clear) j = co->co_nlocals; if (co->co_nlocals) dict_to_map(co->co_varnames, j, locals, fast, 0, clear); - ncells = PyTuple_GET_SIZE(co->co_cellvars); - nfreevars = PyTuple_GET_SIZE(co->co_freevars); - if (ncells || nfreevars) { - dict_to_map(co->co_cellvars, ncells, + if (co->co_ncellvars || co->co_nfreevars) { + dict_to_map(co->co_cellvars, co->co_ncellvars, locals, fast + co->co_nlocals, 1, clear); /* Same test as in PyFrame_FastToLocals() above. */ if (co->co_flags & CO_OPTIMIZED) { - dict_to_map(co->co_freevars, nfreevars, - locals, fast + co->co_nlocals + ncells, 1, - clear); + dict_to_map(co->co_freevars, co->co_nfreevars, locals, + fast + co->co_nlocals + co->co_ncellvars, 1, + clear); } } PyErr_Restore(error_type, error_value, error_traceback); diff --git a/Objects/funcobject.c b/Objects/funcobject.c index f0b0b67..dc27215 100644 --- a/Objects/funcobject.c +++ b/Objects/funcobject.c @@ -279,7 +279,8 @@ func_get_code(PyFunctionObject *op, void *Py_UNUSED(ignored)) static int func_set_code(PyFunctionObject *op, PyObject *value, void *Py_UNUSED(ignored)) { - Py_ssize_t nfree, nclosure; + Py_ssize_t nclosure; + int nfree; /* Not legal to del f.func_code or to set it to anything * other than a code object. */ @@ -294,7 +295,7 @@ func_set_code(PyFunctionObject *op, PyObject *value, void *Py_UNUSED(ignored)) return -1; } - nfree = PyCode_GetNumFree((PyCodeObject *)value); + nfree = ((PyCodeObject *)value)->co_nfreevars; nclosure = (op->func_closure == NULL ? 0 : PyTuple_GET_SIZE(op->func_closure)); if (nclosure != nfree) { @@ -538,7 +539,7 @@ func_new_impl(PyTypeObject *type, PyCodeObject *code, PyObject *globals, /*[clinic end generated code: output=99c6d9da3a24e3be input=93611752fc2daf11]*/ { PyFunctionObject *newfunc; - Py_ssize_t nfree, nclosure; + Py_ssize_t nclosure; if (name != Py_None && !PyUnicode_Check(name)) { PyErr_SetString(PyExc_TypeError, @@ -550,9 +551,8 @@ func_new_impl(PyTypeObject *type, PyCodeObject *code, PyObject *globals, "arg 4 (defaults) must be None or tuple"); return NULL; } - nfree = PyTuple_GET_SIZE(code->co_freevars); if (!PyTuple_Check(closure)) { - if (nfree && closure == Py_None) { + if (code->co_nfreevars && closure == Py_None) { PyErr_SetString(PyExc_TypeError, "arg 5 (closure) must be tuple"); return NULL; @@ -566,10 +566,10 @@ func_new_impl(PyTypeObject *type, PyCodeObject *code, PyObject *globals, /* check that the closure is well-formed */ nclosure = closure == Py_None ? 0 : PyTuple_GET_SIZE(closure); - if (nfree != nclosure) + if (code->co_nfreevars != nclosure) return PyErr_Format(PyExc_ValueError, "%U requires closure of length %zd, not %zd", - code->co_name, nfree, nclosure); + code->co_name, code->co_nfreevars, nclosure); if (nclosure) { Py_ssize_t i; for (i = 0; i < nclosure; i++) { diff --git a/Objects/typeobject.c b/Objects/typeobject.c index 1460085..feb25aa 100644 --- a/Objects/typeobject.c +++ b/Objects/typeobject.c @@ -8848,11 +8848,10 @@ super_init_without_args(PyFrameObject *f, PyCodeObject *co, } PyObject *obj = f->f_localsptr[0]; - Py_ssize_t i, n; + Py_ssize_t i; if (obj == NULL && co->co_cell2arg) { /* The first argument might be a cell. */ - n = PyTuple_GET_SIZE(co->co_cellvars); - for (i = 0; i < n; i++) { + for (i = 0; i < co->co_ncellvars; i++) { if (co->co_cell2arg[i] == 0) { PyObject *cell = f->f_localsptr[co->co_nlocals + i]; assert(PyCell_Check(cell)); @@ -8867,21 +8866,12 @@ super_init_without_args(PyFrameObject *f, PyCodeObject *co, return -1; } - if (co->co_freevars == NULL) { - n = 0; - } - else { - assert(PyTuple_Check(co->co_freevars)); - n = PyTuple_GET_SIZE(co->co_freevars); - } - PyTypeObject *type = NULL; - for (i = 0; i < n; i++) { + for (i = 0; i < co->co_nfreevars; i++) { PyObject *name = PyTuple_GET_ITEM(co->co_freevars, i); assert(PyUnicode_Check(name)); if (_PyUnicode_EqualToASCIIId(name, &PyId___class__)) { - Py_ssize_t index = co->co_nlocals + - PyTuple_GET_SIZE(co->co_cellvars) + i; + Py_ssize_t index = co->co_nlocals + co->co_ncellvars + i; PyObject *cell = f->f_localsptr[index]; if (cell == NULL || !PyCell_Check(cell)) { PyErr_SetString(PyExc_RuntimeError, |