Commits

Anonymous committed fda1f20

fix for reading of freed memory with debug build of Python

  • Participants
  • Parent commits eab84c3

Comments (0)

Files changed (1)

     } else {
         fname = pt->co;
     }
-    
+
 // TODO:memleak on buf?
-#ifdef IS_PY3K    
-    buf = PyBytes_AS_STRING(PyUnicode_AsUTF8String(fname));
+#ifdef IS_PY3K
+    // Take a copy of fname before Py_DECREF
+    buf = strdup(PyBytes_AS_STRING(PyUnicode_AsUTF8String(fname)));
 #else
-    buf = PyString_AS_STRING(fname); 
-#endif    
+    // Take a copy of fname before Py_DECREF
+    buf = strdup(PyString_AS_STRING(fname));
+#endif
     if (PyCode_Check(pt->co)) {
+        // With debug build of Python this seems to wipe out fname
         Py_DECREF(fname);
     }
     return buf;
     tattr2 = PyObject_GetAttrString(tattr1, "__name__");
     if (!tattr2)
         goto err;
-        
+
 #ifdef IS_PY3K
     return PyBytes_AS_STRING(PyUnicode_AsUTF8String(tattr2));
 #else
     _hitem *it;
 
     it = hfind(contexts, (uintptr_t)ts);
-    if (!it) {        
+    if (!it) {
         // callback functions in some circumtances, can be called before the context entry is not
         // created. (See issue 21). To prevent this problem we need to ensure the context entry for
-        // the thread is always available here. 
-        return _profile_thread(ts);        
+        // the thread is always available here.
+        return _profile_thread(ts);
     }
     return (_ctx *)it->val;
 }
                 pit->co = PyString_FromFormat("<%s.%s>",
                                               modname,
                                               cfn->m_ml->ml_name);
-#endif                                              
+#endif
             } else {
 #ifdef IS_PY3K
                 pit->co = PyUnicode_FromFormat("<%s>",
         yerr("no context found or can be created.");
         return 0;
     }
-    
+
     switch (what) {
     case PyTrace_CALL:
         _call_enter(self, frame, arg, 0);
         _call_leave(self, frame, arg);
         break;
 
-#ifdef PyTrace_C_CALL	// not defined in Python <= 2.3 
+#ifdef PyTrace_C_CALL	// not defined in Python <= 2.3
     case PyTrace_C_CALL:
         if (PyCFunction_Check(arg))
             _call_enter(self, frame, arg, 1); // set ccall to true
     if (!ctx) {
         return NULL;
     }
-    
+
     // If a ThreadState object is destroyed, currently yappi does not
     // delete the associated resources. Instead, we rely on the fact that
     // the ThreadState objects are actually recycled. We are using pointer
     }
 
     _ensure_thread_profiled(PyThreadState_GET());
-    
+
 #ifdef IS_PY3K
     ev = PyBytes_AS_STRING(PyUnicode_AsUTF8String(event));
 #else
                           pt->callcount, pt->ttotal * tickfactor() * flags.timing_sample,
                           cumdiff * tickfactor() * flags.timing_sample);
 
+    // Finished with fname - freeing copy allocated in _item2fname
+    free(fname);
+
     return 0;
 }
 
                           cumdiff * tickfactor() * flags.timing_sample,
                           (pt->ttotal * tickfactor() * flags.timing_sample) / pt->callcount);
 
+    // Finished with fname - freeing copy allocated in _item2fname
+    free(fname);
+
     if (!si)
         return 1; // abort enumeration
     sni = (_statnode *)ymalloc(sizeof(_statnode));
     _yformat_string(tcname, temp, THREAD_NAME_LEN);
     _yformat_long(ctx->id, temp);
     _yformat_string(fname, temp, FUNC_NAME_LEN);
+
+    // Finished with fname - freeing copy allocated in _item2fname
+    free(fname);
+
     _yformat_ulong(ctx->sched_cnt, temp);
     _yformat_double(ctx->ttotal * tickfactor(), temp);
 
-#ifdef IS_PY3K  
-    buf = PyUnicode_FromString(temp);    
+#ifdef IS_PY3K
+    buf = PyUnicode_FromString(temp);
 #else
     buf = PyString_FromString(temp);
 #endif
 #endif
         goto err;
     }
-    
+
     henum(contexts, _ctxenumstat, (void *)li);
-    
+
 #ifdef IS_PY3K
     if (PyList_Append(li, PyUnicode_FromString(STAT_FOOTER_STR2)) < 0) {
 #else
-    if (PyList_Append(li, PyString_FromString(STAT_FOOTER_STR2)) < 0) {        
+    if (PyList_Append(li, PyString_FromString(STAT_FOOTER_STR2)) < 0) {
 #endif
         goto err;
     }
-    
+
     if (yapprunning) {
         appttotal = tickcount()-yappstarttick;
         prof_state = "running";
     m = Py_InitModule("_yappi",  yappi_methods);
     if (m == NULL)
         return;
-#endif        
+#endif
 
     d = PyModule_GetDict(m);
     YappiProfileError = PyErr_NewException("_yappi.error", NULL, NULL);
         return;
 #endif
     }
-    
+
 #ifdef IS_PY3K
     return m;
 #endif