mirror of
				https://github.com/python/cpython.git
				synced 2025-10-30 13:11:29 +00:00 
			
		
		
		
	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:
		
							parent
							
								
									154477be72
								
							
						
					
					
						commit
						f5559f38d9
					
				
					 4 changed files with 105 additions and 32 deletions
				
			
		|  | @ -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, | ||||||
|  |  | ||||||
|  | @ -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; | ||||||
|                     } |                     } | ||||||
|  |  | ||||||
|  | @ -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); |  | ||||||
|             int argoffset = (int)PyLong_AS_LONG(varindex); |  | ||||||
|             fixed[oldindex] = argoffset; |  | ||||||
|         } |         } | ||||||
|  |         if (varindex == NULL) { | ||||||
|  |             continue; | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|  |         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) \ | ||||||
|  |  | ||||||
|  | @ -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"); | ||||||
|     } |     } | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Victor Stinner
						Victor Stinner