Skip to content

Commit

Permalink
gh-108308: Replace PyDict_GetItem() with PyDict_GetItemRef()
Browse files Browse the repository at this point in the history
Replace PyDict_GetItem() calls with PyDict_GetItemRef() to handle
errors.

pycore_init_builtins() now checks for _PyType_Lookup() failure.
  • Loading branch information
vstinner committed Aug 22, 2023
1 parent adfc118 commit ce6ea31
Show file tree
Hide file tree
Showing 4 changed files with 61 additions and 15 deletions.
20 changes: 16 additions & 4 deletions Python/assemble.c
Original file line number Diff line number Diff line change
Expand Up @@ -466,7 +466,7 @@ dict_keys_inorder(PyObject *dict, Py_ssize_t offset)
extern void _Py_set_localsplus_info(int, PyObject *, unsigned char,
PyObject *, PyObject *);

static void
static int
compute_localsplus_info(_PyCompile_CodeUnitMetadata *umd, int nlocalsplus,
PyObject *names, PyObject *kinds)
{
Expand All @@ -481,7 +481,11 @@ compute_localsplus_info(_PyCompile_CodeUnitMetadata *umd, int nlocalsplus,
if (PyDict_Contains(umd->u_fasthidden, k)) {
kind |= CO_FAST_HIDDEN;
}
if (PyDict_GetItem(umd->u_cellvars, k) != NULL) {
int has_cell = PyDict_Contains(umd->u_cellvars, k);
if (has_cell < 0) {
return -1;
}
if (has_cell) {
kind |= CO_FAST_CELL;
}
_Py_set_localsplus_info(offset, k, kind, names, kinds);
Expand All @@ -492,7 +496,11 @@ compute_localsplus_info(_PyCompile_CodeUnitMetadata *umd, int nlocalsplus,
int numdropped = 0;
pos = 0;
while (PyDict_Next(umd->u_cellvars, &pos, &k, &v)) {
if (PyDict_GetItem(umd->u_varnames, k) != NULL) {
int has_name = PyDict_Contains(umd->u_varnames, k);
if (has_name < 0) {
return -1;
}
if (has_name) {
// Skip cells that are already covered by locals.
numdropped += 1;
continue;
Expand All @@ -512,6 +520,7 @@ compute_localsplus_info(_PyCompile_CodeUnitMetadata *umd, int nlocalsplus,
assert(offset < nlocalsplus);
_Py_set_localsplus_info(offset, k, CO_FAST_FREE, names, kinds);
}
return 0;
}

static PyCodeObject *
Expand Down Expand Up @@ -556,7 +565,10 @@ makecode(_PyCompile_CodeUnitMetadata *umd, struct assembler *a, PyObject *const_
if (localspluskinds == NULL) {
goto error;
}
compute_localsplus_info(umd, nlocalsplus, localsplusnames, localspluskinds);
if (compute_localsplus_info(umd, nlocalsplus,
localsplusnames, localspluskinds) < 0) {
goto error;
}

struct _PyCodeConstructor con = {
.filename = filename,
Expand Down
24 changes: 20 additions & 4 deletions Python/compile.c
Original file line number Diff line number Diff line change
Expand Up @@ -4194,9 +4194,20 @@ compiler_nameop(struct compiler *c, location loc,
optype = OP_DEREF;
break;
case LOCAL:
if (_PyST_IsFunctionLike(c->u->u_ste) ||
(PyDict_GetItem(c->u->u_metadata.u_fasthidden, mangled) == Py_True))
if (_PyST_IsFunctionLike(c->u->u_ste)) {
optype = OP_FAST;
}
else {
PyObject *item;
if (PyDict_GetItemRef(c->u->u_metadata.u_fasthidden, mangled,
&item) < 0) {
return ERROR;
}
if (item == Py_True) {
optype = OP_FAST;
}
Py_XDECREF(item);
}
break;
case GLOBAL_IMPLICIT:
if (_PyST_IsFunctionLike(c->u->u_ste))
Expand Down Expand Up @@ -5518,8 +5529,13 @@ push_inlined_comprehension_state(struct compiler *c, location loc,
if ((symbol & DEF_LOCAL && !(symbol & DEF_NONLOCAL)) || in_class_block) {
if (!_PyST_IsFunctionLike(c->u->u_ste)) {
// non-function scope: override this name to use fast locals
PyObject *orig = PyDict_GetItem(c->u->u_metadata.u_fasthidden, k);
if (orig != Py_True) {
PyObject *orig;
if (PyDict_GetItemRef(c->u->u_metadata.u_fasthidden, k, &orig) < 0) {
return ERROR;
}
int orig_is_true = (orig == Py_True);
Py_XDECREF(orig);
if (!orig_is_true) {
if (PyDict_SetItem(c->u->u_metadata.u_fasthidden, k, Py_True) < 0) {
return ERROR;
}
Expand Down
6 changes: 5 additions & 1 deletion Python/flowgraph.c
Original file line number Diff line number Diff line change
Expand Up @@ -2404,12 +2404,16 @@ build_cellfixedoffsets(_PyCompile_CodeUnitMetadata *umd)
PyObject *varname, *cellindex;
Py_ssize_t pos = 0;
while (PyDict_Next(umd->u_cellvars, &pos, &varname, &cellindex)) {
PyObject *varindex = PyDict_GetItem(umd->u_varnames, varname);
PyObject *varindex;
if (PyDict_GetItemRef(umd->u_varnames, varname, &varindex) < 0) {
return NULL;
}
if (varindex != NULL) {
assert(PyLong_AS_LONG(cellindex) < INT_MAX);
assert(PyLong_AS_LONG(varindex) < INT_MAX);
int oldindex = (int)PyLong_AS_LONG(cellindex);
int argoffset = (int)PyLong_AS_LONG(varindex);
Py_DECREF(varindex);
fixed[oldindex] = argoffset;
}
}
Expand Down
26 changes: 20 additions & 6 deletions Python/pylifecycle.c
Original file line number Diff line number Diff line change
Expand Up @@ -762,18 +762,32 @@ pycore_init_builtins(PyThreadState *tstate)
}
interp->builtins = Py_NewRef(builtins_dict);

PyObject *isinstance = PyDict_GetItem(builtins_dict, &_Py_ID(isinstance));
assert(isinstance);
PyObject *isinstance;
if (PyDict_GetItemRef(builtins_dict, &_Py_ID(isinstance), &isinstance) != 1) {
goto error;
}
interp->callable_cache.isinstance = isinstance;
PyObject *len = PyDict_GetItem(builtins_dict, &_Py_ID(len));
assert(len);
Py_DECREF(isinstance);

PyObject *len;
if (PyDict_GetItemRef(builtins_dict, &_Py_ID(len), &len) != 1) {
goto error;
}
interp->callable_cache.len = len;
Py_DECREF(len);

PyObject *list_append = _PyType_Lookup(&PyList_Type, &_Py_ID(append));
assert(list_append);
if (list_append == NULL) {
goto error;
}
interp->callable_cache.list_append = list_append;

PyObject *object__getattribute__ = _PyType_Lookup(&PyBaseObject_Type, &_Py_ID(__getattribute__));
assert(object__getattribute__);
if (object__getattribute__ == NULL) {
goto error;
}
interp->callable_cache.object__getattribute__ = object__getattribute__;

if (_PyBuiltins_AddExceptions(bimod) < 0) {
return _PyStatus_ERR("failed to add exceptions to builtins");
}
Expand Down

0 comments on commit ce6ea31

Please sign in to comment.