2828#define  OFF (x ) offsetof(PyFrameObject, x)
2929
3030
31- // Returns borrowed  reference or NULL 
31+ // Returns new  reference or NULL 
3232static  PyObject  * 
3333framelocalsproxy_getval (_PyInterpreterFrame  * frame , PyCodeObject  * co , int  i )
3434{
@@ -57,7 +57,10 @@ framelocalsproxy_getval(_PyInterpreterFrame *frame, PyCodeObject *co, int i)
5757    }
5858
5959    if  (cell  !=  NULL ) {
60-         value  =  PyCell_GET (cell );
60+         value  =  PyCell_GetRef ((PyCellObject  * )cell );
61+     }
62+     else  {
63+         Py_XINCREF (value );
6164    }
6265
6366    if  (value  ==  NULL ) {
@@ -67,24 +70,42 @@ framelocalsproxy_getval(_PyInterpreterFrame *frame, PyCodeObject *co, int i)
6770    return  value ;
6871}
6972
73+ static  bool 
74+ framelocalsproxy_hasval (_PyInterpreterFrame  * frame , PyCodeObject  * co , int  i )
75+ {
76+     PyObject  * value  =  framelocalsproxy_getval (frame , co , i );
77+     if  (value  ==  NULL ) {
78+         return  false;
79+     }
80+     Py_DECREF (value );
81+     return  true;
82+ }
83+ 
7084static  int 
71- framelocalsproxy_getkeyindex (PyFrameObject  * frame , PyObject *   key , bool  read )
85+ framelocalsproxy_getkeyindex (PyFrameObject  * frame , PyObject   * key , bool  read ,  PyObject   * * value_ptr )
7286{
7387    /* 
7488     * Returns -2 (!) if an error occurred; exception will be set. 
7589     * Returns the fast locals index of the key on success: 
7690     *   - if read == true, returns the index if the value is not NULL 
7791     *   - if read == false, returns the index if the value is not hidden 
7892     * Otherwise returns -1. 
93+      * 
94+      * If read == true and value_ptr is not NULL, *value_ptr is set to 
95+      * the value of the key if it is found (with a new reference). 
7996     */ 
8097
98+     // value_ptr should only be given if we are reading the value 
99+     assert (read  ||  value_ptr  ==  NULL );
100+ 
81101    PyCodeObject  * co  =  _PyFrame_GetCode (frame -> f_frame );
82102
83103    // Ensure that the key is hashable. 
84104    Py_hash_t  key_hash  =  PyObject_Hash (key );
85105    if  (key_hash  ==  -1 ) {
86106        return  -2 ;
87107    }
108+ 
88109    bool  found  =  false;
89110
90111    // We do 2 loops here because it's highly possible the key is interned 
@@ -93,7 +114,14 @@ framelocalsproxy_getkeyindex(PyFrameObject *frame, PyObject* key, bool read)
93114        PyObject  * name  =  PyTuple_GET_ITEM (co -> co_localsplusnames , i );
94115        if  (name  ==  key ) {
95116            if  (read ) {
96-                 if  (framelocalsproxy_getval (frame -> f_frame , co , i ) !=  NULL ) {
117+                 PyObject  * value  =  framelocalsproxy_getval (frame -> f_frame , co , i );
118+                 if  (value  !=  NULL ) {
119+                     if  (value_ptr  !=  NULL ) {
120+                         * value_ptr  =  value ;
121+                     }
122+                     else  {
123+                         Py_DECREF (value );
124+                     }
97125                    return  i ;
98126                }
99127            } else  {
@@ -124,7 +152,14 @@ framelocalsproxy_getkeyindex(PyFrameObject *frame, PyObject* key, bool read)
124152        }
125153        if  (same ) {
126154            if  (read ) {
127-                 if  (framelocalsproxy_getval (frame -> f_frame , co , i ) !=  NULL ) {
155+                 PyObject  * value  =  framelocalsproxy_getval (frame -> f_frame , co , i );
156+                 if  (value  !=  NULL ) {
157+                     if  (value_ptr  !=  NULL ) {
158+                         * value_ptr  =  value ;
159+                     }
160+                     else  {
161+                         Py_DECREF (value );
162+                     }
128163                    return  i ;
129164                }
130165            } else  {
@@ -142,25 +177,27 @@ static PyObject *
142177framelocalsproxy_getitem (PyObject  * self , PyObject  * key )
143178{
144179    PyFrameObject  * frame  =  PyFrameLocalsProxyObject_CAST (self )-> frame ;
145-     PyCodeObject   * co  =  _PyFrame_GetCode ( frame -> f_frame ) ;
180+     PyObject   * value  =  NULL ;
146181
147-     int  i  =  framelocalsproxy_getkeyindex (frame , key , true);
182+     int  i  =  framelocalsproxy_getkeyindex (frame , key , true,  & value );
148183    if  (i  ==  -2 ) {
149184        return  NULL ;
150185    }
151186    if  (i  >= 0 ) {
152-         PyObject  * value  =  framelocalsproxy_getval (frame -> f_frame , co , i );
153187        assert (value  !=  NULL );
154-         return  Py_NewRef ( value ) ;
188+         return  value ;
155189    }
190+     assert (value  ==  NULL );
156191
157192    // Okay not in the fast locals, try extra locals 
158193
159194    PyObject  * extra  =  frame -> f_extra_locals ;
160195    if  (extra  !=  NULL ) {
161-         PyObject  * value  =  PyDict_GetItem (extra , key );
196+         if  (PyDict_GetItemRef (extra , key , & value ) <  0 ) {
197+             return  NULL ;
198+         }
162199        if  (value  !=  NULL ) {
163-             return  Py_NewRef ( value ) ;
200+             return  value ;
164201        }
165202    }
166203
@@ -176,7 +213,7 @@ framelocalsproxy_setitem(PyObject *self, PyObject *key, PyObject *value)
176213    _PyStackRef  * fast  =  _PyFrame_GetLocalsArray (frame -> f_frame );
177214    PyCodeObject  * co  =  _PyFrame_GetCode (frame -> f_frame );
178215
179-     int  i  =  framelocalsproxy_getkeyindex (frame , key , false);
216+     int  i  =  framelocalsproxy_getkeyindex (frame , key , false,  NULL );
180217    if  (i  ==  -2 ) {
181218        return  -1 ;
182219    }
@@ -297,8 +334,7 @@ framelocalsproxy_keys(PyObject *self, PyObject *Py_UNUSED(ignored))
297334    }
298335
299336    for  (int  i  =  0 ; i  <  co -> co_nlocalsplus ; i ++ ) {
300-         PyObject  * val  =  framelocalsproxy_getval (frame -> f_frame , co , i );
301-         if  (val ) {
337+         if  (framelocalsproxy_hasval (frame -> f_frame , co , i )) {
302338            PyObject  * name  =  PyTuple_GET_ITEM (co -> co_localsplusnames , i );
303339            if  (PyList_Append (names , name ) <  0 ) {
304340                Py_DECREF (names );
@@ -511,8 +547,10 @@ framelocalsproxy_values(PyObject *self, PyObject *Py_UNUSED(ignored))
511547        if  (value ) {
512548            if  (PyList_Append (values , value ) <  0 ) {
513549                Py_DECREF (values );
550+                 Py_DECREF (value );
514551                return  NULL ;
515552            }
553+             Py_DECREF (value );
516554        }
517555    }
518556
@@ -550,16 +588,19 @@ framelocalsproxy_items(PyObject *self, PyObject *Py_UNUSED(ignored))
550588            PyObject  * pair  =  PyTuple_Pack (2 , name , value );
551589            if  (pair  ==  NULL ) {
552590                Py_DECREF (items );
591+                 Py_DECREF (value );
553592                return  NULL ;
554593            }
555594
556595            if  (PyList_Append (items , pair ) <  0 ) {
557596                Py_DECREF (items );
558597                Py_DECREF (pair );
598+                 Py_DECREF (value );
559599                return  NULL ;
560600            }
561601
562602            Py_DECREF (pair );
603+             Py_DECREF (value );
563604        }
564605    }
565606
@@ -601,7 +642,7 @@ framelocalsproxy_length(PyObject *self)
601642    }
602643
603644    for  (int  i  =  0 ; i  <  co -> co_nlocalsplus ; i ++ ) {
604-         if  (framelocalsproxy_getval (frame -> f_frame , co , i )  !=   NULL ) {
645+         if  (framelocalsproxy_hasval (frame -> f_frame , co , i )) {
605646            size ++ ;
606647        }
607648    }
@@ -613,7 +654,7 @@ framelocalsproxy_contains(PyObject *self, PyObject *key)
613654{
614655    PyFrameObject  * frame  =  PyFrameLocalsProxyObject_CAST (self )-> frame ;
615656
616-     int  i  =  framelocalsproxy_getkeyindex (frame , key , true);
657+     int  i  =  framelocalsproxy_getkeyindex (frame , key , true,  NULL );
617658    if  (i  ==  -2 ) {
618659        return  -1 ;
619660    }
@@ -724,7 +765,7 @@ framelocalsproxy_pop(PyObject* self, PyObject *const *args, Py_ssize_t nargs)
724765
725766    PyFrameObject  * frame  =  PyFrameLocalsProxyObject_CAST (self )-> frame ;
726767
727-     int  i  =  framelocalsproxy_getkeyindex (frame , key , false);
768+     int  i  =  framelocalsproxy_getkeyindex (frame , key , false,  NULL );
728769    if  (i  ==  -2 ) {
729770        return  NULL ;
730771    }
@@ -2066,9 +2107,7 @@ _PyFrame_HasHiddenLocals(_PyInterpreterFrame *frame)
20662107        _PyLocals_Kind  kind  =  _PyLocals_GetKind (co -> co_localspluskinds , i );
20672108
20682109        if  (kind  &  CO_FAST_HIDDEN ) {
2069-             PyObject *  value  =  framelocalsproxy_getval (frame , co , i );
2070- 
2071-             if  (value  !=  NULL ) {
2110+             if  (framelocalsproxy_hasval (frame , co , i )) {
20722111                return  true;
20732112            }
20742113        }
0 commit comments