@@ -66,7 +66,11 @@ static int ProfilerState_UpdateContextVar(ProfilerState *self) {
6666        return  0 ;
6767    }
6868
69-     if  (old  ==  new ) return  1 ;
69+     if  (old  ==  new ) {
70+         // The object is the same, so we don't need the new reference. 
71+         Py_DECREF (new );
72+         return  1 ;
73+     }
7074
7175    self -> last_context_var_value  =  new ;
7276
@@ -251,6 +255,9 @@ call_target(ProfilerState *pState, PyFrameObject *frame, int what, PyObject *arg
251255    return  result ;
252256}
253257
258+ /** 
259+  * Returns a new reference to a PyCodeObject for the given frame. 
260+  */ 
254261static  PyCodeObject  * 
255262code_from_frame (PyFrameObject *  frame )
256263{
@@ -263,6 +270,10 @@ code_from_frame(PyFrameObject* frame)
263270#endif 
264271}
265272
273+ /** 
274+  * Returns a new reference to a PyTupleObject containing the names of the 
275+  * local variables. 
276+  */ 
266277static  PyObject  * 
267278local_names_from_code (PyCodeObject  * code )
268279{
@@ -276,6 +287,10 @@ local_names_from_code(PyCodeObject *code)
276287}
277288
278289#if  PY_VERSION_HEX  >= 0x030b0000  // Python 3.11.0 
290+ /** 
291+  * Returns a C-string containing the name of the class in the frame. The 
292+  * memory belongs to the type object, so it should not be freed. 
293+  */ 
279294static  const  char  * 
280295_get_class_name_of_frame (PyFrameObject  * frame , PyCodeObject  * code ) {
281296    PyObject  * localsNames  =  PyCode_GetVarnames (code );
@@ -287,10 +302,10 @@ _get_class_name_of_frame(PyFrameObject *frame, PyCodeObject *code) {
287302    PyObject  * firstArgName  =  PyTuple_GET_ITEM (localsNames , 0 );
288303
289304    if  (firstArgName  ==  NULL ) {
305+         Py_DECREF (localsNames );
290306        return  NULL ;
291307    }
292308
293- 
294309    int  has_self  =  PyUnicode_Compare (firstArgName , SELF_STRING ) ==  0 ;
295310    int  has_cls  =  PyUnicode_Compare (firstArgName , CLS_STRING ) ==  0 ;
296311
@@ -323,6 +338,7 @@ _get_class_name_of_frame(PyFrameObject *frame, PyCodeObject *code) {
323338        }
324339
325340        result  =  _PyType_Name (self -> ob_type );
341+         Py_DECREF (self );
326342    }
327343    else  if  (has_cls  &&  PyMapping_HasKey (locals , CLS_STRING )) {
328344        PyObject  * cls  =  PyObject_GetItem (locals , CLS_STRING );
@@ -337,6 +353,7 @@ _get_class_name_of_frame(PyFrameObject *frame, PyCodeObject *code) {
337353            PyTypeObject  * type  =  (PyTypeObject  * )cls ;
338354            result  =  _PyType_Name (type );
339355        }
356+         Py_DECREF (cls );
340357    }
341358
342359    Py_DECREF (locals );
@@ -456,6 +473,7 @@ _get_tracebackhide(PyFrameObject *frame, PyCodeObject *code) {
456473
457474    if  (!PySequence_Check (locals_names )) {
458475        // locals_names must be a sequence 
476+         Py_DECREF (locals_names );
459477        return  0 ;
460478    }
461479
@@ -471,6 +489,9 @@ _get_tracebackhide(PyFrameObject *frame, PyCodeObject *code) {
471489    }
472490}
473491
492+ /** 
493+  * Returns a new reference to pyinstrument's frame info string for the given frame. 
494+  */ 
474495static  PyObject  * 
475496_get_frame_info (PyFrameObject  * frame ) {
476497    PyCodeObject  * code  =  code_from_frame (frame );
@@ -703,14 +724,18 @@ setstatprofile(PyObject *m, PyObject *args, PyObject *kwds)
703724        }
704725
705726        pState  =  ProfilerState_New ();
727+         if  (pState  ==  NULL ) { // Check if allocation failed 
728+             return  NULL ;
729+         }
730+ 
706731        ProfilerState_SetTarget (pState , target );
707732
708733        // default interval is 1 ms 
709734        pState -> interval  =  (interval  >  0 ) ? interval  : 0.001 ;
710735
711736        int  timer_type_int  =  _parse_timer_type (timer_type , TIMER_TYPE_WALLTIME );
712737        if  (timer_type_int  ==  -1 ) {
713-             return   NULL ;
738+             goto  error ;
714739        }
715740
716741        if  (timer_func  ==  Py_None ) {
@@ -719,12 +744,12 @@ setstatprofile(PyObject *m, PyObject *args, PyObject *kwds)
719744
720745        if  (timer_type_int  ==  TIMER_TYPE_TIMER_FUNC  &&  timer_func  ==  NULL ) {
721746            PyErr_SetString (PyExc_TypeError , "timer_func must be set if timer_type is 'timer_func'" );
722-             return   NULL ;
747+             goto  error ;
723748        }
724749
725750        if  (timer_func  &&  timer_type_int  !=  TIMER_TYPE_TIMER_FUNC ) {
726751            PyErr_SetString (PyExc_TypeError , "timer_type must be 'timer_func' if timer_func is set" );
727-             return   NULL ;
752+             goto  error ;
728753        }
729754
730755        if  (timer_func ) {
@@ -734,7 +759,7 @@ setstatprofile(PyObject *m, PyObject *args, PyObject *kwds)
734759            pState -> timer_thread_subscription_id  =  pyi_timing_thread_subscribe (pState -> interval );
735760            if  (pState -> timer_thread_subscription_id  <  0 ) {
736761                PyErr_Format (PyExc_RuntimeError , "failed to subscribe to timing thread: error %d" , pState -> timer_thread_subscription_id );
737-                 return   NULL ;
762+                 goto  error ;
738763            }
739764        } else  if  (timer_type_int  ==  TIMER_TYPE_WALLTIME_COARSE ) {
740765            pState -> floatclock_type  =  PYI_FLOATCLOCK_MONOTONIC_COARSE ;
@@ -750,17 +775,21 @@ setstatprofile(PyObject *m, PyObject *args, PyObject *kwds)
750775            pState -> context_var  =  context_var ;
751776
752777            if  (!ProfilerState_UpdateContextVar (pState )) {
753-                 return   NULL ;
778+                 goto  error ;
754779            }
755780        }
756781
757782        PyEval_SetProfile (profile , (PyObject  * )pState );
758-         Py_DECREF (pState );
783+         Py_DECREF (pState );  // We've given a reference to SetProfile, so we release ours. 
759784    } else  {
760785        PyEval_SetProfile (NULL , NULL );
761786    }
762787
763788    Py_RETURN_NONE ;
789+ 
790+ error :
791+     Py_XDECREF (pState );
792+     return  NULL ;
764793}
765794
766795
0 commit comments