diff options
| author | Miss Islington (bot) <31488909+miss-islington@users.noreply.github.com> | 2024-07-18 15:38:28 (GMT) |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2024-07-18 15:38:28 (GMT) |
| commit | 233ed46e6d2ba1d1f7d83a72ccf9aad9e628ede1 (patch) | |
| tree | 01bc7b31b77979643876d79795899b740f155a6d /Python/ceval.c | |
| parent | 98e7d447121f1637c76071548b019ba20a8b8a7a (diff) | |
| download | cpython-233ed46e6d2ba1d1f7d83a72ccf9aad9e628ede1.zip cpython-233ed46e6d2ba1d1f7d83a72ccf9aad9e628ede1.tar.gz cpython-233ed46e6d2ba1d1f7d83a72ccf9aad9e628ede1.tar.bz2 | |
[3.13] gh-118934: Make PyEval_GetLocals return borrowed reference (GH-119769) (#121869)
gh-118934: Make PyEval_GetLocals return borrowed reference (GH-119769)
(cherry picked from commit e65cb4c6f01a687f451ad9db1600525e1c5832c4)
Co-authored-by: Tian Gao <gaogaotiantian@hotmail.com>
Co-authored-by: Alyssa Coghlan <ncoghlan@gmail.com>
Diffstat (limited to 'Python/ceval.c')
| -rw-r--r-- | Python/ceval.c | 33 |
1 files changed, 32 insertions, 1 deletions
diff --git a/Python/ceval.c b/Python/ceval.c index e2521a4..bbd8a24 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -2466,6 +2466,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) { @@ -2473,7 +2474,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; } |
