gh-108308: Replace PyDict_GetItem() with PyDict_GetItemRef() (#108309)

Replace PyDict_GetItem() calls with PyDict_GetItemRef()
or PyDict_GetItemWithError() to handle errors.

* Replace PyLong_AS_LONG() with _PyLong_AsInt()
  and check for errors.
* Check for PyDict_Contains() error.
* pycore_init_builtins() checks for _PyType_Lookup() failure.
This commit is contained in:
Victor Stinner 2023-08-23 17:40:26 +02:00 committed by GitHub
parent 154477be72
commit f5559f38d9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 105 additions and 32 deletions

View File

@ -18,7 +18,7 @@
#define ERROR -1 #define ERROR -1
#define RETURN_IF_ERROR(X) \ #define RETURN_IF_ERROR(X) \
if ((X) == -1) { \ if ((X) < 0) { \
return ERROR; \ return ERROR; \
} }
@ -448,13 +448,17 @@ static PyObject *
dict_keys_inorder(PyObject *dict, Py_ssize_t offset) dict_keys_inorder(PyObject *dict, Py_ssize_t offset)
{ {
PyObject *tuple, *k, *v; PyObject *tuple, *k, *v;
Py_ssize_t i, pos = 0, size = PyDict_GET_SIZE(dict); Py_ssize_t pos = 0, size = PyDict_GET_SIZE(dict);
tuple = PyTuple_New(size); tuple = PyTuple_New(size);
if (tuple == NULL) if (tuple == NULL)
return NULL; return NULL;
while (PyDict_Next(dict, &pos, &k, &v)) { while (PyDict_Next(dict, &pos, &k, &v)) {
i = PyLong_AS_LONG(v); Py_ssize_t i = PyLong_AsSsize_t(v);
if (i == -1 && PyErr_Occurred()) {
Py_DECREF(tuple);
return NULL;
}
assert((i - offset) < size); assert((i - offset) < size);
assert((i - offset) >= 0); assert((i - offset) >= 0);
PyTuple_SET_ITEM(tuple, i - offset, Py_NewRef(k)); PyTuple_SET_ITEM(tuple, i - offset, Py_NewRef(k));
@ -466,24 +470,34 @@ dict_keys_inorder(PyObject *dict, Py_ssize_t offset)
extern void _Py_set_localsplus_info(int, PyObject *, unsigned char, extern void _Py_set_localsplus_info(int, PyObject *, unsigned char,
PyObject *, PyObject *); PyObject *, PyObject *);
static void static int
compute_localsplus_info(_PyCompile_CodeUnitMetadata *umd, int nlocalsplus, compute_localsplus_info(_PyCompile_CodeUnitMetadata *umd, int nlocalsplus,
PyObject *names, PyObject *kinds) PyObject *names, PyObject *kinds)
{ {
PyObject *k, *v; PyObject *k, *v;
Py_ssize_t pos = 0; Py_ssize_t pos = 0;
while (PyDict_Next(umd->u_varnames, &pos, &k, &v)) { while (PyDict_Next(umd->u_varnames, &pos, &k, &v)) {
int offset = (int)PyLong_AS_LONG(v); int offset = _PyLong_AsInt(v);
if (offset == -1 && PyErr_Occurred()) {
return ERROR;
}
assert(offset >= 0); assert(offset >= 0);
assert(offset < nlocalsplus); assert(offset < nlocalsplus);
// For now we do not distinguish arg kinds. // For now we do not distinguish arg kinds.
_PyLocals_Kind kind = CO_FAST_LOCAL; _PyLocals_Kind kind = CO_FAST_LOCAL;
if (PyDict_Contains(umd->u_fasthidden, k)) { int has_key = PyDict_Contains(umd->u_fasthidden, k);
RETURN_IF_ERROR(has_key);
if (has_key) {
kind |= CO_FAST_HIDDEN; kind |= CO_FAST_HIDDEN;
} }
if (PyDict_GetItem(umd->u_cellvars, k) != NULL) {
has_key = PyDict_Contains(umd->u_cellvars, k);
RETURN_IF_ERROR(has_key);
if (has_key) {
kind |= CO_FAST_CELL; kind |= CO_FAST_CELL;
} }
_Py_set_localsplus_info(offset, k, kind, names, kinds); _Py_set_localsplus_info(offset, k, kind, names, kinds);
} }
int nlocals = (int)PyDict_GET_SIZE(umd->u_varnames); int nlocals = (int)PyDict_GET_SIZE(umd->u_varnames);
@ -492,12 +506,18 @@ compute_localsplus_info(_PyCompile_CodeUnitMetadata *umd, int nlocalsplus,
int numdropped = 0; int numdropped = 0;
pos = 0; pos = 0;
while (PyDict_Next(umd->u_cellvars, &pos, &k, &v)) { 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);
RETURN_IF_ERROR(has_name);
if (has_name) {
// Skip cells that are already covered by locals. // Skip cells that are already covered by locals.
numdropped += 1; numdropped += 1;
continue; continue;
} }
int offset = (int)PyLong_AS_LONG(v);
int offset = _PyLong_AsInt(v);
if (offset == -1 && PyErr_Occurred()) {
return ERROR;
}
assert(offset >= 0); assert(offset >= 0);
offset += nlocals - numdropped; offset += nlocals - numdropped;
assert(offset < nlocalsplus); assert(offset < nlocalsplus);
@ -506,12 +526,16 @@ compute_localsplus_info(_PyCompile_CodeUnitMetadata *umd, int nlocalsplus,
pos = 0; pos = 0;
while (PyDict_Next(umd->u_freevars, &pos, &k, &v)) { while (PyDict_Next(umd->u_freevars, &pos, &k, &v)) {
int offset = (int)PyLong_AS_LONG(v); int offset = _PyLong_AsInt(v);
if (offset == -1 && PyErr_Occurred()) {
return ERROR;
}
assert(offset >= 0); assert(offset >= 0);
offset += nlocals - numdropped; offset += nlocals - numdropped;
assert(offset < nlocalsplus); assert(offset < nlocalsplus);
_Py_set_localsplus_info(offset, k, CO_FAST_FREE, names, kinds); _Py_set_localsplus_info(offset, k, CO_FAST_FREE, names, kinds);
} }
return SUCCESS;
} }
static PyCodeObject * static PyCodeObject *
@ -556,7 +580,10 @@ makecode(_PyCompile_CodeUnitMetadata *umd, struct assembler *a, PyObject *const_
if (localspluskinds == NULL) { if (localspluskinds == NULL) {
goto error; goto error;
} }
compute_localsplus_info(umd, nlocalsplus, localsplusnames, localspluskinds); if (compute_localsplus_info(umd, nlocalsplus,
localsplusnames, localspluskinds) == ERROR) {
goto error;
}
struct _PyCodeConstructor con = { struct _PyCodeConstructor con = {
.filename = filename, .filename = filename,

View File

@ -4212,9 +4212,20 @@ compiler_nameop(struct compiler *c, location loc,
optype = OP_DEREF; optype = OP_DEREF;
break; break;
case LOCAL: case LOCAL:
if (_PyST_IsFunctionLike(c->u->u_ste) || if (_PyST_IsFunctionLike(c->u->u_ste)) {
(PyDict_GetItem(c->u->u_metadata.u_fasthidden, mangled) == Py_True))
optype = OP_FAST; optype = OP_FAST;
}
else {
PyObject *item;
if (PyDict_GetItemRef(c->u->u_metadata.u_fasthidden, mangled,
&item) < 0) {
goto error;
}
if (item == Py_True) {
optype = OP_FAST;
}
Py_XDECREF(item);
}
break; break;
case GLOBAL_IMPLICIT: case GLOBAL_IMPLICIT:
if (_PyST_IsFunctionLike(c->u->u_ste)) if (_PyST_IsFunctionLike(c->u->u_ste))
@ -4239,7 +4250,7 @@ compiler_nameop(struct compiler *c, location loc,
op = LOAD_FROM_DICT_OR_DEREF; op = LOAD_FROM_DICT_OR_DEREF;
// First load the locals // First load the locals
if (codegen_addop_noarg(INSTR_SEQUENCE(c), LOAD_LOCALS, loc) < 0) { if (codegen_addop_noarg(INSTR_SEQUENCE(c), LOAD_LOCALS, loc) < 0) {
return ERROR; goto error;
} }
} }
else if (c->u->u_ste->ste_can_see_class_scope) { else if (c->u->u_ste->ste_can_see_class_scope) {
@ -4247,7 +4258,7 @@ compiler_nameop(struct compiler *c, location loc,
// First load the classdict // First load the classdict
if (compiler_addop_o(c->u, loc, LOAD_DEREF, if (compiler_addop_o(c->u, loc, LOAD_DEREF,
c->u->u_metadata.u_freevars, &_Py_ID(__classdict__)) < 0) { c->u->u_metadata.u_freevars, &_Py_ID(__classdict__)) < 0) {
return ERROR; goto error;
} }
} }
else { else {
@ -4274,7 +4285,7 @@ compiler_nameop(struct compiler *c, location loc,
// First load the classdict // First load the classdict
if (compiler_addop_o(c->u, loc, LOAD_DEREF, if (compiler_addop_o(c->u, loc, LOAD_DEREF,
c->u->u_metadata.u_freevars, &_Py_ID(__classdict__)) < 0) { c->u->u_metadata.u_freevars, &_Py_ID(__classdict__)) < 0) {
return ERROR; goto error;
} }
} else { } else {
op = LOAD_GLOBAL; op = LOAD_GLOBAL;
@ -4308,6 +4319,10 @@ compiler_nameop(struct compiler *c, location loc,
arg <<= 1; arg <<= 1;
} }
return codegen_addop_i(INSTR_SEQUENCE(c), op, arg, loc); return codegen_addop_i(INSTR_SEQUENCE(c), op, arg, loc);
error:
Py_DECREF(mangled);
return ERROR;
} }
static int static int
@ -5536,8 +5551,13 @@ push_inlined_comprehension_state(struct compiler *c, location loc,
if ((symbol & DEF_LOCAL && !(symbol & DEF_NONLOCAL)) || in_class_block) { if ((symbol & DEF_LOCAL && !(symbol & DEF_NONLOCAL)) || in_class_block) {
if (!_PyST_IsFunctionLike(c->u->u_ste)) { if (!_PyST_IsFunctionLike(c->u->u_ste)) {
// non-function scope: override this name to use fast locals // non-function scope: override this name to use fast locals
PyObject *orig = PyDict_GetItem(c->u->u_metadata.u_fasthidden, k); PyObject *orig;
if (orig != Py_True) { 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) { if (PyDict_SetItem(c->u->u_metadata.u_fasthidden, k, Py_True) < 0) {
return ERROR; return ERROR;
} }

View File

@ -2404,17 +2404,31 @@ build_cellfixedoffsets(_PyCompile_CodeUnitMetadata *umd)
PyObject *varname, *cellindex; PyObject *varname, *cellindex;
Py_ssize_t pos = 0; Py_ssize_t pos = 0;
while (PyDict_Next(umd->u_cellvars, &pos, &varname, &cellindex)) { while (PyDict_Next(umd->u_cellvars, &pos, &varname, &cellindex)) {
PyObject *varindex = PyDict_GetItem(umd->u_varnames, varname); PyObject *varindex;
if (varindex != NULL) { if (PyDict_GetItemRef(umd->u_varnames, varname, &varindex) < 0) {
assert(PyLong_AS_LONG(cellindex) < INT_MAX); goto error;
assert(PyLong_AS_LONG(varindex) < INT_MAX); }
int oldindex = (int)PyLong_AS_LONG(cellindex); if (varindex == NULL) {
int argoffset = (int)PyLong_AS_LONG(varindex); continue;
fixed[oldindex] = argoffset;
} }
}
int argoffset = _PyLong_AsInt(varindex);
Py_DECREF(varindex);
if (argoffset == -1 && PyErr_Occurred()) {
goto error;
}
int oldindex = _PyLong_AsInt(cellindex);
if (oldindex == -1 && PyErr_Occurred()) {
goto error;
}
fixed[oldindex] = argoffset;
}
return fixed; return fixed;
error:
PyMem_Free(fixed);
return NULL;
} }
#define IS_GENERATOR(CF) \ #define IS_GENERATOR(CF) \

View File

@ -762,18 +762,30 @@ pycore_init_builtins(PyThreadState *tstate)
} }
interp->builtins = Py_NewRef(builtins_dict); interp->builtins = Py_NewRef(builtins_dict);
PyObject *isinstance = PyDict_GetItem(builtins_dict, &_Py_ID(isinstance)); PyObject *isinstance = PyDict_GetItemWithError(builtins_dict, &_Py_ID(isinstance));
assert(isinstance); if (!isinstance) {
goto error;
}
interp->callable_cache.isinstance = isinstance; interp->callable_cache.isinstance = isinstance;
PyObject *len = PyDict_GetItem(builtins_dict, &_Py_ID(len));
assert(len); PyObject *len = PyDict_GetItemWithError(builtins_dict, &_Py_ID(len));
if (!len) {
goto error;
}
interp->callable_cache.len = len; interp->callable_cache.len = len;
PyObject *list_append = _PyType_Lookup(&PyList_Type, &_Py_ID(append)); 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; interp->callable_cache.list_append = list_append;
PyObject *object__getattribute__ = _PyType_Lookup(&PyBaseObject_Type, &_Py_ID(__getattribute__)); 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__; interp->callable_cache.object__getattribute__ = object__getattribute__;
if (_PyBuiltins_AddExceptions(bimod) < 0) { if (_PyBuiltins_AddExceptions(bimod) < 0) {
return _PyStatus_ERR("failed to add exceptions to builtins"); return _PyStatus_ERR("failed to add exceptions to builtins");
} }