Source file clang-analyzer cppcheck cpychecker gcc Notes
coverage-3.5.1b1/coverage/tracer.c 0 0 4 0 Incomplete coverage: 4 analysis failure(s)
python3-python-coverage-3.5.1-0.1.b1.fc17/coverage/tracer.c 0 0 5 0 Incomplete coverage: 4 analysis failure(s)

coverage-3.5.1b1/coverage/tracer.c

Location Tool Test ID Function Issue
coverage/tracer.c:458:1 cpychecker refcount-too-high Tracer_trace ob_refcnt of '*self' is 1 too high
coverage/tracer.c:458:1 cpychecker refcount-too-high Tracer_trace ob_refcnt of '*tracename' is 1 too high
coverage/tracer.c:532:5 cpychecker returns-NULL-without-setting-exception Tracer_call returning (PyObject*)NULL without setting an exception
coverage/tracer.c:609:35 cpychecker flags-within-PyMethodDef flags do not match callback signature for 'Tracer_get_stats' within PyMethodDef table

Incomplete coverage

Tool Location Function Message Data
cpychecker coverage/tracer.c:165:1 Tracer_dealloc Message(text='this function is too complicated for the reference-count checker to fully analyze: not all paths were analyzed') CustomFields([('maxtrans', 256)])
cpychecker coverage/tracer.c:256:1 Tracer_trace Message(text='this function is too complicated for the reference-count checker to fully analyze: not all paths were analyzed') CustomFields([('maxtrans', 256)])
cpychecker coverage/tracer.c:482:1 Tracer_call Message(text='this function is too complicated for the reference-count checker to fully analyze: not all paths were analyzed') CustomFields([('maxtrans', 256)])
cpychecker coverage/tracer.c:715:23 inittracer None CustomFields([('traceback', 'Traceback (most recent call last):\n File "/usr/lib/gcc/x86_64-redhat-linux/4.7.2/plugin/python2/libcpychecker/__init__.py", line 131, in _check_refcounts\n self.options)\n File "/usr/lib/gcc/x86_64-redhat-linux/4.7.2/plugin/python2/libcpychecker/refcounts.py", line 4355, in check_refcounts\n rep = impl_check_refcounts(ctxt, fun, options)\n File "/usr/lib/gcc/x86_64-redhat-linux/4.7.2/plugin/python2/libcpychecker/refcounts.py", line 4213, in impl_check_refcounts\n limits=limits)\n File "/usr/lib/gcc/x86_64-redhat-linux/4.7.2/plugin/python2/libcpychecker/absinterp.py", line 3089, in iter_traces\n depth + 1):\n File "/usr/lib/gcc/x86_64-redhat-linux/4.7.2/plugin/python2/libcpychecker/absinterp.py", line 3089, in iter_traces\n depth + 1):\n File "/usr/lib/gcc/x86_64-redhat-linux/4.7.2/plugin/python2/libcpychecker/absinterp.py", line 3089, in iter_traces\n depth + 1):\n File "/usr/lib/gcc/x86_64-redhat-linux/4.7.2/plugin/python2/libcpychecker/absinterp.py", line 3089, in iter_traces\n depth + 1):\n File "/usr/lib/gcc/x86_64-redhat-linux/4.7.2/plugin/python2/libcpychecker/absinterp.py", line 3089, in iter_traces\n depth + 1):\n File "/usr/lib/gcc/x86_64-redhat-linux/4.7.2/plugin/python2/libcpychecker/absinterp.py", line 3089, in iter_traces\n depth + 1):\n File "/usr/lib/gcc/x86_64-redhat-linux/4.7.2/plugin/python2/libcpychecker/absinterp.py", line 3089, in iter_traces\n depth + 1):\n File "/usr/lib/gcc/x86_64-redhat-linux/4.7.2/plugin/python2/libcpychecker/absinterp.py", line 3089, in iter_traces\n depth + 1):\n File "/usr/lib/gcc/x86_64-redhat-linux/4.7.2/plugin/python2/libcpychecker/absinterp.py", line 3089, in iter_traces\n depth + 1):\n File "/usr/lib/gcc/x86_64-redhat-linux/4.7.2/plugin/python2/libcpychecker/absinterp.py", line 3089, in iter_traces\n depth + 1):\n File "/usr/lib/gcc/x86_64-redhat-linux/4.7.2/plugin/python2/libcpychecker/absinterp.py", line 3089, in iter_traces\n depth + 1):\n File "/usr/lib/gcc/x86_64-redhat-linux/4.7.2/plugin/python2/libcpychecker/absinterp.py", line 3089, in iter_traces\n depth + 1):\n File "/usr/lib/gcc/x86_64-redhat-linux/4.7.2/plugin/python2/libcpychecker/absinterp.py", line 3053, in iter_traces\n transitions = curstate.get_transitions()\n File "/usr/lib/gcc/x86_64-redhat-linux/4.7.2/plugin/python2/libcpychecker/absinterp.py", line 2105, in get_transitions\n return self._get_transitions_for_stmt(stmt)\n File "/usr/lib/gcc/x86_64-redhat-linux/4.7.2/plugin/python2/libcpychecker/absinterp.py", line 2121, in _get_transitions_for_stmt\n return self._get_transitions_for_GimpleCall(stmt)\n File "/usr/lib/gcc/x86_64-redhat-linux/4.7.2/plugin/python2/libcpychecker/absinterp.py", line 2292, in _get_transitions_for_GimpleCall\n return meth(stmt, *args)\n File "/usr/lib/gcc/x86_64-redhat-linux/4.7.2/plugin/python2/libcpychecker/refcounts.py", line 2544, in impl_PyModule_AddObject\n s_success.cpython.steal_reference(v_value, stmt.loc)\n File "/usr/lib/gcc/x86_64-redhat-linux/4.7.2/plugin/python2/libcpychecker/refcounts.py", line 741, in steal_reference\n _steal_ref)\n File "/usr/lib/gcc/x86_64-redhat-linux/4.7.2/plugin/python2/libcpychecker/refcounts.py", line 551, in change_refcount\n check_isinstance(oldvalue, RefcountValue)\n File "/usr/lib/gcc/x86_64-redhat-linux/4.7.2/plugin/python2/gccutils.py", line 642, in check_isinstance\n raise TypeError(\'%s / %r is not an instance of %s\' % (obj, obj, types))\nTypeError: (long int)val [-0x7fffffffffffffff <= val <= 0x7fffffffffffffff] from coverage/tracer.c:714 / WithinRange(gcctype=\'long int\', loc=gcc.Location(file=\'coverage/tracer.c\', line=714), minvalue=-0x7fffffffffffffff, maxvalue=0x7fffffffffffffff) is not an instance of \n')])
  1 /* C-based Tracer for Coverage. */
  2 
  3 #include "Python.h"
  4 #include "compile.h"        /* in 2.3, this wasn't part of Python.h */
  5 #include "eval.h"           /* or this. */
  6 #include "structmember.h"
  7 #include "frameobject.h"
  8 
  9 /* Compile-time debugging helpers */
 10 #undef WHAT_LOG         /* Define to log the WHAT params in the trace function. */
 11 #undef TRACE_LOG        /* Define to log our bookkeeping. */
 12 #undef COLLECT_STATS    /* Collect counters: stats are printed when tracer is stopped. */
 13 
 14 #if COLLECT_STATS
 15 #define STATS(x)        x
 16 #else
 17 #define STATS(x)
 18 #endif
 19 
 20 /* Py 2.x and 3.x compatibility */
 21 
 22 #ifndef Py_TYPE
 23 #define Py_TYPE(o)    (((PyObject*)(o))->ob_type)
 24 #endif
 25 
 26 #if PY_MAJOR_VERSION >= 3
 27 
 28 #define MyText_Type         PyUnicode_Type
 29 #define MyText_Check(o)     PyUnicode_Check(o)
 30 #define MyText_AS_STRING(o) PyBytes_AS_STRING(PyUnicode_AsASCIIString(o))
 31 #define MyInt_FromLong(l)   PyLong_FromLong(l)
 32 
 33 #define MyType_HEAD_INIT    PyVarObject_HEAD_INIT(NULL, 0)
 34 
 35 #else
 36 
 37 #define MyText_Type         PyString_Type
 38 #define MyText_Check(o)     PyString_Check(o)
 39 #define MyText_AS_STRING(o) PyString_AS_STRING(o)
 40 #define MyInt_FromLong(l)   PyInt_FromLong(l)
 41 
 42 #define MyType_HEAD_INIT    PyObject_HEAD_INIT(NULL)  0,
 43 
 44 #endif /* Py3k */
 45 
 46 /* The values returned to indicate ok or error. */
 47 #define RET_OK      0
 48 #define RET_ERROR   -1
 49 
 50 /* An entry on the data stack.  For each call frame, we need to record the
 51     dictionary to capture data, and the last line number executed in that
 52     frame.
 53 */
 54 typedef struct {
 55     PyObject * file_data;  /* PyMem_Malloc'ed, a borrowed ref. */
 56     int last_line;
 57 } DataStackEntry;
 58 
 59 /* The Tracer type. */
 60 
 61 typedef struct {
 62     PyObject_HEAD
 63 
 64     /* Python objects manipulated directly by the Collector class. */
 65     PyObject * should_trace;
 66     PyObject * warn;
 67     PyObject * data;
 68     PyObject * should_trace_cache;
 69     PyObject * arcs;
 70 
 71     /* Has the tracer been started? */
 72     int started;
 73     /* Are we tracing arcs, or just lines? */
 74     int tracing_arcs;
 75 
 76     /*
 77         The data stack is a stack of dictionaries.  Each dictionary collects
 78         data for a single source file.  The data stack parallels the call stack:
 79         each call pushes the new frame's file data onto the data stack, and each
 80         return pops file data off.
 81 
 82         The file data is a dictionary whose form depends on the tracing options.
 83         If tracing arcs, the keys are line number pairs.  If not tracing arcs,
 84         the keys are line numbers.  In both cases, the value is irrelevant
 85         (None).
 86     */
 87     /* The index of the last-used entry in data_stack. */
 88     int depth;
 89     /* The file data at each level, or NULL if not recording. */
 90     DataStackEntry * data_stack;
 91     int data_stack_alloc;       /* number of entries allocated at data_stack. */
 92 
 93     /* The current file_data dictionary.  Borrowed. */
 94     PyObject * cur_file_data;
 95 
 96     /* The line number of the last line recorded, for tracing arcs.
 97         -1 means there was no previous line, as when entering a code object.
 98     */
 99     int last_line;
100 
101     /* The parent frame for the last exception event, to fix missing returns. */
102     PyFrameObject * last_exc_back;
103     int last_exc_firstlineno;
104 
105 #if COLLECT_STATS
106     struct {
107         unsigned int calls;
108         unsigned int lines;
109         unsigned int returns;
110         unsigned int exceptions;
111         unsigned int others;
112         unsigned int new_files;
113         unsigned int missed_returns;
114         unsigned int stack_reallocs;
115         unsigned int errors;
116     } stats;
117 #endif /* COLLECT_STATS */
118 } Tracer;
119 
120 #define STACK_DELTA    100
121 
122 static int
123 Tracer_init(Tracer *self, PyObject *args_unused, PyObject *kwds_unused)
124 {
125 #if COLLECT_STATS
126     self->stats.calls = 0;
127     self->stats.lines = 0;
128     self->stats.returns = 0;
129     self->stats.exceptions = 0;
130     self->stats.others = 0;
131     self->stats.new_files = 0;
132     self->stats.missed_returns = 0;
133     self->stats.stack_reallocs = 0;
134     self->stats.errors = 0;
135 #endif /* COLLECT_STATS */
136 
137     self->should_trace = NULL;
138     self->warn = NULL;
139     self->data = NULL;
140     self->should_trace_cache = NULL;
141     self->arcs = NULL;
142 
143     self->started = 0;
144     self->tracing_arcs = 0;
145 
146     self->depth = -1;
147     self->data_stack = PyMem_Malloc(STACK_DELTA*sizeof(DataStackEntry));
148     if (self->data_stack == NULL) {
149         STATS( self->stats.errors++; )
150         PyErr_NoMemory();
151         return RET_ERROR;
152     }
153     self->data_stack_alloc = STACK_DELTA;
154 
155     self->cur_file_data = NULL;
156     self->last_line = -1;
157 
158     self->last_exc_back = NULL;
159 
160     return RET_OK;
161 }
162 
163 static void
164 Tracer_dealloc(Tracer *self)
165 {
Failure runninng cpychecker (too-complicated)
Message
this function is too complicated for the reference-count checker to fully analyze: not all paths were analyzed
maxtrans: 256
166 if (self->started) { 167 PyEval_SetTrace(NULL, NULL); 168 } 169 170 Py_XDECREF(self->should_trace); 171 Py_XDECREF(self->warn); 172 Py_XDECREF(self->data); 173 Py_XDECREF(self->should_trace_cache); 174 175 PyMem_Free(self->data_stack); 176 177 Py_TYPE(self)->tp_free((PyObject*)self); 178 } 179 180 #if TRACE_LOG 181 static const char * 182 indent(int n) 183 { 184 static const char * spaces = 185 " " 186 " " 187 " " 188 " " 189 ; 190 return spaces + strlen(spaces) - n*2; 191 } 192 193 static int logging = 0; 194 /* Set these constants to be a file substring and line number to start logging. */ 195 static const char * start_file = "tests/views"; 196 static int start_line = 27; 197 198 static void 199 showlog(int depth, int lineno, PyObject * filename, const char * msg) 200 { 201 if (logging) { 202 printf("%s%3d ", indent(depth), depth); 203 if (lineno) { 204 printf("%4d", lineno); 205 } 206 else { 207 printf(" "); 208 } 209 if (filename) { 210 printf(" %s", MyText_AS_STRING(filename)); 211 } 212 if (msg) { 213 printf(" %s", msg); 214 } 215 printf("\n"); 216 } 217 } 218 219 #define SHOWLOG(a,b,c,d) showlog(a,b,c,d) 220 #else 221 #define SHOWLOG(a,b,c,d) 222 #endif /* TRACE_LOG */ 223 224 #if WHAT_LOG 225 static const char * what_sym[] = {"CALL", "EXC ", "LINE", "RET "}; 226 #endif 227 228 /* Record a pair of integers in self->cur_file_data. */ 229 static int 230 Tracer_record_pair(Tracer *self, int l1, int l2) 231 { 232 int ret = RET_OK; 233 234 PyObject * t = PyTuple_New(2); 235 if (t != NULL) { 236 PyTuple_SET_ITEM(t, 0, MyInt_FromLong(l1)); 237 PyTuple_SET_ITEM(t, 1, MyInt_FromLong(l2)); 238 if (PyDict_SetItem(self->cur_file_data, t, Py_None) < 0) { 239 STATS( self->stats.errors++; ) 240 ret = RET_ERROR; 241 } 242 Py_DECREF(t); 243 } 244 else { 245 STATS( self->stats.errors++; ) 246 ret = RET_ERROR; 247 } 248 return ret; 249 } 250 251 /* 252 * The Trace Function 253 */ 254 static int 255 Tracer_trace(Tracer *self, PyFrameObject *frame, int what, PyObject *arg_unused) 256 {
Failure runninng cpychecker (too-complicated)
Message
this function is too complicated for the reference-count checker to fully analyze: not all paths were analyzed
maxtrans: 256
257 int ret = RET_OK; 258 PyObject * filename = NULL; 259 PyObject * tracename = NULL; 260 261 #if WHAT_LOG 262 if (what <= sizeof(what_sym)/sizeof(const char *)) { 263 printf("trace: %s @ %s %d\n", what_sym[what], MyText_AS_STRING(frame->f_code->co_filename), frame->f_lineno); 264 } 265 #endif 266 267 #if TRACE_LOG 268 if (strstr(MyText_AS_STRING(frame->f_code->co_filename), start_file) && frame->f_lineno == start_line) { 269 logging = 1; 270 } 271 #endif 272 273 /* See below for details on missing-return detection. */ 274 if (self->last_exc_back) { 275 if (frame == self->last_exc_back) { 276 /* Looks like someone forgot to send a return event. We'll clear 277 the exception state and do the RETURN code here. Notice that the 278 frame we have in hand here is not the correct frame for the RETURN, 279 that frame is gone. Our handling for RETURN doesn't need the 280 actual frame, but we do log it, so that will look a little off if 281 you're looking at the detailed log. 282 283 If someday we need to examine the frame when doing RETURN, then 284 we'll need to keep more of the missed frame's state. 285 */ 286 STATS( self->stats.missed_returns++; ) 287 if (self->depth >= 0) { 288 if (self->tracing_arcs && self->cur_file_data) { 289 if (Tracer_record_pair(self, self->last_line, -self->last_exc_firstlineno) < 0) { 290 return RET_ERROR; 291 } 292 } 293 SHOWLOG(self->depth, frame->f_lineno, frame->f_code->co_filename, "missedreturn"); 294 self->cur_file_data = self->data_stack[self->depth].file_data; 295 self->last_line = self->data_stack[self->depth].last_line; 296 self->depth--; 297 } 298 } 299 self->last_exc_back = NULL; 300 } 301 302 303 switch (what) { 304 case PyTrace_CALL: /* 0 */ 305 STATS( self->stats.calls++; ) 306 /* Grow the stack. */ 307 self->depth++; 308 if (self->depth >= self->data_stack_alloc) { 309 STATS( self->stats.stack_reallocs++; ) 310 /* We've outgrown our data_stack array: make it bigger. */ 311 int bigger = self->data_stack_alloc + STACK_DELTA; 312 DataStackEntry * bigger_data_stack = PyMem_Realloc(self->data_stack, bigger * sizeof(DataStackEntry)); 313 if (bigger_data_stack == NULL) { 314 STATS( self->stats.errors++; ) 315 PyErr_NoMemory(); 316 self->depth--; 317 return RET_ERROR; 318 } 319 self->data_stack = bigger_data_stack; 320 self->data_stack_alloc = bigger; 321 } 322 323 /* Push the current state on the stack. */ 324 self->data_stack[self->depth].file_data = self->cur_file_data; 325 self->data_stack[self->depth].last_line = self->last_line; 326 327 /* Check if we should trace this line. */ 328 filename = frame->f_code->co_filename; 329 tracename = PyDict_GetItem(self->should_trace_cache, filename); 330 if (tracename == NULL) { 331 STATS( self->stats.new_files++; ) 332 /* We've never considered this file before. */ 333 /* Ask should_trace about it. */ 334 PyObject * args = Py_BuildValue("(OO)", filename, frame); 335 tracename = PyObject_Call(self->should_trace, args, NULL); 336 Py_DECREF(args); 337 if (tracename == NULL) { 338 /* An error occurred inside should_trace. */ 339 STATS( self->stats.errors++; ) 340 return RET_ERROR; 341 } 342 if (PyDict_SetItem(self->should_trace_cache, filename, tracename) < 0) { 343 STATS( self->stats.errors++; ) 344 return RET_ERROR; 345 } 346 } 347 else { 348 Py_INCREF(tracename); 349 } 350 351 /* If tracename is a string, then we're supposed to trace. */ 352 if (MyText_Check(tracename)) { 353 PyObject * file_data = PyDict_GetItem(self->data, tracename); 354 if (file_data == NULL) { 355 file_data = PyDict_New(); 356 if (file_data == NULL) { 357 STATS( self->stats.errors++; ) 358 return RET_ERROR; 359 } 360 ret = PyDict_SetItem(self->data, tracename, file_data); 361 Py_DECREF(file_data); 362 if (ret < 0) { 363 STATS( self->stats.errors++; ) 364 return RET_ERROR; 365 } 366 } 367 self->cur_file_data = file_data; 368 /* Make the frame right in case settrace(gettrace()) happens. */ 369 Py_INCREF(self); 370 frame->f_trace = (PyObject*)self; 371 SHOWLOG(self->depth, frame->f_lineno, filename, "traced"); 372 } 373 else { 374 self->cur_file_data = NULL; 375 SHOWLOG(self->depth, frame->f_lineno, filename, "skipped"); 376 } 377 378 Py_DECREF(tracename); 379 380 self->last_line = -1; 381 break; 382 383 case PyTrace_RETURN: /* 3 */ 384 STATS( self->stats.returns++; ) 385 /* A near-copy of this code is above in the missing-return handler. */ 386 if (self->depth >= 0) { 387 if (self->tracing_arcs && self->cur_file_data) { 388 int first = frame->f_code->co_firstlineno; 389 if (Tracer_record_pair(self, self->last_line, -first) < 0) { 390 return RET_ERROR; 391 } 392 } 393 394 SHOWLOG(self->depth, frame->f_lineno, frame->f_code->co_filename, "return"); 395 self->cur_file_data = self->data_stack[self->depth].file_data; 396 self->last_line = self->data_stack[self->depth].last_line; 397 self->depth--; 398 } 399 break; 400 401 case PyTrace_LINE: /* 2 */ 402 STATS( self->stats.lines++; ) 403 if (self->depth >= 0) { 404 SHOWLOG(self->depth, frame->f_lineno, frame->f_code->co_filename, "line"); 405 if (self->cur_file_data) { 406 /* We're tracing in this frame: record something. */ 407 if (self->tracing_arcs) { 408 /* Tracing arcs: key is (last_line,this_line). */ 409 if (Tracer_record_pair(self, self->last_line, frame->f_lineno) < 0) { 410 return RET_ERROR; 411 } 412 } 413 else { 414 /* Tracing lines: key is simply this_line. */ 415 PyObject * this_line = MyInt_FromLong(frame->f_lineno); 416 if (this_line == NULL) { 417 STATS( self->stats.errors++; ) 418 return RET_ERROR; 419 } 420 ret = PyDict_SetItem(self->cur_file_data, this_line, Py_None); 421 Py_DECREF(this_line); 422 if (ret < 0) { 423 STATS( self->stats.errors++; ) 424 return RET_ERROR; 425 } 426 } 427 } 428 self->last_line = frame->f_lineno; 429 } 430 break; 431 432 case PyTrace_EXCEPTION: 433 /* Some code (Python 2.3, and pyexpat anywhere) fires an exception event 434 without a return event. To detect that, we'll keep a copy of the 435 parent frame for an exception event. If the next event is in that 436 frame, then we must have returned without a return event. We can 437 synthesize the missing event then. 438 439 Python itself fixed this problem in 2.4. Pyexpat still has the bug. 440 I've reported the problem with pyexpat as http://bugs.python.org/issue6359 . 441 If it gets fixed, this code should still work properly. Maybe some day 442 the bug will be fixed everywhere coverage.py is supported, and we can 443 remove this missing-return detection. 444 445 More about this fix: http://nedbatchelder.com/blog/200907/a_nasty_little_bug.html 446 */ 447 STATS( self->stats.exceptions++; ) 448 self->last_exc_back = frame->f_back; 449 self->last_exc_firstlineno = frame->f_code->co_firstlineno; 450 break; 451 452 default: 453 STATS( self->stats.others++; ) 454 break; 455 } 456 457 return RET_OK; 458 }
ob_refcnt of '*self' is 1 too high
(emitted by cpychecker)

