From 585c9a4546685504cfdd9688ee90e74cb0fb3a58 Mon Sep 17 00:00:00 2001
From: Daniele Varrazzo <daniele.varrazzo@gmail.com>
Date: Fri, 24 Feb 2012 23:33:16 +0000
Subject: [PATCH] cpychecker: implement PySequence_SetItem

---
 libcpychecker/refcounts.py                         |   16 ++
 .../refcounts/PySequence_SetItem/correct/input.c   |   64 +++++++++
 .../refcounts/PySequence_SetItem/correct/script.py |   22 +++
 .../PySequence_SetItem/correct/stdout.txt          |  146 ++++++++++++++++++++
 .../refcounts/PySequence_SetItem/incorrect/input.c |   63 +++++++++
 .../PySequence_SetItem/incorrect/metadata.ini      |    3 +
 .../PySequence_SetItem/incorrect/script.py         |   22 +++
 .../PySequence_SetItem/incorrect/stderr.txt        |   17 +++
 .../PySequence_SetItem/incorrect/stdout.txt        |  111 +++++++++++++++
 9 files changed, 464 insertions(+), 0 deletions(-)
 create mode 100644 tests/cpychecker/refcounts/PySequence_SetItem/correct/input.c
 create mode 100644 tests/cpychecker/refcounts/PySequence_SetItem/correct/script.py
 create mode 100644 tests/cpychecker/refcounts/PySequence_SetItem/correct/stdout.txt
 create mode 100644 tests/cpychecker/refcounts/PySequence_SetItem/incorrect/input.c
 create mode 100644 tests/cpychecker/refcounts/PySequence_SetItem/incorrect/metadata.ini
 create mode 100644 tests/cpychecker/refcounts/PySequence_SetItem/incorrect/script.py
 create mode 100644 tests/cpychecker/refcounts/PySequence_SetItem/incorrect/stderr.txt
 create mode 100644 tests/cpychecker/refcounts/PySequence_SetItem/incorrect/stdout.txt

diff --git a/libcpychecker/refcounts.py b/libcpychecker/refcounts.py
index 0cdcdc4..77e2c1d 100644
--- a/libcpychecker/refcounts.py
+++ b/libcpychecker/refcounts.py
@@ -2717,6 +2717,22 @@ class CPython(Facet):
                                                          fnmeta,
                                                          'new ref from %s' % fnmeta.name)
 
+    def impl_PySequence_SetItem(self, stmt, v_o, v_i, v_item):
+        fnmeta = FnMeta(name='PySequence_SetItem',
+                        prototype='int PySequence_SetItem(PyObject *o, Py_ssize_t i, PyObject *item)',
+                        docurl='http://docs.python.org/c-api/sequence.html#PySequence_SetItem',)
+
+        result = []
+
+        s_success  = self.state.mkstate_concrete_return_of(stmt, 0)
+        # The function *doesn't* steal a reference to item
+
+        result.append(Transition(self.state,
+                                 s_success,
+                                 '%s() succeeds' % fnmeta.name))
+
+        return result
+
     ########################################################################
     # PyString_*
     ########################################################################
diff --git a/tests/cpychecker/refcounts/PySequence_SetItem/correct/input.c b/tests/cpychecker/refcounts/PySequence_SetItem/correct/input.c
new file mode 100644
index 0000000..7f19a5d
--- /dev/null
+++ b/tests/cpychecker/refcounts/PySequence_SetItem/correct/input.c
@@ -0,0 +1,64 @@
+/*
+   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>
+
+PyObject *
+handle_SetItem(PyObject *self, PyObject *args)
+{
+    PyObject *list;
+    PyObject *item;
+    int rv;
+
+    list = PyList_New(1);
+    if (!list) {
+        return NULL;
+    }
+
+    item = PyLong_FromLong(42);
+    if (!item) {
+        Py_DECREF(list);
+        return NULL;
+    }
+
+    /* Set the item in the list via PySequence_SetItem() */
+    rv = PySequence_SetItem(list, 0, item);
+    if (rv != 0) {
+        Py_DECREF(list);
+        Py_DECREF(item);
+        return NULL;
+    }
+
+    /* the function doesn't steal a ref, so leaving item here would be a leak */
+    Py_DECREF(item);
+
+    return list;
+}
+static PyMethodDef test_methods[] = {
+    {"test_method",  handle_SetItem, 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/PySequence_SetItem/correct/script.py b/tests/cpychecker/refcounts/PySequence_SetItem/correct/script.py
new file mode 100644
index 0000000..6bb62fd
--- /dev/null
+++ b/tests/cpychecker/refcounts/PySequence_SetItem/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)
diff --git a/tests/cpychecker/refcounts/PySequence_SetItem/correct/stdout.txt b/tests/cpychecker/refcounts/PySequence_SetItem/correct/stdout.txt
new file mode 100644
index 0000000..f4988aa
--- /dev/null
+++ b/tests/cpychecker/refcounts/PySequence_SetItem/correct/stdout.txt
@@ -0,0 +1,146 @@
+Trace 0:
+  Transitions:
+    'when PyList_New() succeeds'
+    'taking False path'
+    'when PyLong_FromLong() succeeds'
+    'taking False path'
+    'PySequence_SetItem() succeeds'
+    'taking False path'
+    'when taking True path'
+    'returning'
+  Return value:
+    repr(): PointerToRegion(gcctype='struct PyObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/PySequence_SetItem/correct/input.c', line=29), region=RegionOnHeap('PyListObject', gcc.Location(file='tests/cpychecker/refcounts/PySequence_SetItem/correct/input.c', line=29)))
+    str(): (struct PyObject *)&RegionOnHeap('PyListObject', gcc.Location(file='tests/cpychecker/refcounts/PySequence_SetItem/correct/input.c', line=29)) from tests/cpychecker/refcounts/PySequence_SetItem/correct/input.c:29
+    r->ob_refcnt: refs: 1 + N where N >= 0
+    r->ob_type: PointerToRegion(gcctype='struct PyTypeObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/PySequence_SetItem/correct/input.c', line=29), region=RegionForGlobal(gcc.VarDecl('PyList_Type')))
+  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/PySequence_SetItem/correct/input.c', line=23), 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/PySequence_SetItem/correct/input.c', line=23), region=Region("region-for-type-of-arg-gcc.ParmDecl('args')"))
+  PyLongObject allocated at tests/cpychecker/refcounts/PySequence_SetItem/correct/input.c:34:
+    repr(): RegionOnHeap('PyLongObject', gcc.Location(file='tests/cpychecker/refcounts/PySequence_SetItem/correct/input.c', line=34))
+    str(): PyLongObject allocated at tests/cpychecker/refcounts/PySequence_SetItem/correct/input.c:34
+    r->ob_refcnt: refs: 0 + N where N >= 0
+    r->ob_type: PointerToRegion(gcctype='struct PyTypeObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/PySequence_SetItem/correct/input.c', line=34), region=RegionForGlobal(gcc.VarDecl('PyLong_Type')))
+  Exception:
+    (struct PyObject *)0 from tests/cpychecker/refcounts/PySequence_SetItem/correct/input.c:24
+
+Trace 1:
+  Transitions:
+    'when PyList_New() succeeds'
+    'taking False path'
+    'when PyLong_FromLong() succeeds'
+    'taking False path'
+    'PySequence_SetItem() succeeds'
+    'taking False path'
+    'when taking False path'
+    'calling tp_dealloc on PyLongObject allocated at tests/cpychecker/refcounts/PySequence_SetItem/correct/input.c:34'
+    'returning'
+  Return value:
+    repr(): PointerToRegion(gcctype='struct PyObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/PySequence_SetItem/correct/input.c', line=29), region=RegionOnHeap('PyListObject', gcc.Location(file='tests/cpychecker/refcounts/PySequence_SetItem/correct/input.c', line=29)))
+    str(): (struct PyObject *)&RegionOnHeap('PyListObject', gcc.Location(file='tests/cpychecker/refcounts/PySequence_SetItem/correct/input.c', line=29)) from tests/cpychecker/refcounts/PySequence_SetItem/correct/input.c:29
+    r->ob_refcnt: refs: 1 + N where N >= 0
+    r->ob_type: PointerToRegion(gcctype='struct PyTypeObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/PySequence_SetItem/correct/input.c', line=29), region=RegionForGlobal(gcc.VarDecl('PyList_Type')))
+  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/PySequence_SetItem/correct/input.c', line=23), 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/PySequence_SetItem/correct/input.c', line=23), region=Region("region-for-type-of-arg-gcc.ParmDecl('args')"))
+  PyLongObject allocated at tests/cpychecker/refcounts/PySequence_SetItem/correct/input.c:34:
+    repr(): RegionOnHeap('PyLongObject', gcc.Location(file='tests/cpychecker/refcounts/PySequence_SetItem/correct/input.c', line=34))
+    str(): PyLongObject allocated at tests/cpychecker/refcounts/PySequence_SetItem/correct/input.c:34
+    r->ob_refcnt: None
+    r->ob_type: None
+  Exception:
+    (struct PyObject *)0 from tests/cpychecker/refcounts/PySequence_SetItem/correct/input.c:24
+
+Trace 2:
+  Transitions:
+    'when PyList_New() succeeds'
+    'taking False path'
+    'when PyLong_FromLong() fails'
+    'taking True path'
+    'when taking True path'
+    'returning'
+  Return value:
+    repr(): ConcreteValue(gcctype='struct PyObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/PySequence_SetItem/correct/input.c', line=37), value=0)
+    str(): (struct PyObject *)0 from tests/cpychecker/refcounts/PySequence_SetItem/correct/input.c:37
+  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/PySequence_SetItem/correct/input.c', line=23), 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/PySequence_SetItem/correct/input.c', line=23), region=Region("region-for-type-of-arg-gcc.ParmDecl('args')"))
+  PyListObject allocated at tests/cpychecker/refcounts/PySequence_SetItem/correct/input.c:29:
+    repr(): RegionOnHeap('PyListObject', gcc.Location(file='tests/cpychecker/refcounts/PySequence_SetItem/correct/input.c', line=29))
+    str(): PyListObject allocated at tests/cpychecker/refcounts/PySequence_SetItem/correct/input.c:29
+    r->ob_refcnt: refs: 0 + N where N >= 0
+    r->ob_type: PointerToRegion(gcctype='struct PyTypeObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/PySequence_SetItem/correct/input.c', line=29), region=RegionForGlobal(gcc.VarDecl('PyList_Type')))
+  Exception:
+    (struct PyObject *)&RegionForGlobal(gcc.VarDecl('PyExc_MemoryError')) from tests/cpychecker/refcounts/PySequence_SetItem/correct/input.c:34
+
+Trace 3:
+  Transitions:
+    'when PyList_New() succeeds'
+    'taking False path'
+    'when PyLong_FromLong() fails'
+    'taking True path'
+    'when taking False path'
+    'calling tp_dealloc on PyListObject allocated at tests/cpychecker/refcounts/PySequence_SetItem/correct/input.c:29'
+    'returning'
+  Return value:
+    repr(): ConcreteValue(gcctype='struct PyObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/PySequence_SetItem/correct/input.c', line=37), value=0)
+    str(): (struct PyObject *)0 from tests/cpychecker/refcounts/PySequence_SetItem/correct/input.c:37
+  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/PySequence_SetItem/correct/input.c', line=23), 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/PySequence_SetItem/correct/input.c', line=23), region=Region("region-for-type-of-arg-gcc.ParmDecl('args')"))
+  PyListObject allocated at tests/cpychecker/refcounts/PySequence_SetItem/correct/input.c:29:
+    repr(): RegionOnHeap('PyListObject', gcc.Location(file='tests/cpychecker/refcounts/PySequence_SetItem/correct/input.c', line=29))
+    str(): PyListObject allocated at tests/cpychecker/refcounts/PySequence_SetItem/correct/input.c:29
+    r->ob_refcnt: None
+    r->ob_type: None
+  Exception:
+    (struct PyObject *)&RegionForGlobal(gcc.VarDecl('PyExc_MemoryError')) from tests/cpychecker/refcounts/PySequence_SetItem/correct/input.c:34
+
+Trace 4:
+  Transitions:
+    'when PyList_New() fails'
+    'taking True path'
+    'returning'
+  Return value:
+    repr(): ConcreteValue(gcctype='struct PyObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/PySequence_SetItem/correct/input.c', line=31), value=0)
+    str(): (struct PyObject *)0 from tests/cpychecker/refcounts/PySequence_SetItem/correct/input.c:31
+  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/PySequence_SetItem/correct/input.c', line=23), 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/PySequence_SetItem/correct/input.c', line=23), region=Region("region-for-type-of-arg-gcc.ParmDecl('args')"))
+  Exception:
+    (struct PyObject *)&RegionForGlobal(gcc.VarDecl('PyExc_MemoryError')) from tests/cpychecker/refcounts/PySequence_SetItem/correct/input.c:29
diff --git a/tests/cpychecker/refcounts/PySequence_SetItem/incorrect/input.c b/tests/cpychecker/refcounts/PySequence_SetItem/incorrect/input.c
new file mode 100644
index 0000000..fb8ba36
--- /dev/null
+++ b/tests/cpychecker/refcounts/PySequence_SetItem/incorrect/input.c
@@ -0,0 +1,63 @@
+/*
+   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>
+
+PyObject *
+handle_SetItem(PyObject *self, PyObject *args)
+{
+    PyObject *list;
+    PyObject *item;
+    int rv;
+
+    list = PyList_New(1);
+    if (!list) {
+        return NULL;
+    }
+
+    item = PyLong_FromLong(42);
+    if (!item) {
+        Py_DECREF(list);
+        return NULL;
+    }
+
+    /* Set the item in the list via PySequence_SetItem() */
+    rv = PySequence_SetItem(list, 0, item);
+    if (rv != 0) {
+        Py_DECREF(list);
+        Py_DECREF(item);
+        return NULL;
+    }
+
+    /* ERROR: we are still keeping a reference on item */
+
+    return list;
+}
+static PyMethodDef test_methods[] = {
+    {"test_method",  handle_SetItem, 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/PySequence_SetItem/incorrect/metadata.ini b/tests/cpychecker/refcounts/PySequence_SetItem/incorrect/metadata.ini
new file mode 100644
index 0000000..0d5711c
--- /dev/null
+++ b/tests/cpychecker/refcounts/PySequence_SetItem/incorrect/metadata.ini
@@ -0,0 +1,3 @@
+[ExpectedBehavior]
+# We expect only compilation *warnings*, so we expect a 0 exit code
+exitcode = 0
diff --git a/tests/cpychecker/refcounts/PySequence_SetItem/incorrect/script.py b/tests/cpychecker/refcounts/PySequence_SetItem/incorrect/script.py
new file mode 100644
index 0000000..6bb62fd
--- /dev/null
+++ b/tests/cpychecker/refcounts/PySequence_SetItem/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)
diff --git a/tests/cpychecker/refcounts/PySequence_SetItem/incorrect/stderr.txt b/tests/cpychecker/refcounts/PySequence_SetItem/incorrect/stderr.txt
new file mode 100644
index 0000000..bcaf1f1
--- /dev/null
+++ b/tests/cpychecker/refcounts/PySequence_SetItem/incorrect/stderr.txt
@@ -0,0 +1,17 @@
+tests/cpychecker/refcounts/PySequence_SetItem/incorrect/input.c: In function 'handle_SetItem':
+tests/cpychecker/refcounts/PySequence_SetItem/incorrect/input.c:51:nn: warning: ob_refcnt of '*item' is 1 too high [enabled by default]
+tests/cpychecker/refcounts/PySequence_SetItem/incorrect/input.c:51:nn: note: was expecting final ob_refcnt to be N + 0 (for some unknown N)
+tests/cpychecker/refcounts/PySequence_SetItem/incorrect/input.c:51:nn: note: but final ob_refcnt is N + 1
+tests/cpychecker/refcounts/PySequence_SetItem/incorrect/input.c:34:nn: note: PyLongObject allocated at:     item = PyLong_FromLong(42);
+tests/cpychecker/refcounts/PySequence_SetItem/incorrect/input.c:29:nn: note: when PyList_New() succeeds at:     list = PyList_New(1);
+tests/cpychecker/refcounts/PySequence_SetItem/incorrect/input.c:30:nn: note: taking False path at:     if (!list) {
+tests/cpychecker/refcounts/PySequence_SetItem/incorrect/input.c:34:nn: note: reaching:     item = PyLong_FromLong(42);
+tests/cpychecker/refcounts/PySequence_SetItem/incorrect/input.c:34:nn: note: when PyLong_FromLong() succeeds at:     item = PyLong_FromLong(42);
+tests/cpychecker/refcounts/PySequence_SetItem/incorrect/input.c:34:nn: note: ob_refcnt is now refs: 1 + N where N >= 0
+tests/cpychecker/refcounts/PySequence_SetItem/incorrect/input.c:35:nn: note: taking False path at:     if (!item) {
+tests/cpychecker/refcounts/PySequence_SetItem/incorrect/input.c:41:nn: note: reaching:     rv = PySequence_SetItem(list, 0, item);
+tests/cpychecker/refcounts/PySequence_SetItem/incorrect/input.c:41:nn: note: PySequence_SetItem() succeeds at:     rv = PySequence_SetItem(list, 0, item);
+tests/cpychecker/refcounts/PySequence_SetItem/incorrect/input.c:42:nn: note: taking False path at:     if (rv != 0) {
+tests/cpychecker/refcounts/PySequence_SetItem/incorrect/input.c:50:nn: note: reaching:     return list;
+tests/cpychecker/refcounts/PySequence_SetItem/incorrect/input.c:51:nn: note: returning
+tests/cpychecker/refcounts/PySequence_SetItem/incorrect/input.c:24:nn: note: graphical error report for function 'handle_SetItem' written out to 'tests/cpychecker/refcounts/PySequence_SetItem/incorrect/input.c.handle_SetItem-refcount-errors.html'
diff --git a/tests/cpychecker/refcounts/PySequence_SetItem/incorrect/stdout.txt b/tests/cpychecker/refcounts/PySequence_SetItem/incorrect/stdout.txt
new file mode 100644
index 0000000..5f20363
--- /dev/null
+++ b/tests/cpychecker/refcounts/PySequence_SetItem/incorrect/stdout.txt
@@ -0,0 +1,111 @@
+Trace 0:
+  Transitions:
+    'when PyList_New() succeeds'
+    'taking False path'
+    'when PyLong_FromLong() succeeds'
+    'taking False path'
+    'PySequence_SetItem() succeeds'
+    'taking False path'
+    'returning'
+  Return value:
+    repr(): PointerToRegion(gcctype='struct PyObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/PySequence_SetItem/incorrect/input.c', line=29), region=RegionOnHeap('PyListObject', gcc.Location(file='tests/cpychecker/refcounts/PySequence_SetItem/incorrect/input.c', line=29)))
+    str(): (struct PyObject *)&RegionOnHeap('PyListObject', gcc.Location(file='tests/cpychecker/refcounts/PySequence_SetItem/incorrect/input.c', line=29)) from tests/cpychecker/refcounts/PySequence_SetItem/incorrect/input.c:29
+    r->ob_refcnt: refs: 1 + N where N >= 0
+    r->ob_type: PointerToRegion(gcctype='struct PyTypeObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/PySequence_SetItem/incorrect/input.c', line=29), region=RegionForGlobal(gcc.VarDecl('PyList_Type')))
+  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/PySequence_SetItem/incorrect/input.c', line=23), 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/PySequence_SetItem/incorrect/input.c', line=23), region=Region("region-for-type-of-arg-gcc.ParmDecl('args')"))
+  PyLongObject allocated at tests/cpychecker/refcounts/PySequence_SetItem/incorrect/input.c:34:
+    repr(): RegionOnHeap('PyLongObject', gcc.Location(file='tests/cpychecker/refcounts/PySequence_SetItem/incorrect/input.c', line=34))
+    str(): PyLongObject allocated at tests/cpychecker/refcounts/PySequence_SetItem/incorrect/input.c:34
+    r->ob_refcnt: refs: 1 + N where N >= 0
+    r->ob_type: PointerToRegion(gcctype='struct PyTypeObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/PySequence_SetItem/incorrect/input.c', line=34), region=RegionForGlobal(gcc.VarDecl('PyLong_Type')))
+  Exception:
+    (struct PyObject *)0 from tests/cpychecker/refcounts/PySequence_SetItem/incorrect/input.c:24
+
+Trace 1:
+  Transitions:
+    'when PyList_New() succeeds'
+    'taking False path'
+    'when PyLong_FromLong() fails'
+    'taking True path'
+    'when taking True path'
+    'returning'
+  Return value:
+    repr(): ConcreteValue(gcctype='struct PyObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/PySequence_SetItem/incorrect/input.c', line=37), value=0)
+    str(): (struct PyObject *)0 from tests/cpychecker/refcounts/PySequence_SetItem/incorrect/input.c:37
+  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/PySequence_SetItem/incorrect/input.c', line=23), 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/PySequence_SetItem/incorrect/input.c', line=23), region=Region("region-for-type-of-arg-gcc.ParmDecl('args')"))
+  PyListObject allocated at tests/cpychecker/refcounts/PySequence_SetItem/incorrect/input.c:29:
+    repr(): RegionOnHeap('PyListObject', gcc.Location(file='tests/cpychecker/refcounts/PySequence_SetItem/incorrect/input.c', line=29))
+    str(): PyListObject allocated at tests/cpychecker/refcounts/PySequence_SetItem/incorrect/input.c:29
+    r->ob_refcnt: refs: 0 + N where N >= 0
+    r->ob_type: PointerToRegion(gcctype='struct PyTypeObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/PySequence_SetItem/incorrect/input.c', line=29), region=RegionForGlobal(gcc.VarDecl('PyList_Type')))
+  Exception:
+    (struct PyObject *)&RegionForGlobal(gcc.VarDecl('PyExc_MemoryError')) from tests/cpychecker/refcounts/PySequence_SetItem/incorrect/input.c:34
+
+Trace 2:
+  Transitions:
+    'when PyList_New() succeeds'
+    'taking False path'
+    'when PyLong_FromLong() fails'
+    'taking True path'
+    'when taking False path'
+    'calling tp_dealloc on PyListObject allocated at tests/cpychecker/refcounts/PySequence_SetItem/incorrect/input.c:29'
+    'returning'
+  Return value:
+    repr(): ConcreteValue(gcctype='struct PyObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/PySequence_SetItem/incorrect/input.c', line=37), value=0)
+    str(): (struct PyObject *)0 from tests/cpychecker/refcounts/PySequence_SetItem/incorrect/input.c:37
+  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/PySequence_SetItem/incorrect/input.c', line=23), 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/PySequence_SetItem/incorrect/input.c', line=23), region=Region("region-for-type-of-arg-gcc.ParmDecl('args')"))
+  PyListObject allocated at tests/cpychecker/refcounts/PySequence_SetItem/incorrect/input.c:29:
+    repr(): RegionOnHeap('PyListObject', gcc.Location(file='tests/cpychecker/refcounts/PySequence_SetItem/incorrect/input.c', line=29))
+    str(): PyListObject allocated at tests/cpychecker/refcounts/PySequence_SetItem/incorrect/input.c:29
+    r->ob_refcnt: None
+    r->ob_type: None
+  Exception:
+    (struct PyObject *)&RegionForGlobal(gcc.VarDecl('PyExc_MemoryError')) from tests/cpychecker/refcounts/PySequence_SetItem/incorrect/input.c:34
+
+Trace 3:
+  Transitions:
+    'when PyList_New() fails'
+    'taking True path'
+    'returning'
+  Return value:
+    repr(): ConcreteValue(gcctype='struct PyObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/PySequence_SetItem/incorrect/input.c', line=31), value=0)
+    str(): (struct PyObject *)0 from tests/cpychecker/refcounts/PySequence_SetItem/incorrect/input.c:31
+  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/PySequence_SetItem/incorrect/input.c', line=23), 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/PySequence_SetItem/incorrect/input.c', line=23), region=Region("region-for-type-of-arg-gcc.ParmDecl('args')"))
+  Exception:
+    (struct PyObject *)&RegionForGlobal(gcc.VarDecl('PyExc_MemoryError')) from tests/cpychecker/refcounts/PySequence_SetItem/incorrect/input.c:29
-- 
1.7.5.4

