commit efc20c87cc58854f87e5fbf68c036f9997727cc4 Author: David Malcolm dmalcolm@redhat.com Date: Thu Sep 1 15:45:19 2011 -0400
cpychecker: implement PyDict_SetItemString
libcpychecker/refcounts.py | 59 ++++- .../refcounts/PyDict_SetItemString/correct/input.c | 69 +++++ .../PyDict_SetItemString/correct/script.py | 22 ++ .../PyDict_SetItemString/correct/stdout.txt | 312 ++++++++++++++++++++ .../PyDict_SetItemString/incorrect/input.c | 70 +++++ .../PyDict_SetItemString/incorrect/script.py | 22 ++ .../PyDict_SetItemString/incorrect/stderr.txt | 18 ++ .../PyDict_SetItemString/incorrect/stdout.txt | 277 +++++++++++++++++ 8 files changed, 846 insertions(+), 3 deletions(-) --- diff --git a/libcpychecker/refcounts.py b/libcpychecker/refcounts.py index d8de452..1f1a022 100644 --- a/libcpychecker/refcounts.py +++ b/libcpychecker/refcounts.py @@ -290,20 +290,50 @@ class MyState(State): raise NotImplementedError("Don't know how to cope with %r (%s) at %s" % (stmt, stmt, stmt.loc))
- def add_ref(self, pyobjectptr, loc): + def change_refcount(self, pyobjectptr, loc, fn): + """ + Manipulate pyobjectptr's ob_refcnt. + + fn is a function taking a RefcountValue instance, returning another one + """ assert isinstance(pyobjectptr, AbstractValue) assert isinstance(pyobjectptr, PointerToRegion) ob_refcnt = self.make_field_region(pyobjectptr.region, 'ob_refcnt') assert isinstance(ob_refcnt, Region) oldvalue = self.get_store(ob_refcnt, None, loc) # FIXME: gcctype assert isinstance(oldvalue, AbstractValue) - log('oldvalue: %r' % oldvalue) + log('oldvalue: %r', oldvalue) #if isinstance(oldvalue, UnknownValue): # self.raise_split_value(oldvalue, loc) assert isinstance(oldvalue, RefcountValue) - newvalue = RefcountValue(oldvalue.relvalue + 1, oldvalue.min_external) + newvalue = fn(oldvalue) + log('newvalue: %r', newvalue) self.value_for_region[ob_refcnt] = newvalue
+ def add_ref(self, pyobjectptr, loc): + """ + Add a "visible" reference to pyobjectptr's ob_refcnt i.e. a reference + being held by a PyObject* that we are directly tracking. + """ + def _incref_internal(oldvalue): + return RefcountValue(oldvalue.relvalue + 1, + oldvalue.min_external) + self.change_refcount(pyobjectptr, + loc, + _incref_internal) + + def add_external_ref(self, pyobjectptr, loc): + """ + Add an "external" reference to pyobjectptr's ob_refcnt i.e. a reference + being held by a PyObject* that we're not directly tracking. + """ + def _incref_external(oldvalue): + return RefcountValue(oldvalue.relvalue, + oldvalue.min_external + 1) + self.change_refcount(pyobjectptr, + loc, + _incref_external) + def set_exception(self, exc_name): """ Given the name of a (PyObject*) global for an exception class, such as @@ -588,6 +618,29 @@ class MyState(State): t_notfound] #t_memoryexc]
+ def impl_PyDict_SetItemString(self, stmt): + # Declared in dictobject.h: + # PyAPI_FUNC(int) PyDict_SetItemString(PyObject *dp, const char *key, PyObject *item); + # Defined in dictobject.c + # + # API docs: + # http://docs.python.org/c-api/dict.html#PyDict_SetItemString + # Can return -1, setting MemoryError + # Otherwise returns 0, and adds a ref on the value + v_dp, v_key, v_item = self.eval_stmt_args(stmt) + + s_success = self.mkstate_concrete_return_of(stmt, 0) + # the dictionary now owns a new ref on "item". We won't model the + # insides of the dictionary type. Instead, treat it as a new + # external reference: + s_success.add_external_ref(v_item, stmt.loc) + + s_failure = self.mkstate_concrete_return_of(stmt, -1) + s_failure.set_exception('PyExc_MemoryError') + + return self.make_transitions_for_fncall(stmt, s_success, s_failure) + + ######################################################################## # PyErr_* ######################################################################## diff --git a/tests/cpychecker/refcounts/PyDict_SetItemString/correct/input.c b/tests/cpychecker/refcounts/PyDict_SetItemString/correct/input.c new file mode 100644 index 0000000..6ac0f1c --- /dev/null +++ b/tests/cpychecker/refcounts/PyDict_SetItemString/correct/input.c @@ -0,0 +1,69 @@ +/* + Copyright 2011 David Malcolm dmalcolm@redhat.com + Copyright 2011 Red Hat, Inc. + + This is free software: you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see + http://www.gnu.org/licenses/. +*/ + +#include <Python.h> + +/* + Test of correct reference-handling in a call to PyDict_SetItemString +*/ + +PyObject * +test(PyObject *self, PyObject *args) +{ + PyObject *dict = NULL; + PyObject *value = NULL; + + dict = PyDict_New(); + if (!dict) { + goto error; + } + + value = PyLong_FromLong(1000); + if (!value) { + goto error; + } + + if (-1 == PyDict_SetItemString(dict, "key", value)) { + goto error; + } + /* + The successful call added a ref on "value", owned by the dictionary. + We must now drop our reference on in: + */ + Py_DECREF(value); + + return dict; + + error: + Py_XDECREF(dict); + Py_XDECREF(value); + return NULL; +} +static PyMethodDef test_methods[] = { + {"test_method", test, METH_VARARGS, NULL}, + {NULL, NULL, 0, NULL} /* Sentinel */ +}; + +/* + PEP-7 +Local variables: +c-basic-offset: 4 +indent-tabs-mode: nil +End: +*/ diff --git a/tests/cpychecker/refcounts/PyDict_SetItemString/correct/script.py b/tests/cpychecker/refcounts/PyDict_SetItemString/correct/script.py new file mode 100644 index 0000000..fdd5ba3 --- /dev/null +++ b/tests/cpychecker/refcounts/PyDict_SetItemString/correct/script.py @@ -0,0 +1,22 @@ +# -*- coding: utf-8 -*- +# Copyright 2011 David Malcolm dmalcolm@redhat.com +# Copyright 2011 Red Hat, Inc. +# +# This is free software: you can redistribute it and/or modify it +# under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see +# http://www.gnu.org/licenses/. + +from libcpychecker import main +main(verify_refcounting=True, + dump_traces=True, + show_traces=False) diff --git a/tests/cpychecker/refcounts/PyDict_SetItemString/correct/stdout.txt b/tests/cpychecker/refcounts/PyDict_SetItemString/correct/stdout.txt new file mode 100644 index 0000000..7b5c3bd --- /dev/null +++ b/tests/cpychecker/refcounts/PyDict_SetItemString/correct/stdout.txt @@ -0,0 +1,312 @@ +Trace 0: + Transitions: + 'PyDict_New() succeeds' + 'taking False path' + 'PyLong_FromLong() succeeds' + 'taking False path' + 'PyDict_SetItemString() succeeds' + 'taking False path' + 'taking True path' + 'returning' + Return value: + repr(): PointerToRegion(gcctype='struct PyObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/PyDict_SetItemString/correct/input.c', line=32), region=RegionOnHeap('new ref from (unknown) PyDict_New', gcc.Location(file='tests/cpychecker/refcounts/PyDict_SetItemString/correct/input.c', line=32))) + str(): (struct PyObject *)&RegionOnHeap('new ref from (unknown) PyDict_New', gcc.Location(file='tests/cpychecker/refcounts/PyDict_SetItemString/correct/input.c', line=32)) from tests/cpychecker/refcounts/PyDict_SetItemString/correct/input.c:32 + r->ob_refcnt: refs: 1 + N where N >= 0 + r->ob_type: PointerToRegion(gcctype='struct PyTypeObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/PyDict_SetItemString/correct/input.c', line=32), region=Region('PyTypeObject for new ref from (unknown) PyDict_New')) + Region("region-for-arg-gcc.ParmDecl('self')"): + repr(): Region("region-for-arg-gcc.ParmDecl('self')") + str(): Region("region-for-arg-gcc.ParmDecl('self')") + r->ob_refcnt: refs: 0 + N where N >= 1 + r->ob_type: PointerToRegion(gcctype='struct PyTypeObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/PyDict_SetItemString/correct/input.c', line=27), region=Region("region-for-type-of-arg-gcc.ParmDecl('self')")) + Region("region-for-arg-gcc.ParmDecl('args')"): + repr(): Region("region-for-arg-gcc.ParmDecl('args')") + str(): Region("region-for-arg-gcc.ParmDecl('args')") + r->ob_refcnt: refs: 0 + N where N >= 1 + r->ob_type: PointerToRegion(gcctype='struct PyTypeObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/PyDict_SetItemString/correct/input.c', line=27), region=Region("region-for-type-of-arg-gcc.ParmDecl('args')")) + PyLongObject allocated at tests/cpychecker/refcounts/PyDict_SetItemString/correct/input.c:37: + repr(): RegionOnHeap('PyLongObject', gcc.Location(file='tests/cpychecker/refcounts/PyDict_SetItemString/correct/input.c', line=37)) + str(): PyLongObject allocated at tests/cpychecker/refcounts/PyDict_SetItemString/correct/input.c:37 + r->ob_refcnt: refs: 0 + N where N >= 1 + r->ob_type: PointerToRegion(gcctype='struct PyTypeObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/PyDict_SetItemString/correct/input.c', line=37), region=RegionForGlobal(gcc.VarDecl('PyLong_Type'))) + Exception: + (struct PyObject *)0 from tests/cpychecker/refcounts/PyDict_SetItemString/correct/input.c:28 + +Trace 1: + Transitions: + 'PyDict_New() succeeds' + 'taking False path' + 'PyLong_FromLong() succeeds' + 'taking False path' + 'PyDict_SetItemString() succeeds' + 'taking False path' + 'taking False path' + 'calling tp_dealloc on PyLongObject allocated at tests/cpychecker/refcounts/PyDict_SetItemString/correct/input.c:37' + 'returning' + Return value: + repr(): PointerToRegion(gcctype='struct PyObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/PyDict_SetItemString/correct/input.c', line=32), region=RegionOnHeap('new ref from (unknown) PyDict_New', gcc.Location(file='tests/cpychecker/refcounts/PyDict_SetItemString/correct/input.c', line=32))) + str(): (struct PyObject *)&RegionOnHeap('new ref from (unknown) PyDict_New', gcc.Location(file='tests/cpychecker/refcounts/PyDict_SetItemString/correct/input.c', line=32)) from tests/cpychecker/refcounts/PyDict_SetItemString/correct/input.c:32 + r->ob_refcnt: refs: 1 + N where N >= 0 + r->ob_type: PointerToRegion(gcctype='struct PyTypeObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/PyDict_SetItemString/correct/input.c', line=32), region=Region('PyTypeObject for new ref from (unknown) PyDict_New')) + Region("region-for-arg-gcc.ParmDecl('self')"): + repr(): Region("region-for-arg-gcc.ParmDecl('self')") + str(): Region("region-for-arg-gcc.ParmDecl('self')") + r->ob_refcnt: refs: 0 + N where N >= 1 + r->ob_type: PointerToRegion(gcctype='struct PyTypeObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/PyDict_SetItemString/correct/input.c', line=27), region=Region("region-for-type-of-arg-gcc.ParmDecl('self')")) + Region("region-for-arg-gcc.ParmDecl('args')"): + repr(): Region("region-for-arg-gcc.ParmDecl('args')") + str(): Region("region-for-arg-gcc.ParmDecl('args')") + r->ob_refcnt: refs: 0 + N where N >= 1 + r->ob_type: PointerToRegion(gcctype='struct PyTypeObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/PyDict_SetItemString/correct/input.c', line=27), region=Region("region-for-type-of-arg-gcc.ParmDecl('args')")) + PyLongObject allocated at tests/cpychecker/refcounts/PyDict_SetItemString/correct/input.c:37: + repr(): RegionOnHeap('PyLongObject', gcc.Location(file='tests/cpychecker/refcounts/PyDict_SetItemString/correct/input.c', line=37)) + str(): PyLongObject allocated at tests/cpychecker/refcounts/PyDict_SetItemString/correct/input.c:37 + r->ob_refcnt: None + r->ob_type: None + Exception: + (struct PyObject *)0 from tests/cpychecker/refcounts/PyDict_SetItemString/correct/input.c:28 + +Trace 2: + Transitions: + 'PyDict_New() succeeds' + 'taking False path' + 'PyLong_FromLong() succeeds' + 'taking False path' + 'PyDict_SetItemString() fails' + 'taking True path' + 'taking False path' + 'taking True path' + 'taking False path' + 'taking True path' + 'returning' + Return value: + repr(): ConcreteValue(gcctype='struct PyObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/PyDict_SetItemString/correct/input.c', line=56), value=0) + str(): (struct PyObject *)0 from tests/cpychecker/refcounts/PyDict_SetItemString/correct/input.c:56 + Region("region-for-arg-gcc.ParmDecl('self')"): + repr(): Region("region-for-arg-gcc.ParmDecl('self')") + str(): Region("region-for-arg-gcc.ParmDecl('self')") + r->ob_refcnt: refs: 0 + N where N >= 1 + r->ob_type: PointerToRegion(gcctype='struct PyTypeObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/PyDict_SetItemString/correct/input.c', line=27), region=Region("region-for-type-of-arg-gcc.ParmDecl('self')")) + Region("region-for-arg-gcc.ParmDecl('args')"): + repr(): Region("region-for-arg-gcc.ParmDecl('args')") + str(): Region("region-for-arg-gcc.ParmDecl('args')") + r->ob_refcnt: refs: 0 + N where N >= 1 + r->ob_type: PointerToRegion(gcctype='struct PyTypeObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/PyDict_SetItemString/correct/input.c', line=27), region=Region("region-for-type-of-arg-gcc.ParmDecl('args')")) + new ref from (unknown) PyDict_New allocated at tests/cpychecker/refcounts/PyDict_SetItemString/correct/input.c:32: + repr(): RegionOnHeap('new ref from (unknown) PyDict_New', gcc.Location(file='tests/cpychecker/refcounts/PyDict_SetItemString/correct/input.c', line=32)) + str(): new ref from (unknown) PyDict_New allocated at tests/cpychecker/refcounts/PyDict_SetItemString/correct/input.c:32 + r->ob_refcnt: refs: 0 + N where N >= 0 + r->ob_type: PointerToRegion(gcctype='struct PyTypeObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/PyDict_SetItemString/correct/input.c', line=32), region=Region('PyTypeObject for new ref from (unknown) PyDict_New')) + PyLongObject allocated at tests/cpychecker/refcounts/PyDict_SetItemString/correct/input.c:37: + repr(): RegionOnHeap('PyLongObject', gcc.Location(file='tests/cpychecker/refcounts/PyDict_SetItemString/correct/input.c', line=37)) + str(): PyLongObject allocated at tests/cpychecker/refcounts/PyDict_SetItemString/correct/input.c:37 + r->ob_refcnt: refs: 0 + N where N >= 0 + r->ob_type: PointerToRegion(gcctype='struct PyTypeObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/PyDict_SetItemString/correct/input.c', line=37), region=RegionForGlobal(gcc.VarDecl('PyLong_Type'))) + Exception: + RegionForGlobal(gcc.VarDecl('PyExc_MemoryError')) + +Trace 3: + Transitions: + 'PyDict_New() succeeds' + 'taking False path' + 'PyLong_FromLong() succeeds' + 'taking False path' + 'PyDict_SetItemString() fails' + 'taking True path' + 'taking False path' + 'taking True path' + 'taking False path' + 'taking False path' + 'calling tp_dealloc on PyLongObject allocated at tests/cpychecker/refcounts/PyDict_SetItemString/correct/input.c:37' + 'returning' + Return value: + repr(): ConcreteValue(gcctype='struct PyObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/PyDict_SetItemString/correct/input.c', line=56), value=0) + str(): (struct PyObject *)0 from tests/cpychecker/refcounts/PyDict_SetItemString/correct/input.c:56 + Region("region-for-arg-gcc.ParmDecl('self')"): + repr(): Region("region-for-arg-gcc.ParmDecl('self')") + str(): Region("region-for-arg-gcc.ParmDecl('self')") + r->ob_refcnt: refs: 0 + N where N >= 1 + r->ob_type: PointerToRegion(gcctype='struct PyTypeObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/PyDict_SetItemString/correct/input.c', line=27), region=Region("region-for-type-of-arg-gcc.ParmDecl('self')")) + Region("region-for-arg-gcc.ParmDecl('args')"): + repr(): Region("region-for-arg-gcc.ParmDecl('args')") + str(): Region("region-for-arg-gcc.ParmDecl('args')") + r->ob_refcnt: refs: 0 + N where N >= 1 + r->ob_type: PointerToRegion(gcctype='struct PyTypeObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/PyDict_SetItemString/correct/input.c', line=27), region=Region("region-for-type-of-arg-gcc.ParmDecl('args')")) + new ref from (unknown) PyDict_New allocated at tests/cpychecker/refcounts/PyDict_SetItemString/correct/input.c:32: + repr(): RegionOnHeap('new ref from (unknown) PyDict_New', gcc.Location(file='tests/cpychecker/refcounts/PyDict_SetItemString/correct/input.c', line=32)) + str(): new ref from (unknown) PyDict_New allocated at tests/cpychecker/refcounts/PyDict_SetItemString/correct/input.c:32 + r->ob_refcnt: refs: 0 + N where N >= 0 + r->ob_type: PointerToRegion(gcctype='struct PyTypeObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/PyDict_SetItemString/correct/input.c', line=32), region=Region('PyTypeObject for new ref from (unknown) PyDict_New')) + PyLongObject allocated at tests/cpychecker/refcounts/PyDict_SetItemString/correct/input.c:37: + repr(): RegionOnHeap('PyLongObject', gcc.Location(file='tests/cpychecker/refcounts/PyDict_SetItemString/correct/input.c', line=37)) + str(): PyLongObject allocated at tests/cpychecker/refcounts/PyDict_SetItemString/correct/input.c:37 + r->ob_refcnt: None + r->ob_type: None + Exception: + RegionForGlobal(gcc.VarDecl('PyExc_MemoryError')) + +Trace 4: + Transitions: + 'PyDict_New() succeeds' + 'taking False path' + 'PyLong_FromLong() succeeds' + 'taking False path' + 'PyDict_SetItemString() fails' + 'taking True path' + 'taking False path' + 'taking False path' + 'calling tp_dealloc on new ref from (unknown) PyDict_New allocated at tests/cpychecker/refcounts/PyDict_SetItemString/correct/input.c:32' + 'taking False path' + 'taking True path' + 'returning' + Return value: + repr(): ConcreteValue(gcctype='struct PyObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/PyDict_SetItemString/correct/input.c', line=56), value=0) + str(): (struct PyObject *)0 from tests/cpychecker/refcounts/PyDict_SetItemString/correct/input.c:56 + Region("region-for-arg-gcc.ParmDecl('self')"): + repr(): Region("region-for-arg-gcc.ParmDecl('self')") + str(): Region("region-for-arg-gcc.ParmDecl('self')") + r->ob_refcnt: refs: 0 + N where N >= 1 + r->ob_type: PointerToRegion(gcctype='struct PyTypeObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/PyDict_SetItemString/correct/input.c', line=27), region=Region("region-for-type-of-arg-gcc.ParmDecl('self')")) + Region("region-for-arg-gcc.ParmDecl('args')"): + repr(): Region("region-for-arg-gcc.ParmDecl('args')") + str(): Region("region-for-arg-gcc.ParmDecl('args')") + r->ob_refcnt: refs: 0 + N where N >= 1 + r->ob_type: PointerToRegion(gcctype='struct PyTypeObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/PyDict_SetItemString/correct/input.c', line=27), region=Region("region-for-type-of-arg-gcc.ParmDecl('args')")) + new ref from (unknown) PyDict_New allocated at tests/cpychecker/refcounts/PyDict_SetItemString/correct/input.c:32: + repr(): RegionOnHeap('new ref from (unknown) PyDict_New', gcc.Location(file='tests/cpychecker/refcounts/PyDict_SetItemString/correct/input.c', line=32)) + str(): new ref from (unknown) PyDict_New allocated at tests/cpychecker/refcounts/PyDict_SetItemString/correct/input.c:32 + r->ob_refcnt: None + r->ob_type: None + PyLongObject allocated at tests/cpychecker/refcounts/PyDict_SetItemString/correct/input.c:37: + repr(): RegionOnHeap('PyLongObject', gcc.Location(file='tests/cpychecker/refcounts/PyDict_SetItemString/correct/input.c', line=37)) + str(): PyLongObject allocated at tests/cpychecker/refcounts/PyDict_SetItemString/correct/input.c:37 + r->ob_refcnt: refs: 0 + N where N >= 0 + r->ob_type: PointerToRegion(gcctype='struct PyTypeObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/PyDict_SetItemString/correct/input.c', line=37), region=RegionForGlobal(gcc.VarDecl('PyLong_Type'))) + Exception: + RegionForGlobal(gcc.VarDecl('PyExc_MemoryError')) + +Trace 5: + Transitions: + 'PyDict_New() succeeds' + 'taking False path' + 'PyLong_FromLong() succeeds' + 'taking False path' + 'PyDict_SetItemString() fails' + 'taking True path' + 'taking False path' + 'taking False path' + 'calling tp_dealloc on new ref from (unknown) PyDict_New allocated at tests/cpychecker/refcounts/PyDict_SetItemString/correct/input.c:32' + 'taking False path' + 'taking False path' + 'calling tp_dealloc on PyLongObject allocated at tests/cpychecker/refcounts/PyDict_SetItemString/correct/input.c:37' + 'returning' + Return value: + repr(): ConcreteValue(gcctype='struct PyObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/PyDict_SetItemString/correct/input.c', line=56), value=0) + str(): (struct PyObject *)0 from tests/cpychecker/refcounts/PyDict_SetItemString/correct/input.c:56 + Region("region-for-arg-gcc.ParmDecl('self')"): + repr(): Region("region-for-arg-gcc.ParmDecl('self')") + str(): Region("region-for-arg-gcc.ParmDecl('self')") + r->ob_refcnt: refs: 0 + N where N >= 1 + r->ob_type: PointerToRegion(gcctype='struct PyTypeObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/PyDict_SetItemString/correct/input.c', line=27), region=Region("region-for-type-of-arg-gcc.ParmDecl('self')")) + Region("region-for-arg-gcc.ParmDecl('args')"): + repr(): Region("region-for-arg-gcc.ParmDecl('args')") + str(): Region("region-for-arg-gcc.ParmDecl('args')") + r->ob_refcnt: refs: 0 + N where N >= 1 + r->ob_type: PointerToRegion(gcctype='struct PyTypeObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/PyDict_SetItemString/correct/input.c', line=27), region=Region("region-for-type-of-arg-gcc.ParmDecl('args')")) + new ref from (unknown) PyDict_New allocated at tests/cpychecker/refcounts/PyDict_SetItemString/correct/input.c:32: + repr(): RegionOnHeap('new ref from (unknown) PyDict_New', gcc.Location(file='tests/cpychecker/refcounts/PyDict_SetItemString/correct/input.c', line=32)) + str(): new ref from (unknown) PyDict_New allocated at tests/cpychecker/refcounts/PyDict_SetItemString/correct/input.c:32 + r->ob_refcnt: None + r->ob_type: None + PyLongObject allocated at tests/cpychecker/refcounts/PyDict_SetItemString/correct/input.c:37: + repr(): RegionOnHeap('PyLongObject', gcc.Location(file='tests/cpychecker/refcounts/PyDict_SetItemString/correct/input.c', line=37)) + str(): PyLongObject allocated at tests/cpychecker/refcounts/PyDict_SetItemString/correct/input.c:37 + r->ob_refcnt: None + r->ob_type: None + Exception: + RegionForGlobal(gcc.VarDecl('PyExc_MemoryError')) + +Trace 6: + Transitions: + 'PyDict_New() succeeds' + 'taking False path' + 'PyLong_FromLong() fails' + 'taking True path' + 'taking False path' + 'taking True path' + 'taking True path' + 'returning' + Return value: + repr(): ConcreteValue(gcctype='struct PyObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/PyDict_SetItemString/correct/input.c', line=56), value=0) + str(): (struct PyObject *)0 from tests/cpychecker/refcounts/PyDict_SetItemString/correct/input.c:56 + Region("region-for-arg-gcc.ParmDecl('self')"): + repr(): Region("region-for-arg-gcc.ParmDecl('self')") + str(): Region("region-for-arg-gcc.ParmDecl('self')") + r->ob_refcnt: refs: 0 + N where N >= 1 + r->ob_type: PointerToRegion(gcctype='struct PyTypeObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/PyDict_SetItemString/correct/input.c', line=27), region=Region("region-for-type-of-arg-gcc.ParmDecl('self')")) + Region("region-for-arg-gcc.ParmDecl('args')"): + repr(): Region("region-for-arg-gcc.ParmDecl('args')") + str(): Region("region-for-arg-gcc.ParmDecl('args')") + r->ob_refcnt: refs: 0 + N where N >= 1 + r->ob_type: PointerToRegion(gcctype='struct PyTypeObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/PyDict_SetItemString/correct/input.c', line=27), region=Region("region-for-type-of-arg-gcc.ParmDecl('args')")) + new ref from (unknown) PyDict_New allocated at tests/cpychecker/refcounts/PyDict_SetItemString/correct/input.c:32: + repr(): RegionOnHeap('new ref from (unknown) PyDict_New', gcc.Location(file='tests/cpychecker/refcounts/PyDict_SetItemString/correct/input.c', line=32)) + str(): new ref from (unknown) PyDict_New allocated at tests/cpychecker/refcounts/PyDict_SetItemString/correct/input.c:32 + r->ob_refcnt: refs: 0 + N where N >= 0 + r->ob_type: PointerToRegion(gcctype='struct PyTypeObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/PyDict_SetItemString/correct/input.c', line=32), region=Region('PyTypeObject for new ref from (unknown) PyDict_New')) + Exception: + RegionForGlobal(gcc.VarDecl('PyExc_MemoryError')) + +Trace 7: + Transitions: + 'PyDict_New() succeeds' + 'taking False path' + 'PyLong_FromLong() fails' + 'taking True path' + 'taking False path' + 'taking False path' + 'calling tp_dealloc on new ref from (unknown) PyDict_New allocated at tests/cpychecker/refcounts/PyDict_SetItemString/correct/input.c:32' + 'taking True path' + 'returning' + Return value: + repr(): ConcreteValue(gcctype='struct PyObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/PyDict_SetItemString/correct/input.c', line=56), value=0) + str(): (struct PyObject *)0 from tests/cpychecker/refcounts/PyDict_SetItemString/correct/input.c:56 + Region("region-for-arg-gcc.ParmDecl('self')"): + repr(): Region("region-for-arg-gcc.ParmDecl('self')") + str(): Region("region-for-arg-gcc.ParmDecl('self')") + r->ob_refcnt: refs: 0 + N where N >= 1 + r->ob_type: PointerToRegion(gcctype='struct PyTypeObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/PyDict_SetItemString/correct/input.c', line=27), region=Region("region-for-type-of-arg-gcc.ParmDecl('self')")) + Region("region-for-arg-gcc.ParmDecl('args')"): + repr(): Region("region-for-arg-gcc.ParmDecl('args')") + str(): Region("region-for-arg-gcc.ParmDecl('args')") + r->ob_refcnt: refs: 0 + N where N >= 1 + r->ob_type: PointerToRegion(gcctype='struct PyTypeObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/PyDict_SetItemString/correct/input.c', line=27), region=Region("region-for-type-of-arg-gcc.ParmDecl('args')")) + new ref from (unknown) PyDict_New allocated at tests/cpychecker/refcounts/PyDict_SetItemString/correct/input.c:32: + repr(): RegionOnHeap('new ref from (unknown) PyDict_New', gcc.Location(file='tests/cpychecker/refcounts/PyDict_SetItemString/correct/input.c', line=32)) + str(): new ref from (unknown) PyDict_New allocated at tests/cpychecker/refcounts/PyDict_SetItemString/correct/input.c:32 + r->ob_refcnt: None + r->ob_type: None + Exception: + RegionForGlobal(gcc.VarDecl('PyExc_MemoryError')) + +Trace 8: + Transitions: + 'PyDict_New() fails' + 'taking True path' + 'taking True path' + 'taking True path' + 'returning' + Return value: + repr(): ConcreteValue(gcctype='struct PyObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/PyDict_SetItemString/correct/input.c', line=56), value=0) + str(): (struct PyObject *)0 from tests/cpychecker/refcounts/PyDict_SetItemString/correct/input.c:56 + Region("region-for-arg-gcc.ParmDecl('self')"): + repr(): Region("region-for-arg-gcc.ParmDecl('self')") + str(): Region("region-for-arg-gcc.ParmDecl('self')") + r->ob_refcnt: refs: 0 + N where N >= 1 + r->ob_type: PointerToRegion(gcctype='struct PyTypeObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/PyDict_SetItemString/correct/input.c', line=27), region=Region("region-for-type-of-arg-gcc.ParmDecl('self')")) + Region("region-for-arg-gcc.ParmDecl('args')"): + repr(): Region("region-for-arg-gcc.ParmDecl('args')") + str(): Region("region-for-arg-gcc.ParmDecl('args')") + r->ob_refcnt: refs: 0 + N where N >= 1 + r->ob_type: PointerToRegion(gcctype='struct PyTypeObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/PyDict_SetItemString/correct/input.c', line=27), region=Region("region-for-type-of-arg-gcc.ParmDecl('args')")) + Exception: + RegionForGlobal(gcc.VarDecl('PyExc_MemoryError')) diff --git a/tests/cpychecker/refcounts/PyDict_SetItemString/incorrect/input.c b/tests/cpychecker/refcounts/PyDict_SetItemString/incorrect/input.c new file mode 100644 index 0000000..cdd4666 --- /dev/null +++ b/tests/cpychecker/refcounts/PyDict_SetItemString/incorrect/input.c @@ -0,0 +1,70 @@ +/* + Copyright 2011 David Malcolm dmalcolm@redhat.com + Copyright 2011 Red Hat, Inc. + + This is free software: you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see + http://www.gnu.org/licenses/. +*/ + +#include <Python.h> + +/* + Test of incorrect reference-handling in a call to PyDict_SetItemString +*/ + +PyObject * +test(PyObject *self, PyObject *args) +{ + PyObject *dict = NULL; + PyObject *value = NULL; + + dict = PyDict_New(); + if (!dict) { + goto error; + } + + value = PyLong_FromLong(1000); + if (!value) { + goto error; + } + + if (-1 == PyDict_SetItemString(dict, "key", value)) { + goto error; + } + /* + The successful call added a ref on "value", owned by the dictionary. + + However, we still hold another reference on "value", and this code + erroneously fails to call Py_DECREF on it, which will be a leak. + */ + + return dict; + + error: + Py_XDECREF(dict); + Py_XDECREF(value); + return NULL; +} +static PyMethodDef test_methods[] = { + {"test_method", test, METH_VARARGS, NULL}, + {NULL, NULL, 0, NULL} /* Sentinel */ +}; + +/* + PEP-7 +Local variables: +c-basic-offset: 4 +indent-tabs-mode: nil +End: +*/ diff --git a/tests/cpychecker/refcounts/PyDict_SetItemString/incorrect/script.py b/tests/cpychecker/refcounts/PyDict_SetItemString/incorrect/script.py new file mode 100644 index 0000000..fdd5ba3 --- /dev/null +++ b/tests/cpychecker/refcounts/PyDict_SetItemString/incorrect/script.py @@ -0,0 +1,22 @@ +# -*- coding: utf-8 -*- +# Copyright 2011 David Malcolm dmalcolm@redhat.com +# Copyright 2011 Red Hat, Inc. +# +# This is free software: you can redistribute it and/or modify it +# under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see +# http://www.gnu.org/licenses/. + +from libcpychecker import main +main(verify_refcounting=True, + dump_traces=True, + show_traces=False) diff --git a/tests/cpychecker/refcounts/PyDict_SetItemString/incorrect/stderr.txt b/tests/cpychecker/refcounts/PyDict_SetItemString/incorrect/stderr.txt new file mode 100644 index 0000000..01ba16c --- /dev/null +++ b/tests/cpychecker/refcounts/PyDict_SetItemString/incorrect/stderr.txt @@ -0,0 +1,18 @@ +tests/cpychecker/refcounts/PyDict_SetItemString/incorrect/input.c: In function 'test': +tests/cpychecker/refcounts/PyDict_SetItemString/incorrect/input.c:58:1: error: ob_refcnt of PyLongObject is 1 too high +tests/cpychecker/refcounts/PyDict_SetItemString/incorrect/input.c:58:1: note: was expecting final ob_refcnt to be N + 0 (for some unknown N) +tests/cpychecker/refcounts/PyDict_SetItemString/incorrect/input.c:58:1: note: but final ob_refcnt is N + 1 +tests/cpychecker/refcounts/PyDict_SetItemString/incorrect/input.c:37:11: note: PyLongObject allocated at: value = PyLong_FromLong(1000); +tests/cpychecker/refcounts/PyDict_SetItemString/incorrect/input.c:32:10: note: when PyDict_New() succeeds at: dict = PyDict_New(); +tests/cpychecker/refcounts/PyDict_SetItemString/incorrect/input.c:33:8: note: when taking False path at: if (!dict) { +tests/cpychecker/refcounts/PyDict_SetItemString/incorrect/input.c:37:11: note: reaching: value = PyLong_FromLong(1000); +tests/cpychecker/refcounts/PyDict_SetItemString/incorrect/input.c:37:11: note: when PyLong_FromLong() succeeds at: value = PyLong_FromLong(1000); +tests/cpychecker/refcounts/PyDict_SetItemString/incorrect/input.c:37:11: note: ob_refcnt is now refs: 1 + N where N >= 0 +tests/cpychecker/refcounts/PyDict_SetItemString/incorrect/input.c:38:8: note: when taking False path at: if (!value) { +tests/cpychecker/refcounts/PyDict_SetItemString/incorrect/input.c:42:35: note: reaching: if (-1 == PyDict_SetItemString(dict, "key", value)) { +tests/cpychecker/refcounts/PyDict_SetItemString/incorrect/input.c:42:35: note: when PyDict_SetItemString() succeeds at: if (-1 == PyDict_SetItemString(dict, "key", value)) { +tests/cpychecker/refcounts/PyDict_SetItemString/incorrect/input.c:42:35: note: ob_refcnt is now refs: 1 + N where N >= 1 +tests/cpychecker/refcounts/PyDict_SetItemString/incorrect/input.c:42:8: note: when taking False path at: if (-1 == PyDict_SetItemString(dict, "key", value)) { +tests/cpychecker/refcounts/PyDict_SetItemString/incorrect/input.c:52:5: note: reaching: return dict; +tests/cpychecker/refcounts/PyDict_SetItemString/incorrect/input.c:58:1: note: when returning +tests/cpychecker/refcounts/PyDict_SetItemString/incorrect/input.c:28:1: note: graphical error report for function 'test' written out to 'tests/cpychecker/refcounts/PyDict_SetItemString/incorrect/input.c.test-refcount-errors.html' diff --git a/tests/cpychecker/refcounts/PyDict_SetItemString/incorrect/stdout.txt b/tests/cpychecker/refcounts/PyDict_SetItemString/incorrect/stdout.txt new file mode 100644 index 0000000..1dad097 --- /dev/null +++ b/tests/cpychecker/refcounts/PyDict_SetItemString/incorrect/stdout.txt @@ -0,0 +1,277 @@ +Trace 0: + Transitions: + 'PyDict_New() succeeds' + 'taking False path' + 'PyLong_FromLong() succeeds' + 'taking False path' + 'PyDict_SetItemString() succeeds' + 'taking False path' + 'returning' + Return value: + repr(): PointerToRegion(gcctype='struct PyObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/PyDict_SetItemString/incorrect/input.c', line=32), region=RegionOnHeap('new ref from (unknown) PyDict_New', gcc.Location(file='tests/cpychecker/refcounts/PyDict_SetItemString/incorrect/input.c', line=32))) + str(): (struct PyObject *)&RegionOnHeap('new ref from (unknown) PyDict_New', gcc.Location(file='tests/cpychecker/refcounts/PyDict_SetItemString/incorrect/input.c', line=32)) from tests/cpychecker/refcounts/PyDict_SetItemString/incorrect/input.c:32 + r->ob_refcnt: refs: 1 + N where N >= 0 + r->ob_type: PointerToRegion(gcctype='struct PyTypeObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/PyDict_SetItemString/incorrect/input.c', line=32), region=Region('PyTypeObject for new ref from (unknown) PyDict_New')) + Region("region-for-arg-gcc.ParmDecl('self')"): + repr(): Region("region-for-arg-gcc.ParmDecl('self')") + str(): Region("region-for-arg-gcc.ParmDecl('self')") + r->ob_refcnt: refs: 0 + N where N >= 1 + r->ob_type: PointerToRegion(gcctype='struct PyTypeObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/PyDict_SetItemString/incorrect/input.c', line=27), region=Region("region-for-type-of-arg-gcc.ParmDecl('self')")) + Region("region-for-arg-gcc.ParmDecl('args')"): + repr(): Region("region-for-arg-gcc.ParmDecl('args')") + str(): Region("region-for-arg-gcc.ParmDecl('args')") + r->ob_refcnt: refs: 0 + N where N >= 1 + r->ob_type: PointerToRegion(gcctype='struct PyTypeObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/PyDict_SetItemString/incorrect/input.c', line=27), region=Region("region-for-type-of-arg-gcc.ParmDecl('args')")) + PyLongObject allocated at tests/cpychecker/refcounts/PyDict_SetItemString/incorrect/input.c:37: + repr(): RegionOnHeap('PyLongObject', gcc.Location(file='tests/cpychecker/refcounts/PyDict_SetItemString/incorrect/input.c', line=37)) + str(): PyLongObject allocated at tests/cpychecker/refcounts/PyDict_SetItemString/incorrect/input.c:37 + r->ob_refcnt: refs: 1 + N where N >= 1 + r->ob_type: PointerToRegion(gcctype='struct PyTypeObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/PyDict_SetItemString/incorrect/input.c', line=37), region=RegionForGlobal(gcc.VarDecl('PyLong_Type'))) + Exception: + (struct PyObject *)0 from tests/cpychecker/refcounts/PyDict_SetItemString/incorrect/input.c:28 + +Trace 1: + Transitions: + 'PyDict_New() succeeds' + 'taking False path' + 'PyLong_FromLong() succeeds' + 'taking False path' + 'PyDict_SetItemString() fails' + 'taking True path' + 'taking False path' + 'taking True path' + 'taking False path' + 'taking True path' + 'returning' + Return value: + repr(): ConcreteValue(gcctype='struct PyObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/PyDict_SetItemString/incorrect/input.c', line=57), value=0) + str(): (struct PyObject *)0 from tests/cpychecker/refcounts/PyDict_SetItemString/incorrect/input.c:57 + Region("region-for-arg-gcc.ParmDecl('self')"): + repr(): Region("region-for-arg-gcc.ParmDecl('self')") + str(): Region("region-for-arg-gcc.ParmDecl('self')") + r->ob_refcnt: refs: 0 + N where N >= 1 + r->ob_type: PointerToRegion(gcctype='struct PyTypeObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/PyDict_SetItemString/incorrect/input.c', line=27), region=Region("region-for-type-of-arg-gcc.ParmDecl('self')")) + Region("region-for-arg-gcc.ParmDecl('args')"): + repr(): Region("region-for-arg-gcc.ParmDecl('args')") + str(): Region("region-for-arg-gcc.ParmDecl('args')") + r->ob_refcnt: refs: 0 + N where N >= 1 + r->ob_type: PointerToRegion(gcctype='struct PyTypeObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/PyDict_SetItemString/incorrect/input.c', line=27), region=Region("region-for-type-of-arg-gcc.ParmDecl('args')")) + new ref from (unknown) PyDict_New allocated at tests/cpychecker/refcounts/PyDict_SetItemString/incorrect/input.c:32: + repr(): RegionOnHeap('new ref from (unknown) PyDict_New', gcc.Location(file='tests/cpychecker/refcounts/PyDict_SetItemString/incorrect/input.c', line=32)) + str(): new ref from (unknown) PyDict_New allocated at tests/cpychecker/refcounts/PyDict_SetItemString/incorrect/input.c:32 + r->ob_refcnt: refs: 0 + N where N >= 0 + r->ob_type: PointerToRegion(gcctype='struct PyTypeObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/PyDict_SetItemString/incorrect/input.c', line=32), region=Region('PyTypeObject for new ref from (unknown) PyDict_New')) + PyLongObject allocated at tests/cpychecker/refcounts/PyDict_SetItemString/incorrect/input.c:37: + repr(): RegionOnHeap('PyLongObject', gcc.Location(file='tests/cpychecker/refcounts/PyDict_SetItemString/incorrect/input.c', line=37)) + str(): PyLongObject allocated at tests/cpychecker/refcounts/PyDict_SetItemString/incorrect/input.c:37 + r->ob_refcnt: refs: 0 + N where N >= 0 + r->ob_type: PointerToRegion(gcctype='struct PyTypeObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/PyDict_SetItemString/incorrect/input.c', line=37), region=RegionForGlobal(gcc.VarDecl('PyLong_Type'))) + Exception: + RegionForGlobal(gcc.VarDecl('PyExc_MemoryError')) + +Trace 2: + Transitions: + 'PyDict_New() succeeds' + 'taking False path' + 'PyLong_FromLong() succeeds' + 'taking False path' + 'PyDict_SetItemString() fails' + 'taking True path' + 'taking False path' + 'taking True path' + 'taking False path' + 'taking False path' + 'calling tp_dealloc on PyLongObject allocated at tests/cpychecker/refcounts/PyDict_SetItemString/incorrect/input.c:37' + 'returning' + Return value: + repr(): ConcreteValue(gcctype='struct PyObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/PyDict_SetItemString/incorrect/input.c', line=57), value=0) + str(): (struct PyObject *)0 from tests/cpychecker/refcounts/PyDict_SetItemString/incorrect/input.c:57 + Region("region-for-arg-gcc.ParmDecl('self')"): + repr(): Region("region-for-arg-gcc.ParmDecl('self')") + str(): Region("region-for-arg-gcc.ParmDecl('self')") + r->ob_refcnt: refs: 0 + N where N >= 1 + r->ob_type: PointerToRegion(gcctype='struct PyTypeObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/PyDict_SetItemString/incorrect/input.c', line=27), region=Region("region-for-type-of-arg-gcc.ParmDecl('self')")) + Region("region-for-arg-gcc.ParmDecl('args')"): + repr(): Region("region-for-arg-gcc.ParmDecl('args')") + str(): Region("region-for-arg-gcc.ParmDecl('args')") + r->ob_refcnt: refs: 0 + N where N >= 1 + r->ob_type: PointerToRegion(gcctype='struct PyTypeObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/PyDict_SetItemString/incorrect/input.c', line=27), region=Region("region-for-type-of-arg-gcc.ParmDecl('args')")) + new ref from (unknown) PyDict_New allocated at tests/cpychecker/refcounts/PyDict_SetItemString/incorrect/input.c:32: + repr(): RegionOnHeap('new ref from (unknown) PyDict_New', gcc.Location(file='tests/cpychecker/refcounts/PyDict_SetItemString/incorrect/input.c', line=32)) + str(): new ref from (unknown) PyDict_New allocated at tests/cpychecker/refcounts/PyDict_SetItemString/incorrect/input.c:32 + r->ob_refcnt: refs: 0 + N where N >= 0 + r->ob_type: PointerToRegion(gcctype='struct PyTypeObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/PyDict_SetItemString/incorrect/input.c', line=32), region=Region('PyTypeObject for new ref from (unknown) PyDict_New')) + PyLongObject allocated at tests/cpychecker/refcounts/PyDict_SetItemString/incorrect/input.c:37: + repr(): RegionOnHeap('PyLongObject', gcc.Location(file='tests/cpychecker/refcounts/PyDict_SetItemString/incorrect/input.c', line=37)) + str(): PyLongObject allocated at tests/cpychecker/refcounts/PyDict_SetItemString/incorrect/input.c:37 + r->ob_refcnt: None + r->ob_type: None + Exception: + RegionForGlobal(gcc.VarDecl('PyExc_MemoryError')) + +Trace 3: + Transitions: + 'PyDict_New() succeeds' + 'taking False path' + 'PyLong_FromLong() succeeds' + 'taking False path' + 'PyDict_SetItemString() fails' + 'taking True path' + 'taking False path' + 'taking False path' + 'calling tp_dealloc on new ref from (unknown) PyDict_New allocated at tests/cpychecker/refcounts/PyDict_SetItemString/incorrect/input.c:32' + 'taking False path' + 'taking True path' + 'returning' + Return value: + repr(): ConcreteValue(gcctype='struct PyObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/PyDict_SetItemString/incorrect/input.c', line=57), value=0) + str(): (struct PyObject *)0 from tests/cpychecker/refcounts/PyDict_SetItemString/incorrect/input.c:57 + Region("region-for-arg-gcc.ParmDecl('self')"): + repr(): Region("region-for-arg-gcc.ParmDecl('self')") + str(): Region("region-for-arg-gcc.ParmDecl('self')") + r->ob_refcnt: refs: 0 + N where N >= 1 + r->ob_type: PointerToRegion(gcctype='struct PyTypeObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/PyDict_SetItemString/incorrect/input.c', line=27), region=Region("region-for-type-of-arg-gcc.ParmDecl('self')")) + Region("region-for-arg-gcc.ParmDecl('args')"): + repr(): Region("region-for-arg-gcc.ParmDecl('args')") + str(): Region("region-for-arg-gcc.ParmDecl('args')") + r->ob_refcnt: refs: 0 + N where N >= 1 + r->ob_type: PointerToRegion(gcctype='struct PyTypeObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/PyDict_SetItemString/incorrect/input.c', line=27), region=Region("region-for-type-of-arg-gcc.ParmDecl('args')")) + new ref from (unknown) PyDict_New allocated at tests/cpychecker/refcounts/PyDict_SetItemString/incorrect/input.c:32: + repr(): RegionOnHeap('new ref from (unknown) PyDict_New', gcc.Location(file='tests/cpychecker/refcounts/PyDict_SetItemString/incorrect/input.c', line=32)) + str(): new ref from (unknown) PyDict_New allocated at tests/cpychecker/refcounts/PyDict_SetItemString/incorrect/input.c:32 + r->ob_refcnt: None + r->ob_type: None + PyLongObject allocated at tests/cpychecker/refcounts/PyDict_SetItemString/incorrect/input.c:37: + repr(): RegionOnHeap('PyLongObject', gcc.Location(file='tests/cpychecker/refcounts/PyDict_SetItemString/incorrect/input.c', line=37)) + str(): PyLongObject allocated at tests/cpychecker/refcounts/PyDict_SetItemString/incorrect/input.c:37 + r->ob_refcnt: refs: 0 + N where N >= 0 + r->ob_type: PointerToRegion(gcctype='struct PyTypeObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/PyDict_SetItemString/incorrect/input.c', line=37), region=RegionForGlobal(gcc.VarDecl('PyLong_Type'))) + Exception: + RegionForGlobal(gcc.VarDecl('PyExc_MemoryError')) + +Trace 4: + Transitions: + 'PyDict_New() succeeds' + 'taking False path' + 'PyLong_FromLong() succeeds' + 'taking False path' + 'PyDict_SetItemString() fails' + 'taking True path' + 'taking False path' + 'taking False path' + 'calling tp_dealloc on new ref from (unknown) PyDict_New allocated at tests/cpychecker/refcounts/PyDict_SetItemString/incorrect/input.c:32' + 'taking False path' + 'taking False path' + 'calling tp_dealloc on PyLongObject allocated at tests/cpychecker/refcounts/PyDict_SetItemString/incorrect/input.c:37' + 'returning' + Return value: + repr(): ConcreteValue(gcctype='struct PyObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/PyDict_SetItemString/incorrect/input.c', line=57), value=0) + str(): (struct PyObject *)0 from tests/cpychecker/refcounts/PyDict_SetItemString/incorrect/input.c:57 + Region("region-for-arg-gcc.ParmDecl('self')"): + repr(): Region("region-for-arg-gcc.ParmDecl('self')") + str(): Region("region-for-arg-gcc.ParmDecl('self')") + r->ob_refcnt: refs: 0 + N where N >= 1 + r->ob_type: PointerToRegion(gcctype='struct PyTypeObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/PyDict_SetItemString/incorrect/input.c', line=27), region=Region("region-for-type-of-arg-gcc.ParmDecl('self')")) + Region("region-for-arg-gcc.ParmDecl('args')"): + repr(): Region("region-for-arg-gcc.ParmDecl('args')") + str(): Region("region-for-arg-gcc.ParmDecl('args')") + r->ob_refcnt: refs: 0 + N where N >= 1 + r->ob_type: PointerToRegion(gcctype='struct PyTypeObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/PyDict_SetItemString/incorrect/input.c', line=27), region=Region("region-for-type-of-arg-gcc.ParmDecl('args')")) + new ref from (unknown) PyDict_New allocated at tests/cpychecker/refcounts/PyDict_SetItemString/incorrect/input.c:32: + repr(): RegionOnHeap('new ref from (unknown) PyDict_New', gcc.Location(file='tests/cpychecker/refcounts/PyDict_SetItemString/incorrect/input.c', line=32)) + str(): new ref from (unknown) PyDict_New allocated at tests/cpychecker/refcounts/PyDict_SetItemString/incorrect/input.c:32 + r->ob_refcnt: None + r->ob_type: None + PyLongObject allocated at tests/cpychecker/refcounts/PyDict_SetItemString/incorrect/input.c:37: + repr(): RegionOnHeap('PyLongObject', gcc.Location(file='tests/cpychecker/refcounts/PyDict_SetItemString/incorrect/input.c', line=37)) + str(): PyLongObject allocated at tests/cpychecker/refcounts/PyDict_SetItemString/incorrect/input.c:37 + r->ob_refcnt: None + r->ob_type: None + Exception: + RegionForGlobal(gcc.VarDecl('PyExc_MemoryError')) + +Trace 5: + Transitions: + 'PyDict_New() succeeds' + 'taking False path' + 'PyLong_FromLong() fails' + 'taking True path' + 'taking False path' + 'taking True path' + 'taking True path' + 'returning' + Return value: + repr(): ConcreteValue(gcctype='struct PyObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/PyDict_SetItemString/incorrect/input.c', line=57), value=0) + str(): (struct PyObject *)0 from tests/cpychecker/refcounts/PyDict_SetItemString/incorrect/input.c:57 + Region("region-for-arg-gcc.ParmDecl('self')"): + repr(): Region("region-for-arg-gcc.ParmDecl('self')") + str(): Region("region-for-arg-gcc.ParmDecl('self')") + r->ob_refcnt: refs: 0 + N where N >= 1 + r->ob_type: PointerToRegion(gcctype='struct PyTypeObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/PyDict_SetItemString/incorrect/input.c', line=27), region=Region("region-for-type-of-arg-gcc.ParmDecl('self')")) + Region("region-for-arg-gcc.ParmDecl('args')"): + repr(): Region("region-for-arg-gcc.ParmDecl('args')") + str(): Region("region-for-arg-gcc.ParmDecl('args')") + r->ob_refcnt: refs: 0 + N where N >= 1 + r->ob_type: PointerToRegion(gcctype='struct PyTypeObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/PyDict_SetItemString/incorrect/input.c', line=27), region=Region("region-for-type-of-arg-gcc.ParmDecl('args')")) + new ref from (unknown) PyDict_New allocated at tests/cpychecker/refcounts/PyDict_SetItemString/incorrect/input.c:32: + repr(): RegionOnHeap('new ref from (unknown) PyDict_New', gcc.Location(file='tests/cpychecker/refcounts/PyDict_SetItemString/incorrect/input.c', line=32)) + str(): new ref from (unknown) PyDict_New allocated at tests/cpychecker/refcounts/PyDict_SetItemString/incorrect/input.c:32 + r->ob_refcnt: refs: 0 + N where N >= 0 + r->ob_type: PointerToRegion(gcctype='struct PyTypeObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/PyDict_SetItemString/incorrect/input.c', line=32), region=Region('PyTypeObject for new ref from (unknown) PyDict_New')) + Exception: + RegionForGlobal(gcc.VarDecl('PyExc_MemoryError')) + +Trace 6: + Transitions: + 'PyDict_New() succeeds' + 'taking False path' + 'PyLong_FromLong() fails' + 'taking True path' + 'taking False path' + 'taking False path' + 'calling tp_dealloc on new ref from (unknown) PyDict_New allocated at tests/cpychecker/refcounts/PyDict_SetItemString/incorrect/input.c:32' + 'taking True path' + 'returning' + Return value: + repr(): ConcreteValue(gcctype='struct PyObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/PyDict_SetItemString/incorrect/input.c', line=57), value=0) + str(): (struct PyObject *)0 from tests/cpychecker/refcounts/PyDict_SetItemString/incorrect/input.c:57 + Region("region-for-arg-gcc.ParmDecl('self')"): + repr(): Region("region-for-arg-gcc.ParmDecl('self')") + str(): Region("region-for-arg-gcc.ParmDecl('self')") + r->ob_refcnt: refs: 0 + N where N >= 1 + r->ob_type: PointerToRegion(gcctype='struct PyTypeObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/PyDict_SetItemString/incorrect/input.c', line=27), region=Region("region-for-type-of-arg-gcc.ParmDecl('self')")) + Region("region-for-arg-gcc.ParmDecl('args')"): + repr(): Region("region-for-arg-gcc.ParmDecl('args')") + str(): Region("region-for-arg-gcc.ParmDecl('args')") + r->ob_refcnt: refs: 0 + N where N >= 1 + r->ob_type: PointerToRegion(gcctype='struct PyTypeObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/PyDict_SetItemString/incorrect/input.c', line=27), region=Region("region-for-type-of-arg-gcc.ParmDecl('args')")) + new ref from (unknown) PyDict_New allocated at tests/cpychecker/refcounts/PyDict_SetItemString/incorrect/input.c:32: + repr(): RegionOnHeap('new ref from (unknown) PyDict_New', gcc.Location(file='tests/cpychecker/refcounts/PyDict_SetItemString/incorrect/input.c', line=32)) + str(): new ref from (unknown) PyDict_New allocated at tests/cpychecker/refcounts/PyDict_SetItemString/incorrect/input.c:32 + r->ob_refcnt: None + r->ob_type: None + Exception: + RegionForGlobal(gcc.VarDecl('PyExc_MemoryError')) + +Trace 7: + Transitions: + 'PyDict_New() fails' + 'taking True path' + 'taking True path' + 'taking True path' + 'returning' + Return value: + repr(): ConcreteValue(gcctype='struct PyObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/PyDict_SetItemString/incorrect/input.c', line=57), value=0) + str(): (struct PyObject *)0 from tests/cpychecker/refcounts/PyDict_SetItemString/incorrect/input.c:57 + Region("region-for-arg-gcc.ParmDecl('self')"): + repr(): Region("region-for-arg-gcc.ParmDecl('self')") + str(): Region("region-for-arg-gcc.ParmDecl('self')") + r->ob_refcnt: refs: 0 + N where N >= 1 + r->ob_type: PointerToRegion(gcctype='struct PyTypeObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/PyDict_SetItemString/incorrect/input.c', line=27), region=Region("region-for-type-of-arg-gcc.ParmDecl('self')")) + Region("region-for-arg-gcc.ParmDecl('args')"): + repr(): Region("region-for-arg-gcc.ParmDecl('args')") + str(): Region("region-for-arg-gcc.ParmDecl('args')") + r->ob_refcnt: refs: 0 + N where N >= 1 + r->ob_type: PointerToRegion(gcctype='struct PyTypeObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/PyDict_SetItemString/incorrect/input.c', line=27), region=Region("region-for-type-of-arg-gcc.ParmDecl('args')")) + Exception: + RegionForGlobal(gcc.VarDecl('PyExc_MemoryError'))
gcc-python-plugin-commits@lists.stg.fedorahosted.org