TODO: a detailed trace is available in the data model (not yet rendered in this report)

ob_refcnt of '*tracename' is 1 too high
(emitted by cpychecker)

TODO: a detailed trace is available in the data model (not yet rendered in this report)

459 460 /* 461 * Python has two ways to set the trace function: sys.settrace(fn), which 462 * takes a Python callable, and PyEval_SetTrace(func, obj), which takes 463 * a C function and a Python object. The way these work together is that 464 * sys.settrace(pyfn) calls PyEval_SetTrace(builtin_func, pyfn), using the 465 * Python callable as the object in PyEval_SetTrace. So sys.gettrace() 466 * simply returns the Python object used as the second argument to 467 * PyEval_SetTrace. So sys.gettrace() will return our self parameter, which 468 * means it must be callable to be used in sys.settrace(). 469 * 470 * So we make our self callable, equivalent to invoking our trace function. 471 * 472 * To help with the process of replaying stored frames, this function has an 473 * optional keyword argument: 474 * 475 * def Tracer_call(frame, event, arg, lineno=0) 476 * 477 * If provided, the lineno argument is used as the line number, and the 478 * frame's f_lineno member is ignored. 479 */ 480 static PyObject * 481 Tracer_call(Tracer *self, PyObject *args, PyObject *kwds) 482 {
Failure runninng cpychecker (too-complicated)
Message
this function is too complicated for the reference-count checker to fully analyze: not all paths were analyzed
maxtrans: 256
483 PyFrameObject *frame; 484 PyObject *what_str; 485 PyObject *arg; 486 int lineno = 0; 487 int what; 488 int orig_lineno; 489 PyObject *ret = NULL; 490 491 static char *what_names[] = { 492 "call", "exception", "line", "return", 493 "c_call", "c_exception", "c_return", 494 NULL 495 }; 496 497 #if WHAT_LOG 498 printf("pytrace\n"); 499 #endif 500 501 static char *kwlist[] = {"frame", "event", "arg", "lineno", NULL}; 502 503 if (!PyArg_ParseTupleAndKeywords(args, kwds, "O!O!O|i:Tracer_call", kwlist, 504 &PyFrame_Type, &frame, &MyText_Type, &what_str, &arg, &lineno)) { 505 goto done; 506 } 507 508 /* In Python, the what argument is a string, we need to find an int 509 for the C function. */ 510 for (what = 0; what_names[what]; what++) { 511 if (!strcmp(MyText_AS_STRING(what_str), what_names[what])) { 512 break; 513 } 514 } 515 516 /* Save off the frame's lineno, and use the forced one, if provided. */ 517 orig_lineno = frame->f_lineno; 518 if (lineno > 0) { 519 frame->f_lineno = lineno; 520 } 521 522 /* Invoke the C function, and return ourselves. */ 523 if (Tracer_trace(self, frame, what, arg) == RET_OK) { 524 Py_INCREF(self); 525 ret = (PyObject *)self; 526 } 527 528 /* Clean up. */ 529 frame->f_lineno = orig_lineno; 530 531 done: 532 return ret;
returning (PyObject*)NULL without setting an exception
(emitted by cpychecker)

TODO: a detailed trace is available in the data model (not yet rendered in this report)

533 } 534 535 static PyObject * 536 Tracer_start(Tracer *self, PyObject *args_unused) 537 { 538 PyEval_SetTrace((Py_tracefunc)Tracer_trace, (PyObject*)self); 539 self->started = 1; 540 self->tracing_arcs = self->arcs && PyObject_IsTrue(self->arcs); 541 self->last_line = -1; 542 543 /* start() returns a trace function usable with sys.settrace() */ 544 Py_INCREF(self); 545 return (PyObject *)self; 546 } 547 548 static PyObject * 549 Tracer_stop(Tracer *self, PyObject *args_unused) 550 { 551 if (self->started) { 552 PyEval_SetTrace(NULL, NULL); 553 self->started = 0; 554 } 555 556 return Py_BuildValue(""); 557 } 558 559 static PyObject * 560 Tracer_get_stats(Tracer *self) 561 { 562 #if COLLECT_STATS 563 return Py_BuildValue( 564 "{sI,sI,sI,sI,sI,sI,sI,sI,si,sI}", 565 "calls", self->stats.calls, 566 "lines", self->stats.lines, 567 "returns", self->stats.returns, 568 "exceptions", self->stats.exceptions, 569 "others", self->stats.others, 570 "new_files", self->stats.new_files, 571 "missed_returns", self->stats.missed_returns, 572 "stack_reallocs", self->stats.stack_reallocs, 573 "stack_alloc", self->data_stack_alloc, 574 "errors", self->stats.errors 575 ); 576 #else 577 return Py_BuildValue(""); 578 #endif /* COLLECT_STATS */ 579 } 580 581 static PyMemberDef 582 Tracer_members[] = { 583 { "should_trace", T_OBJECT, offsetof(Tracer, should_trace), 0, 584 PyDoc_STR("Function indicating whether to trace a file.") }, 585 586 { "warn", T_OBJECT, offsetof(Tracer, warn), 0, 587 PyDoc_STR("Function for issuing warnings.") }, 588 589 { "data", T_OBJECT, offsetof(Tracer, data), 0, 590 PyDoc_STR("The raw dictionary of trace data.") }, 591 592 { "should_trace_cache", T_OBJECT, offsetof(Tracer, should_trace_cache), 0, 593 PyDoc_STR("Dictionary caching should_trace results.") }, 594 595 { "arcs", T_OBJECT, offsetof(Tracer, arcs), 0, 596 PyDoc_STR("Should we trace arcs, or just lines?") }, 597 598 { NULL } 599 }; 600 601 static PyMethodDef 602 Tracer_methods[] = { 603 { "start", (PyCFunction) Tracer_start, METH_VARARGS, 604 PyDoc_STR("Start the tracer") }, 605 606 { "stop", (PyCFunction) Tracer_stop, METH_VARARGS, 607 PyDoc_STR("Stop the tracer") }, 608 609 { "get_stats", (PyCFunction) Tracer_get_stats, METH_VARARGS,
flags do not match callback signature for 'Tracer_get_stats' within PyMethodDef table
(emitted by cpychecker)
610 PyDoc_STR("Get statistics about the tracing") }, 611 612 { NULL } 613 }; 614 615 static PyTypeObject 616 TracerType = { 617 MyType_HEAD_INIT 618 "coverage.Tracer", /*tp_name*/ 619 sizeof(Tracer), /*tp_basicsize*/ 620 0, /*tp_itemsize*/ 621 (destructor)Tracer_dealloc, /*tp_dealloc*/ 622 0, /*tp_print*/ 623 0, /*tp_getattr*/ 624 0, /*tp_setattr*/ 625 0, /*tp_compare*/ 626 0, /*tp_repr*/ 627 0, /*tp_as_number*/ 628 0, /*tp_as_sequence*/ 629 0, /*tp_as_mapping*/ 630 0, /*tp_hash */ 631 (ternaryfunc)Tracer_call, /*tp_call*/ 632 0, /*tp_str*/ 633 0, /*tp_getattro*/ 634 0, /*tp_setattro*/ 635 0, /*tp_as_buffer*/ 636 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/ 637 "Tracer objects", /* tp_doc */ 638 0, /* tp_traverse */ 639 0, /* tp_clear */ 640 0, /* tp_richcompare */ 641 0, /* tp_weaklistoffset */ 642 0, /* tp_iter */ 643 0, /* tp_iternext */ 644 Tracer_methods, /* tp_methods */ 645 Tracer_members, /* tp_members */ 646 0, /* tp_getset */ 647 0, /* tp_base */ 648 0, /* tp_dict */ 649 0, /* tp_descr_get */ 650 0, /* tp_descr_set */ 651 0, /* tp_dictoffset */ 652 (initproc)Tracer_init, /* tp_init */ 653 0, /* tp_alloc */ 654 0, /* tp_new */ 655 }; 656 657 /* Module definition */ 658 659 #define MODULE_DOC PyDoc_STR("Fast coverage tracer.") 660 661 #if PY_MAJOR_VERSION >= 3 662 663 static PyModuleDef 664 moduledef = { 665 PyModuleDef_HEAD_INIT, 666 "coverage.tracer", 667 MODULE_DOC, 668 -1, 669 NULL, /* methods */ 670 NULL, 671 NULL, /* traverse */ 672 NULL, /* clear */ 673 NULL 674 }; 675 676 677 PyObject * 678 PyInit_tracer(void) 679 { 680 PyObject * mod = PyModule_Create(&moduledef); 681 if (mod == NULL) { 682 return NULL; 683 } 684 685 TracerType.tp_new = PyType_GenericNew; 686 if (PyType_Ready(&TracerType) < 0) { 687 Py_DECREF(mod); 688 return NULL; 689 } 690 691 Py_INCREF(&TracerType); 692 PyModule_AddObject(mod, "Tracer", (PyObject *)&TracerType); 693 694 return mod; 695 } 696 697 #else 698 699 void 700 inittracer(void) 701 { 702 PyObject * mod; 703 704 mod = Py_InitModule3("coverage.tracer", NULL, MODULE_DOC); 705 if (mod == NULL) { 706 return; 707 } 708 709 TracerType.tp_new = PyType_GenericNew; 710 if (PyType_Ready(&TracerType) < 0) { 711 return; 712 } 713 714 Py_INCREF(&TracerType); 715 PyModule_AddObject(mod, "Tracer", (PyObject *)&TracerType);
Failure runninng cpychecker (python-exception)
traceback: Traceback (most recent call last): File "/usr/lib/gcc/x86_64-redhat-linux/4.7.2/plugin/python2/libcpychecker/__init__.py", line 131, in _check_refcounts self.options) File "/usr/lib/gcc/x86_64-redhat-linux/4.7.2/plugin/python2/libcpychecker/refcounts.py", line 4355, in check_refcounts rep = impl_check_refcounts(ctxt, fun, options) File "/usr/lib/gcc/x86_64-redhat-linux/4.7.2/plugin/python2/libcpychecker/refcounts.py", line 4213, in impl_check_refcounts limits=limits) File "/usr/lib/gcc/x86_64-redhat-linux/4.7.2/plugin/python2/libcpychecker/absinterp.py", line 3089, in iter_traces depth + 1): File "/usr/lib/gcc/x86_64-redhat-linux/4.7.2/plugin/python2/libcpychecker/absinterp.py", line 3089, in iter_traces depth + 1): File "/usr/lib/gcc/x86_64-redhat-linux/4.7.2/plugin/python2/libcpychecker/absinterp.py", line 3089, in iter_traces depth + 1): File "/usr/lib/gcc/x86_64-redhat-linux/4.7.2/plugin/python2/libcpychecker/absinterp.py", line 3089, in iter_traces depth + 1): File "/usr/lib/gcc/x86_64-redhat-linux/4.7.2/plugin/python2/libcpychecker/absinterp.py", line 3089, in iter_traces depth + 1): File "/usr/lib/gcc/x86_64-redhat-linux/4.7.2/plugin/python2/libcpychecker/absinterp.py", line 3089, in iter_traces depth + 1): File "/usr/lib/gcc/x86_64-redhat-linux/4.7.2/plugin/python2/libcpychecker/absinterp.py", line 3089, in iter_traces depth + 1): File "/usr/lib/gcc/x86_64-redhat-linux/4.7.2/plugin/python2/libcpychecker/absinterp.py", line 3089, in iter_traces depth + 1): File "/usr/lib/gcc/x86_64-redhat-linux/4.7.2/plugin/python2/libcpychecker/absinterp.py", line 3089, in iter_traces depth + 1): File "/usr/lib/gcc/x86_64-redhat-linux/4.7.2/plugin/python2/libcpychecker/absinterp.py", line 3089, in iter_traces depth + 1): File "/usr/lib/gcc/x86_64-redhat-linux/4.7.2/plugin/python2/libcpychecker/absinterp.py", line 3089, in iter_traces depth + 1): File "/usr/lib/gcc/x86_64-redhat-linux/4.7.2/plugin/python2/libcpychecker/absinterp.py", line 3089, in iter_traces depth + 1): File "/usr/lib/gcc/x86_64-redhat-linux/4.7.2/plugin/python2/libcpychecker/absinterp.py", line 3053, in iter_traces transitions = curstate.get_transitions() File "/usr/lib/gcc/x86_64-redhat-linux/4.7.2/plugin/python2/libcpychecker/absinterp.py", line 2105, in get_transitions return self._get_transitions_for_stmt(stmt) File "/usr/lib/gcc/x86_64-redhat-linux/4.7.2/plugin/python2/libcpychecker/absinterp.py", line 2121, in _get_transitions_for_stmt return self._get_transitions_for_GimpleCall(stmt) File "/usr/lib/gcc/x86_64-redhat-linux/4.7.2/plugin/python2/libcpychecker/absinterp.py", line 2292, in _get_transitions_for_GimpleCall return meth(stmt, *args) File "/usr/lib/gcc/x86_64-redhat-linux/4.7.2/plugin/python2/libcpychecker/refcounts.py", line 2544, in impl_PyModule_AddObject s_success.cpython.steal_reference(v_value, stmt.loc) File "/usr/lib/gcc/x86_64-redhat-linux/4.7.2/plugin/python2/libcpychecker/refcounts.py", line 741, in steal_reference _steal_ref) File "/usr/lib/gcc/x86_64-redhat-linux/4.7.2/plugin/python2/libcpychecker/refcounts.py", line 551, in change_refcount check_isinstance(oldvalue, RefcountValue) File "/usr/lib/gcc/x86_64-redhat-linux/4.7.2/plugin/python2/gccutils.py", line 642, in check_isinstance raise TypeError('%s / %r is not an instance of %s' % (obj, obj, types)) TypeError: (long int)val [-0x7fffffffffffffff <= val <= 0x7fffffffffffffff] from coverage/tracer.c:714 / WithinRange(gcctype='long int', loc=gcc.Location(file='coverage/tracer.c', line=714), minvalue=-0x7fffffffffffffff, maxvalue=0x7fffffffffffffff) is not an instance of <class 'libcpychecker.refcounts.RefcountValue'>
716 } 717 718 #endif /* Py3k */

python3-python-coverage-3.5.1-0.1.b1.fc17/coverage/tracer.c

Location Tool Test ID Function Issue
coverage/tracer.c:458:1 cpychecker refcount-too-high Tracer_trace ob_refcnt of '*self' is 1 too high
coverage/tracer.c:458:1 cpychecker refcount-too-high Tracer_trace ob_refcnt of '*tracename' is 1 too high
coverage/tracer.c:532:5 cpychecker refcount-too-high Tracer_call ob_refcnt of new ref from (unknown) PyUnicodeUCS4_AsASCIIString is 1 too high
coverage/tracer.c:532:5 cpychecker returns-NULL-without-setting-exception Tracer_call returning (PyObject*)NULL without setting an exception
coverage/tracer.c:609:35 cpychecker flags-within-PyMethodDef flags do not match callback signature for 'Tracer_get_stats' within PyMethodDef table

Incomplete coverage

Tool Location Function Message Data
cpychecker coverage/tracer.c:165:1 Tracer_dealloc Message(text='this function is too complicated for the reference-count checker to fully analyze: not all paths were analyzed') CustomFields([('maxtrans', 256)])
cpychecker coverage/tracer.c:256:1 Tracer_trace Message(text='this function is too complicated for the reference-count checker to fully analyze: not all paths were analyzed') CustomFields([('maxtrans', 256)])
cpychecker coverage/tracer.c:482:1 Tracer_call Message(text='this function is too complicated for the reference-count checker to fully analyze: not all paths were analyzed') CustomFields([('maxtrans', 256)])
cpychecker coverage/tracer.c:692:23 PyInit_tracer None CustomFields([('traceback', 'Traceback (most recent call last):\n File "/usr/lib/gcc/x86_64-redhat-linux/4.7.2/plugin/python2/libcpychecker/__init__.py", line 131, in _check_refcounts\n self.options)\n File "/usr/lib/gcc/x86_64-redhat-linux/4.7.2/plugin/python2/libcpychecker/refcounts.py", line 4355, in check_refcounts\n rep = impl_check_refcounts(ctxt, fun, options)\n File "/usr/lib/gcc/x86_64-redhat-linux/4.7.2/plugin/python2/libcpychecker/refcounts.py", line 4213, in impl_check_refcounts\n limits=limits)\n File "/usr/lib/gcc/x86_64-redhat-linux/4.7.2/plugin/python2/libcpychecker/absinterp.py", line 3089, in iter_traces\n depth + 1):\n File "/usr/lib/gcc/x86_64-redhat-linux/4.7.2/plugin/python2/libcpychecker/absinterp.py", line 3089, in iter_traces\n depth + 1):\n File "/usr/lib/gcc/x86_64-redhat-linux/4.7.2/plugin/python2/libcpychecker/absinterp.py", line 3089, in iter_traces\n depth + 1):\n File "/usr/lib/gcc/x86_64-redhat-linux/4.7.2/plugin/python2/libcpychecker/absinterp.py", line 3089, in iter_traces\n depth + 1):\n File "/usr/lib/gcc/x86_64-redhat-linux/4.7.2/plugin/python2/libcpychecker/absinterp.py", line 3089, in iter_traces\n depth + 1):\n File "/usr/lib/gcc/x86_64-redhat-linux/4.7.2/plugin/python2/libcpychecker/absinterp.py", line 3089, in iter_traces\n depth + 1):\n File "/usr/lib/gcc/x86_64-redhat-linux/4.7.2/plugin/python2/libcpychecker/absinterp.py", line 3089, in iter_traces\n depth + 1):\n File "/usr/lib/gcc/x86_64-redhat-linux/4.7.2/plugin/python2/libcpychecker/absinterp.py", line 3089, in iter_traces\n depth + 1):\n File "/usr/lib/gcc/x86_64-redhat-linux/4.7.2/plugin/python2/libcpychecker/absinterp.py", line 3089, in iter_traces\n depth + 1):\n File "/usr/lib/gcc/x86_64-redhat-linux/4.7.2/plugin/python2/libcpychecker/absinterp.py", line 3089, in iter_traces\n depth + 1):\n File "/usr/lib/gcc/x86_64-redhat-linux/4.7.2/plugin/python2/libcpychecker/absinterp.py", line 3089, in iter_traces\n depth + 1):\n File "/usr/lib/gcc/x86_64-redhat-linux/4.7.2/plugin/python2/libcpychecker/absinterp.py", line 3089, in iter_traces\n depth + 1):\n File "/usr/lib/gcc/x86_64-redhat-linux/4.7.2/plugin/python2/libcpychecker/absinterp.py", line 3053, in iter_traces\n transitions = curstate.get_transitions()\n File "/usr/lib/gcc/x86_64-redhat-linux/4.7.2/plugin/python2/libcpychecker/absinterp.py", line 2105, in get_transitions\n return self._get_transitions_for_stmt(stmt)\n File "/usr/lib/gcc/x86_64-redhat-linux/4.7.2/plugin/python2/libcpychecker/absinterp.py", line 2121, in _get_transitions_for_stmt\n return self._get_transitions_for_GimpleCall(stmt)\n File "/usr/lib/gcc/x86_64-redhat-linux/4.7.2/plugin/python2/libcpychecker/absinterp.py", line 2292, in _get_transitions_for_GimpleCall\n return meth(stmt, *args)\n File "/usr/lib/gcc/x86_64-redhat-linux/4.7.2/plugin/python2/libcpychecker/refcounts.py", line 2544, in impl_PyModule_AddObject\n s_success.cpython.steal_reference(v_value, stmt.loc)\n File "/usr/lib/gcc/x86_64-redhat-linux/4.7.2/plugin/python2/libcpychecker/refcounts.py", line 741, in steal_reference\n _steal_ref)\n File "/usr/lib/gcc/x86_64-redhat-linux/4.7.2/plugin/python2/libcpychecker/refcounts.py", line 551, in change_refcount\n check_isinstance(oldvalue, RefcountValue)\n File "/usr/lib/gcc/x86_64-redhat-linux/4.7.2/plugin/python2/gccutils.py", line 642, in check_isinstance\n raise TypeError(\'%s / %r is not an instance of %s\' % (obj, obj, types))\nTypeError: (long int)val [-0x7fffffffffffffff <= val <= 0x7fffffffffffffff] from coverage/tracer.c:691 / WithinRange(gcctype=\'long int\', loc=gcc.Location(file=\'coverage/tracer.c\', line=691), minvalue=-0x7fffffffffffffff, maxvalue=0x7fffffffffffffff) is not an instance of \n')])
  1 /* C-based Tracer for Coverage. */
  2 
  3 #include "Python.h"
  4 #include "compile.h"        /* in 2.3, this wasn't part of Python.h */
  5 #include "eval.h"           /* or this. */
  6 #include "structmember.h"
  7 #include "frameobject.h"
  8 
  9 /* Compile-time debugging helpers */
 10 #undef WHAT_LOG         /* Define to log the WHAT params in the trace function. */
 11 #undef TRACE_LOG        /* Define to log our bookkeeping. */
 12 #undef COLLECT_STATS    /* Collect counters: stats are printed when tracer is stopped. */
 13 
 14 #if COLLECT_STATS
 15 #define STATS(x)        x
 16 #else
 17 #define STATS(x)
 18 #endif
 19 
 20 /* Py 2.x and 3.x compatibility */
 21 
 22 #ifndef Py_TYPE
 23 #define Py_TYPE(o)    (((PyObject*)(o))->ob_type)
 24 #endif
 25 
 26 #if PY_MAJOR_VERSION >= 3
 27 
 28 #define MyText_Type         PyUnicode_Type
 29 #define MyText_Check(o)     PyUnicode_Check(o)
 30 #define MyText_AS_STRING(o) PyBytes_AS_STRING(PyUnicode_AsASCIIString(o))
 31 #define MyInt_FromLong(l)   PyLong_FromLong(l)
 32 
 33 #define MyType_HEAD_INIT    PyVarObject_HEAD_INIT(NULL, 0)
 34 
 35 #else
 36 
 37 #define MyText_Type         PyString_Type
 38 #define MyText_Check(o)     PyString_Check(o)
 39 #define MyText_AS_STRING(o) PyString_AS_STRING(o)
 40 #define MyInt_FromLong(l)   PyInt_FromLong(l)
 41 
 42 #define MyType_HEAD_INIT    PyObject_HEAD_INIT(NULL)  0,
 43 
 44 #endif /* Py3k */
 45 
 46 /* The values returned to indicate ok or error. */
 47 #define RET_OK      0
 48 #define RET_ERROR   -1
 49 
 50 /* An entry on the data stack.  For each call frame, we need to record the
 51     dictionary to capture data, and the last line number executed in that
 52     frame.
 53 */
 54 typedef struct {
 55     PyObject * file_data;  /* PyMem_Malloc'ed, a borrowed ref. */
 56     int last_line;
 57 } DataStackEntry;
 58 
 59 /* The Tracer type. */
 60 
 61 typedef struct {
 62     PyObject_HEAD
 63 
 64     /* Python objects manipulated directly by the Collector class. */
 65     PyObject * should_trace;
 66     PyObject * warn;
 67     PyObject * data;
 68     PyObject * should_trace_cache;
 69     PyObject * arcs;
 70 
 71     /* Has the tracer been started? */
 72     int started;
 73     /* Are we tracing arcs, or just lines? */
 74     int tracing_arcs;
 75 
 76     /*
 77         The data stack is a stack of dictionaries.  Each dictionary collects
 78         data for a single source file.  The data stack parallels the call stack:
 79         each call pushes the new frame's file data onto the data stack, and each
 80         return pops file data off.
 81 
 82         The file data is a dictionary whose form depends on the tracing options.
 83         If tracing arcs, the keys are line number pairs.  If not tracing arcs,
 84         the keys are line numbers.  In both cases, the value is irrelevant
 85         (None).
 86     */
 87     /* The index of the last-used entry in data_stack. */
 88     int depth;
 89     /* The file data at each level, or NULL if not recording. */
 90     DataStackEntry * data_stack;
 91     int data_stack_alloc;       /* number of entries allocated at data_stack. */
 92 
 93     /* The current file_data dictionary.  Borrowed. */
 94     PyObject * cur_file_data;
 95 
 96     /* The line number of the last line recorded, for tracing arcs.
 97         -1 means there was no previous line, as when entering a code object.
 98     */
 99     int last_line;
100 
101     /* The parent frame for the last exception event, to fix missing returns. */
102     PyFrameObject * last_exc_back;
103     int last_exc_firstlineno;
104 
105 #if COLLECT_STATS
106     struct {
107         unsigned int calls;
108         unsigned int lines;
109         unsigned int returns;
110         unsigned int exceptions;
111         unsigned int others;
112         unsigned int new_files;
113         unsigned int missed_returns;
114         unsigned int stack_reallocs;
115         unsigned int errors;
116     } stats;
117 #endif /* COLLECT_STATS */
118 } Tracer;
119 
120 #define STACK_DELTA    100
121 
122 static int
123 Tracer_init(Tracer *self, PyObject *args_unused, PyObject *kwds_unused)
124 {
125 #if COLLECT_STATS
126     self->stats.calls = 0;
127     self->stats.lines = 0;
128     self->stats.returns = 0;
129     self->stats.exceptions = 0;
130     self->stats.others = 0;
131     self->stats.new_files = 0;
132     self->stats.missed_returns = 0;
133     self->stats.stack_reallocs = 0;
134     self->stats.errors = 0;
135 #endif /* COLLECT_STATS */
136 
137     self->should_trace = NULL;
138     self->warn = NULL;
139     self->data = NULL;
140     self->should_trace_cache = NULL;
141     self->arcs = NULL;
142 
143     self->started = 0;
144     self->tracing_arcs = 0;
145 
146     self->depth = -1;
147     self->data_stack = PyMem_Malloc(STACK_DELTA*sizeof(DataStackEntry));
148     if (self->data_stack == NULL) {
149         STATS( self->stats.errors++; )
150         PyErr_NoMemory();
151         return RET_ERROR;
152     }
153     self->data_stack_alloc = STACK_DELTA;
154 
155     self->cur_file_data = NULL;
156     self->last_line = -1;
157 
158     self->last_exc_back = NULL;
159 
160     return RET_OK;
161 }
162 
163 static void
164 Tracer_dealloc(Tracer *self)
165 {
Failure runninng cpychecker (too-complicated)
Message
this function is too complicated for the reference-count checker to fully analyze: not all paths were analyzed
maxtrans: 256
166 if (self->started) { 167 PyEval_SetTrace(NULL, NULL); 168 } 169 170 Py_XDECREF(self->should_trace); 171 Py_XDECREF(self->warn); 172 Py_XDECREF(self->data); 173 Py_XDECREF(self->should_trace_cache); 174 175 PyMem_Free(self->data_stack); 176 177 Py_TYPE(self)->tp_free((PyObject*)self); 178 } 179 180 #if TRACE_LOG 181 static const char * 182 indent(int n) 183 { 184 static const char * spaces = 185 " " 186 " " 187 " " 188 " " 189 ; 190 return spaces + strlen(spaces) - n*2; 191 } 192 193 static int logging = 0; 194 /* Set these constants to be a file substring and line number to start logging. */ 195 static const char * start_file = "tests/views"; 196 static int start_line = 27; 197 198 static void 199 showlog(int depth, int lineno, PyObject * filename, const char * msg) 200 { 201 if (logging) { 202 printf("%s%3d ", indent(depth), depth); 203 if (lineno) { 204 printf("%4d", lineno); 205 } 206 else { 207 printf(" "); 208 } 209 if (filename) { 210 printf(" %s", MyText_AS_STRING(filename)); 211 } 212 if (msg) { 213 printf(" %s", msg); 214 } 215 printf("\n"); 216 } 217 } 218 219 #define SHOWLOG(a,b,c,d) showlog(a,b,c,d) 220 #else 221 #define SHOWLOG(a,b,c,d) 222 #endif /* TRACE_LOG */ 223 224 #if WHAT_LOG 225 static const char * what_sym[] = {"CALL", "EXC ", "LINE", "RET "}; 226 #endif 227 228 /* Record a pair of integers in self->cur_file_data. */ 229 static int 230 Tracer_record_pair(Tracer *self, int l1, int l2) 231 { 232 int ret = RET_OK; 233 234 PyObject * t = PyTuple_New(2); 235 if (t != NULL) { 236 PyTuple_SET_ITEM(t, 0, MyInt_FromLong(l1)); 237 PyTuple_SET_ITEM(t, 1, MyInt_FromLong(l2)); 238 if (PyDict_SetItem(self->cur_file_data, t, Py_None) < 0) { 239 STATS( self->stats.errors++; ) 240 ret = RET_ERROR; 241 } 242 Py_DECREF(t); 243 } 244 else { 245 STATS( self->stats.errors++; ) 246 ret = RET_ERROR; 247 } 248 return ret; 249 } 250 251 /* 252 * The Trace Function 253 */ 254 static int 255 Tracer_trace(Tracer *self, PyFrameObject *frame, int what, PyObject *arg_unused) 256 {
Failure runninng cpychecker (too-complicated)
Message
this function is too complicated for the reference-count checker to fully analyze: not all paths were analyzed
maxtrans: 256
257 int ret = RET_OK; 258 PyObject * filename = NULL; 259 PyObject * tracename = NULL; 260 261 #if WHAT_LOG 262 if (what <= sizeof(what_sym)/sizeof(const char *)) { 263 printf("trace: %s @ %s %d\n", what_sym[what], MyText_AS_STRING(frame->f_code->co_filename), frame->f_lineno); 264 } 265 #endif 266 267 #if TRACE_LOG 268 if (strstr(MyText_AS_STRING(frame->f_code->co_filename), start_file) && frame->f_lineno == start_line) { 269 logging = 1; 270 } 271 #endif 272 273 /* See below for details on missing-return detection. */ 274 if (self->last_exc_back) { 275 if (frame == self->last_exc_back) { 276 /* Looks like someone forgot to send a return event. We'll clear 277 the exception state and do the RETURN code here. Notice that the 278 frame we have in hand here is not the correct frame for the RETURN, 279 that frame is gone. Our handling for RETURN doesn't need the 280 actual frame, but we do log it, so that will look a little off if 281 you're looking at the detailed log. 282 283 If someday we need to examine the frame when doing RETURN, then 284 we'll need to keep more of the missed frame's state. 285 */ 286 STATS( self->stats.missed_returns++; ) 287 if (self->depth >= 0) { 288 if (self->tracing_arcs && self->cur_file_data) { 289 if (Tracer_record_pair(self, self->last_line, -self->last_exc_firstlineno) < 0) { 290 return RET_ERROR; 291 } 292 } 293 SHOWLOG(self->depth, frame->f_lineno, frame->f_code->co_filename, "missedreturn"); 294 self->cur_file_data = self->data_stack[self->depth].file_data; 295 self->last_line = self->data_stack[self->depth].last_line; 296 self->depth--; 297 } 298 } 299 self->last_exc_back = NULL; 300 } 301 302 303 switch (what) { 304 case PyTrace_CALL: /* 0 */ 305 STATS( self->stats.calls++; ) 306 /* Grow the stack. */ 307 self->depth++; 308 if (self->depth >= self->data_stack_alloc) { 309 STATS( self->stats.stack_reallocs++; ) 310 /* We've outgrown our data_stack array: make it bigger. */ 311 int bigger = self->data_stack_alloc + STACK_DELTA; 312 DataStackEntry * bigger_data_stack = PyMem_Realloc(self->data_stack, bigger * sizeof(DataStackEntry)); 313 if (bigger_data_stack == NULL) { 314 STATS( self->stats.errors++; ) 315 PyErr_NoMemory(); 316 self->depth--; 317 return RET_ERROR; 318 } 319 self->data_stack = bigger_data_stack; 320 self->data_stack_alloc = bigger; 321 } 322 323 /* Push the current state on the stack. */ 324 self->data_stack[self->depth].file_data = self->cur_file_data; 325 self->data_stack[self->depth].last_line = self->last_line; 326 327 /* Check if we should trace this line. */ 328 filename = frame->f_code->co_filename; 329 tracename = PyDict_GetItem(self->should_trace_cache, filename); 330 if (tracename == NULL) { 331 STATS( self->stats.new_files++; ) 332 /* We've never considered this file before. */ 333 /* Ask should_trace about it. */ 334 PyObject * args = Py_BuildValue("(OO)", filename, frame); 335 tracename = PyObject_Call(self->should_trace, args, NULL); 336 Py_DECREF(args); 337 if (tracename == NULL) { 338 /* An error occurred inside should_trace. */ 339 STATS( self->stats.errors++; ) 340 return RET_ERROR; 341 } 342 if (PyDict_SetItem(self->should_trace_cache, filename, tracename) < 0) { 343 STATS( self->stats.errors++; ) 344 return RET_ERROR; 345 } 346 } 347 else { 348 Py_INCREF(tracename); 349 } 350 351 /* If tracename is a string, then we're supposed to trace. */ 352 if (MyText_Check(tracename)) { 353 PyObject * file_data = PyDict_GetItem(self->data, tracename); 354 if (file_data == NULL) { 355 file_data = PyDict_New(); 356 if (file_data == NULL) { 357 STATS( self->stats.errors++; ) 358 return RET_ERROR; 359 } 360 ret = PyDict_SetItem(self->data, tracename, file_data); 361 Py_DECREF(file_data); 362 if (ret < 0) { 363 STATS( self->stats.errors++; ) 364 return RET_ERROR; 365 } 366 } 367 self->cur_file_data = file_data; 368 /* Make the frame right in case settrace(gettrace()) happens. */ 369 Py_INCREF(self); 370 frame->f_trace = (PyObject*)self; 371 SHOWLOG(self->depth, frame->f_lineno, filename, "traced"); 372 } 373 else { 374 self->cur_file_data = NULL; 375 SHOWLOG(self->depth, frame->f_lineno, filename, "skipped"); 376 } 377 378 Py_DECREF(tracename); 379 380 self->last_line = -1; 381 break; 382 383 case PyTrace_RETURN: /* 3 */ 384 STATS( self->stats.returns++; ) 385 /* A near-copy of this code is above in the missing-return handler. */ 386 if (self->depth >= 0) { 387 if (self->tracing_arcs && self->cur_file_data) { 388 int first = frame->f_code->co_firstlineno; 389 if (Tracer_record_pair(self, self->last_line, -first) < 0) { 390 return RET_ERROR; 391 } 392 } 393 394 SHOWLOG(self->depth, frame->f_lineno, frame->f_code->co_filename, "return"); 395 self->cur_file_data = self->data_stack[self->depth].file_data; 396 self->last_line = self->data_stack[self->depth].last_line; 397 self->depth--; 398 } 399 break; 400 401 case PyTrace_LINE: /* 2 */ 402 STATS( self->stats.lines++; ) 403 if (self->depth >= 0) { 404 SHOWLOG(self->depth, frame->f_lineno, frame->f_code->co_filename, "line"); 405 if (self->cur_file_data) { 406 /* We're tracing in this frame: record something. */ 407 if (self->tracing_arcs) { 408 /* Tracing arcs: key is (last_line,this_line). */ 409 if (Tracer_record_pair(self, self->last_line, frame->f_lineno) < 0) { 410 return RET_ERROR; 411 } 412 } 413 else { 414 /* Tracing lines: key is simply this_line. */ 415 PyObject * this_line = MyInt_FromLong(frame->f_lineno); 416 if (this_line == NULL) { 417 STATS( self->stats.errors++; ) 418 return RET_ERROR; 419 } 420 ret = PyDict_SetItem(self->cur_file_data, this_line, Py_None); 421 Py_DECREF(this_line); 422 if (ret < 0) { 423 STATS( self->stats.errors++; ) 424 return RET_ERROR; 425 } 426 } 427 } 428 self->last_line = frame->f_lineno; 429 } 430 break; 431 432 case PyTrace_EXCEPTION: 433 /* Some code (Python 2.3, and pyexpat anywhere) fires an exception event 434 without a return event. To detect that, we'll keep a copy of the 435 parent frame for an exception event. If the next event is in that 436 frame, then we must have returned without a return event. We can 437 synthesize the missing event then. 438 439 Python itself fixed this problem in 2.4. Pyexpat still has the bug. 440 I've reported the problem with pyexpat as http://bugs.python.org/issue6359 . 441 If it gets fixed, this code should still work properly. Maybe some day 442 the bug will be fixed everywhere coverage.py is supported, and we can 443 remove this missing-return detection. 444 445 More about this fix: http://nedbatchelder.com/blog/200907/a_nasty_little_bug.html 446 */ 447 STATS( self->stats.exceptions++; ) 448 self->last_exc_back = frame->f_back; 449 self->last_exc_firstlineno = frame->f_code->co_firstlineno; 450 break; 451 452 default: 453 STATS( self->stats.others++; ) 454 break; 455 } 456 457 return RET_OK; 458 }
ob_refcnt of '*self' is 1 too high
(emitted by cpychecker)

TODO: a detailed trace is available in the data model (not yet rendered in this report)

ob_refcnt of '*tracename' is 1 too high
(emitted by cpychecker)

TODO: a detailed trace is available in the data model (not yet rendered in this report)

459 460 /* 461 * Python has two ways to set the trace function: sys.settrace(fn), which 462 * takes a Python callable, and PyEval_SetTrace(func, obj), which takes 463 * a C function and a Python object. The way these work together is that 464 * sys.settrace(pyfn) calls PyEval_SetTrace(builtin_func, pyfn), using the 465 * Python callable as the object in PyEval_SetTrace. So sys.gettrace() 466 * simply returns the Python object used as the second argument to 467 * PyEval_SetTrace. So sys.gettrace() will return our self parameter, which 468 * means it must be callable to be used in sys.settrace(). 469 * 470 * So we make our self callable, equivalent to invoking our trace function. 471 * 472 * To help with the process of replaying stored frames, this function has an 473 * optional keyword argument: 474 * 475 * def Tracer_call(frame, event, arg, lineno=0) 476 * 477 * If provided, the lineno argument is used as the line number, and the 478 * frame's f_lineno member is ignored. 479 */ 480 static PyObject * 481 Tracer_call(Tracer *self, PyObject *args, PyObject *kwds) 482 {
Failure runninng cpychecker (too-complicated)
Message
this function is too complicated for the reference-count checker to fully analyze: not all paths were analyzed
maxtrans: 256
483 PyFrameObject *frame; 484 PyObject *what_str; 485 PyObject *arg; 486 int lineno = 0; 487 int what; 488 int orig_lineno; 489 PyObject *ret = NULL; 490 491 static char *what_names[] = { 492 "call", "exception", "line", "return", 493 "c_call", "c_exception", "c_return", 494 NULL 495 }; 496 497 #if WHAT_LOG 498 printf("pytrace\n"); 499 #endif 500 501 static char *kwlist[] = {"frame", "event", "arg", "lineno", NULL}; 502 503 if (!PyArg_ParseTupleAndKeywords(args, kwds, "O!O!O|i:Tracer_call", kwlist, 504 &PyFrame_Type, &frame, &MyText_Type, &what_str, &arg, &lineno)) { 505 goto done; 506 } 507 508 /* In Python, the what argument is a string, we need to find an int 509 for the C function. */ 510 for (what = 0; what_names[what]; what++) { 511 if (!strcmp(MyText_AS_STRING(what_str), what_names[what])) { 512 break; 513 } 514 } 515 516 /* Save off the frame's lineno, and use the forced one, if provided. */ 517 orig_lineno = frame->f_lineno; 518 if (lineno > 0) { 519 frame->f_lineno = lineno; 520 } 521 522 /* Invoke the C function, and return ourselves. */ 523 if (Tracer_trace(self, frame, what, arg) == RET_OK) { 524 Py_INCREF(self); 525 ret = (PyObject *)self; 526 } 527 528 /* Clean up. */ 529 frame->f_lineno = orig_lineno; 530 531 done: 532 return ret;
ob_refcnt of new ref from (unknown) PyUnicodeUCS4_AsASCIIString is 1 too high
(emitted by cpychecker)

TODO: a detailed trace is available in the data model (not yet rendered in this report)

returning (PyObject*)NULL without setting an exception
(emitted by cpychecker)

TODO: a detailed trace is available in the data model (not yet rendered in this report)

533 } 534 535 static PyObject * 536 Tracer_start(Tracer *self, PyObject *args_unused) 537 { 538 PyEval_SetTrace((Py_tracefunc)Tracer_trace, (PyObject*)self); 539 self->started = 1; 540 self->tracing_arcs = self->arcs && PyObject_IsTrue(self->arcs); 541 self->last_line = -1; 542 543 /* start() returns a trace function usable with sys.settrace() */ 544 Py_INCREF(self); 545 return (PyObject *)self; 546 } 547 548 static PyObject * 549 Tracer_stop(Tracer *self, PyObject *args_unused) 550 { 551 if (self->started) { 552 PyEval_SetTrace(NULL, NULL); 553 self->started = 0; 554 } 555 556 return Py_BuildValue(""); 557 } 558 559 static PyObject * 560 Tracer_get_stats(Tracer *self) 561 { 562 #if COLLECT_STATS 563 return Py_BuildValue( 564 "{sI,sI,sI,sI,sI,sI,sI,sI,si,sI}", 565 "calls", self->stats.calls, 566 "lines", self->stats.lines, 567 "returns", self->stats.returns, 568 "exceptions", self->stats.exceptions, 569 "others", self->stats.others, 570 "new_files", self->stats.new_files, 571 "missed_returns", self->stats.missed_returns, 572 "stack_reallocs", self->stats.stack_reallocs, 573 "stack_alloc", self->data_stack_alloc, 574 "errors", self->stats.errors 575 ); 576 #else 577 return Py_BuildValue(""); 578 #endif /* COLLECT_STATS */ 579 } 580 581 static PyMemberDef 582 Tracer_members[] = { 583 { "should_trace", T_OBJECT, offsetof(Tracer, should_trace), 0, 584 PyDoc_STR("Function indicating whether to trace a file.") }, 585 586 { "warn", T_OBJECT, offsetof(Tracer, warn), 0, 587 PyDoc_STR("Function for issuing warnings.") }, 588 589 { "data", T_OBJECT, offsetof(Tracer, data), 0, 590 PyDoc_STR("The raw dictionary of trace data.") }, 591 592 { "should_trace_cache", T_OBJECT, offsetof(Tracer, should_trace_cache), 0, 593 PyDoc_STR("Dictionary caching should_trace results.") }, 594 595 { "arcs", T_OBJECT, offsetof(Tracer, arcs), 0, 596 PyDoc_STR("Should we trace arcs, or just lines?") }, 597 598 { NULL } 599 }; 600 601 static PyMethodDef 602 Tracer_methods[] = { 603 { "start", (PyCFunction) Tracer_start, METH_VARARGS, 604 PyDoc_STR("Start the tracer") }, 605 606 { "stop", (PyCFunction) Tracer_stop, METH_VARARGS, 607 PyDoc_STR("Stop the tracer") }, 608 609 { "get_stats", (PyCFunction) Tracer_get_stats, METH_VARARGS,
flags do not match callback signature for 'Tracer_get_stats' within PyMethodDef table
(emitted by cpychecker)
610 PyDoc_STR("Get statistics about the tracing") }, 611 612 { NULL } 613 }; 614 615 static PyTypeObject 616 TracerType = { 617 MyType_HEAD_INIT 618 "coverage.Tracer", /*tp_name*/ 619 sizeof(Tracer), /*tp_basicsize*/ 620 0, /*tp_itemsize*/ 621 (destructor)Tracer_dealloc, /*tp_dealloc*/ 622 0, /*tp_print*/ 623 0, /*tp_getattr*/ 624 0, /*tp_setattr*/ 625 0, /*tp_compare*/ 626 0, /*tp_repr*/ 627 0, /*tp_as_number*/ 628 0, /*tp_as_sequence*/ 629 0, /*tp_as_mapping*/ 630 0, /*tp_hash */ 631 (ternaryfunc)Tracer_call, /*tp_call*/ 632 0, /*tp_str*/ 633 0, /*tp_getattro*/ 634 0, /*tp_setattro*/ 635 0, /*tp_as_buffer*/ 636 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/ 637 "Tracer objects", /* tp_doc */ 638 0, /* tp_traverse */ 639 0, /* tp_clear */ 640 0, /* tp_richcompare */ 641 0, /* tp_weaklistoffset */ 642 0, /* tp_iter */ 643 0, /* tp_iternext */ 644 Tracer_methods, /* tp_methods */ 645 Tracer_members, /* tp_members */ 646 0, /* tp_getset */ 647 0, /* tp_base */ 648 0, /* tp_dict */ 649 0, /* tp_descr_get */ 650 0, /* tp_descr_set */ 651 0, /* tp_dictoffset */ 652 (initproc)Tracer_init, /* tp_init */ 653 0, /* tp_alloc */ 654 0, /* tp_new */ 655 }; 656 657 /* Module definition */ 658 659 #define MODULE_DOC PyDoc_STR("Fast coverage tracer.") 660 661 #if PY_MAJOR_VERSION >= 3 662 663 static PyModuleDef 664 moduledef = { 665 PyModuleDef_HEAD_INIT, 666 "coverage.tracer", 667 MODULE_DOC, 668 -1, 669 NULL, /* methods */ 670 NULL, 671 NULL, /* traverse */ 672 NULL, /* clear */ 673 NULL 674 }; 675 676 677 PyObject * 678 PyInit_tracer(void) 679 { 680 PyObject * mod = PyModule_Create(&moduledef); 681 if (mod == NULL) { 682 return NULL; 683 } 684 685 TracerType.tp_new = PyType_GenericNew; 686 if (PyType_Ready(&TracerType) < 0) { 687 Py_DECREF(mod); 688 return NULL; 689 } 690 691 Py_INCREF(&TracerType); 692 PyModule_AddObject(mod, "Tracer", (PyObject *)&TracerType);
Failure runninng cpychecker (python-exception)
traceback: Traceback (most recent call last): File "/usr/lib/gcc/x86_64-redhat-linux/4.7.2/plugin/python2/libcpychecker/__init__.py", line 131, in _check_refcounts self.options) File "/usr/lib/gcc/x86_64-redhat-linux/4.7.2/plugin/python2/libcpychecker/refcounts.py", line 4355, in check_refcounts rep = impl_check_refcounts(ctxt, fun, options) File "/usr/lib/gcc/x86_64-redhat-linux/4.7.2/plugin/python2/libcpychecker/refcounts.py", line 4213, in impl_check_refcounts limits=limits) File "/usr/lib/gcc/x86_64-redhat-linux/4.7.2/plugin/python2/libcpychecker/absinterp.py", line 3089, in iter_traces depth + 1): File "/usr/lib/gcc/x86_64-redhat-linux/4.7.2/plugin/python2/libcpychecker/absinterp.py", line 3089, in iter_traces depth + 1): File "/usr/lib/gcc/x86_64-redhat-linux/4.7.2/plugin/python2/libcpychecker/absinterp.py", line 3089, in iter_traces depth + 1): File "/usr/lib/gcc/x86_64-redhat-linux/4.7.2/plugin/python2/libcpychecker/absinterp.py", line 3089, in iter_traces depth + 1): File "/usr/lib/gcc/x86_64-redhat-linux/4.7.2/plugin/python2/libcpychecker/absinterp.py", line 3089, in iter_traces depth + 1): File "/usr/lib/gcc/x86_64-redhat-linux/4.7.2/plugin/python2/libcpychecker/absinterp.py", line 3089, in iter_traces depth + 1): File "/usr/lib/gcc/x86_64-redhat-linux/4.7.2/plugin/python2/libcpychecker/absinterp.py", line 3089, in iter_traces depth + 1): File "/usr/lib/gcc/x86_64-redhat-linux/4.7.2/plugin/python2/libcpychecker/absinterp.py", line 3089, in iter_traces depth + 1): File "/usr/lib/gcc/x86_64-redhat-linux/4.7.2/plugin/python2/libcpychecker/absinterp.py", line 3089, in iter_traces depth + 1): File "/usr/lib/gcc/x86_64-redhat-linux/4.7.2/plugin/python2/libcpychecker/absinterp.py", line 3089, in iter_traces depth + 1): File "/usr/lib/gcc/x86_64-redhat-linux/4.7.2/plugin/python2/libcpychecker/absinterp.py", line 3089, in iter_traces depth + 1): File "/usr/lib/gcc/x86_64-redhat-linux/4.7.2/plugin/python2/libcpychecker/absinterp.py", line 3089, in iter_traces depth + 1): File "/usr/lib/gcc/x86_64-redhat-linux/4.7.2/plugin/python2/libcpychecker/absinterp.py", line 3053, in iter_traces transitions = curstate.get_transitions() File "/usr/lib/gcc/x86_64-redhat-linux/4.7.2/plugin/python2/libcpychecker/absinterp.py", line 2105, in get_transitions return self._get_transitions_for_stmt(stmt) File "/usr/lib/gcc/x86_64-redhat-linux/4.7.2/plugin/python2/libcpychecker/absinterp.py", line 2121, in _get_transitions_for_stmt return self._get_transitions_for_GimpleCall(stmt) File "/usr/lib/gcc/x86_64-redhat-linux/4.7.2/plugin/python2/libcpychecker/absinterp.py", line 2292, in _get_transitions_for_GimpleCall return meth(stmt, *args) File "/usr/lib/gcc/x86_64-redhat-linux/4.7.2/plugin/python2/libcpychecker/refcounts.py", line 2544, in impl_PyModule_AddObject s_success.cpython.steal_reference(v_value, stmt.loc) File "/usr/lib/gcc/x86_64-redhat-linux/4.7.2/plugin/python2/libcpychecker/refcounts.py", line 741, in steal_reference _steal_ref) File "/usr/lib/gcc/x86_64-redhat-linux/4.7.2/plugin/python2/libcpychecker/refcounts.py", line 551, in change_refcount check_isinstance(oldvalue, RefcountValue) File "/usr/lib/gcc/x86_64-redhat-linux/4.7.2/plugin/python2/gccutils.py", line 642, in check_isinstance raise TypeError('%s / %r is not an instance of %s' % (obj, obj, types)) TypeError: (long int)val [-0x7fffffffffffffff <= val <= 0x7fffffffffffffff] from coverage/tracer.c:691 / WithinRange(gcctype='long int', loc=gcc.Location(file='coverage/tracer.c', line=691), minvalue=-0x7fffffffffffffff, maxvalue=0x7fffffffffffffff) is not an instance of <class 'libcpychecker.refcounts.RefcountValue'>
693 694 return mod; 695 } 696 697 #else 698 699 void 700 inittracer(void) 701 { 702 PyObject * mod; 703 704 mod = Py_InitModule3("coverage.tracer", NULL, MODULE_DOC); 705 if (mod == NULL) { 706 return; 707 } 708 709 TracerType.tp_new = PyType_GenericNew; 710 if (PyType_Ready(&TracerType) < 0) { 711 return; 712 } 713 714 Py_INCREF(&TracerType); 715 PyModule_AddObject(mod, "Tracer", (PyObject *)&TracerType); 716 } 717 718 #endif /* Py3k */