mirror of
https://github.com/python/cpython.git
synced 2025-08-04 00:48:58 +00:00
gh-118934: Make PyEval_GetLocals return borrowed reference (#119769)
Co-authored-by: Alyssa Coghlan <ncoghlan@gmail.com>
This commit is contained in:
parent
162b41f577
commit
e65cb4c6f0
5 changed files with 42 additions and 2 deletions
|
@ -2525,6 +2525,7 @@ _PyEval_GetBuiltinId(_Py_Identifier *name)
|
|||
PyObject *
|
||||
PyEval_GetLocals(void)
|
||||
{
|
||||
// We need to return a borrowed reference here, so some tricks are needed
|
||||
PyThreadState *tstate = _PyThreadState_GET();
|
||||
_PyInterpreterFrame *current_frame = _PyThreadState_GetFrame(tstate);
|
||||
if (current_frame == NULL) {
|
||||
|
@ -2532,7 +2533,37 @@ PyEval_GetLocals(void)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
PyObject *locals = _PyEval_GetFrameLocals();
|
||||
// Be aware that this returns a new reference
|
||||
PyObject *locals = _PyFrame_GetLocals(current_frame);
|
||||
|
||||
if (locals == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (PyFrameLocalsProxy_Check(locals)) {
|
||||
PyFrameObject *f = _PyFrame_GetFrameObject(current_frame);
|
||||
PyObject *ret = f->f_locals_cache;
|
||||
if (ret == NULL) {
|
||||
PyObject *ret = PyDict_New();
|
||||
if (ret == NULL) {
|
||||
Py_DECREF(locals);
|
||||
return NULL;
|
||||
}
|
||||
f->f_locals_cache = ret;
|
||||
}
|
||||
if (PyDict_Update(ret, locals) < 0) {
|
||||
// At this point, if the cache dict is broken, it will stay broken, as
|
||||
// trying to clean it up or replace it will just cause other problems
|
||||
ret = NULL;
|
||||
}
|
||||
Py_DECREF(locals);
|
||||
return ret;
|
||||
}
|
||||
|
||||
assert(PyMapping_Check(locals));
|
||||
assert(Py_REFCNT(locals) > 1);
|
||||
Py_DECREF(locals);
|
||||
|
||||
return locals;
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue