commit 517cda7fc22b1d058c5b150b484548304dbb9d2d Author: David Malcolm dmalcolm@redhat.com Date: Mon Sep 5 19:02:17 2011 -0400
cpychecker: implement PySys_SetObject
libcpychecker/refcounts.py | 27 ++++ .../refcounts/PySys_SetObject/correct/input.c | 53 ++++++++ .../refcounts/PySys_SetObject/correct/script.py | 22 +++ .../refcounts/PySys_SetObject/correct/stdout.txt | 142 ++++++++++++++++++++ 4 files changed, 244 insertions(+), 0 deletions(-) --- diff --git a/libcpychecker/refcounts.py b/libcpychecker/refcounts.py index f1d877e..dda2cd4 100644 --- a/libcpychecker/refcounts.py +++ b/libcpychecker/refcounts.py @@ -1303,6 +1303,33 @@ class MyState(State): return [t_success, t_failure]
######################################################################## + # PySys_* + ######################################################################## + def impl_PySys_SetObject(self, stmt): + # Declated in sysmodule.h + # Defined in Python/sysmodule.c: + # int PySys_SetObject(char *name, PyObject *v) + # Docs: + # http://docs.python.org/c-api/sys.html#PySys_SetObject + # + # can be called with NULL or non-NULL, calls PyDict_SetItemString + # on non-NULL, which adds a ref on it + fnname = 'PySys_SetObject' + returntype = stmt.fn.type.dereference.type + args = self.eval_stmt_args(stmt) + v_name, v_value = args + t_success = self.mktrans_assignment(stmt.lhs, + ConcreteValue(returntype, stmt.loc, 0), + '%s() succeeds' % fnname) + if isinstance(v_value, PointerToRegion): + t_success.dest.add_external_ref(v_value, stmt.loc) + t_failure = self.mktrans_assignment(stmt.lhs, + ConcreteValue(returntype, stmt.loc, -1), + '%s() fails' % fnname) + t_failure.dest.set_exception('PyExc_MemoryError') + return [t_success, t_failure] + + ######################################################################## # PyTuple_* ######################################################################## def impl_PyTuple_New(self, stmt): diff --git a/tests/cpychecker/refcounts/PySys_SetObject/correct/input.c b/tests/cpychecker/refcounts/PySys_SetObject/correct/input.c new file mode 100644 index 0000000..0ee1ad2 --- /dev/null +++ b/tests/cpychecker/refcounts/PySys_SetObject/correct/input.c @@ -0,0 +1,53 @@ +/* + 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 PySys_SetObject + with a non-NULL argument +*/ + +PyObject * +test(PyObject *self, PyObject *args) +{ + PyObject *str; + str = PyString_FromString("hello world"); + if (!str) { + return NULL; + } + /* we own a ref on the string */ + /* if successful, this adds a ref on the string: */ + PySys_SetObject("greeting", str); + /* get rid of our ref on the string: */ + Py_DECREF(str); + Py_RETURN_NONE; +} +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/PySys_SetObject/correct/script.py b/tests/cpychecker/refcounts/PySys_SetObject/correct/script.py new file mode 100644 index 0000000..fdd5ba3 --- /dev/null +++ b/tests/cpychecker/refcounts/PySys_SetObject/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/PySys_SetObject/correct/stdout.txt b/tests/cpychecker/refcounts/PySys_SetObject/correct/stdout.txt new file mode 100644 index 0000000..ba0eb88 --- /dev/null +++ b/tests/cpychecker/refcounts/PySys_SetObject/correct/stdout.txt @@ -0,0 +1,142 @@ +Trace 0: + Transitions: + 'PyString_FromString() succeeds' + 'taking False path' + 'PySys_SetObject() succeeds' + 'taking True path' + 'returning' + Return value: + repr(): PointerToRegion(gcctype='struct PyObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/PySys_SetObject/correct/input.c', line=40), region=RegionForGlobal(gcc.VarDecl('_Py_NoneStruct'))) + str(): (struct PyObject *)&RegionForGlobal(gcc.VarDecl('_Py_NoneStruct')) from tests/cpychecker/refcounts/PySys_SetObject/correct/input.c:40 + r->ob_refcnt: refs: 1 + N where N >= 1 + r->ob_type: None + 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/PySys_SetObject/correct/input.c', line=28), 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/PySys_SetObject/correct/input.c', line=28), region=Region("region-for-type-of-arg-gcc.ParmDecl('args')")) + PyStringObject allocated at tests/cpychecker/refcounts/PySys_SetObject/correct/input.c:31: + repr(): RegionOnHeap('PyStringObject', gcc.Location(file='tests/cpychecker/refcounts/PySys_SetObject/correct/input.c', line=31)) + str(): PyStringObject allocated at tests/cpychecker/refcounts/PySys_SetObject/correct/input.c:31 + r->ob_refcnt: refs: 0 + N where N >= 1 + r->ob_type: PointerToRegion(gcctype='struct PyTypeObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/PySys_SetObject/correct/input.c', line=31), region=RegionForGlobal(gcc.VarDecl('PyString_Type'))) + Exception: + (struct PyObject *)0 from tests/cpychecker/refcounts/PySys_SetObject/correct/input.c:29 + +Trace 1: + Transitions: + 'PyString_FromString() succeeds' + 'taking False path' + 'PySys_SetObject() succeeds' + 'taking False path' + 'calling tp_dealloc on PyStringObject allocated at tests/cpychecker/refcounts/PySys_SetObject/correct/input.c:31' + 'returning' + Return value: + repr(): PointerToRegion(gcctype='struct PyObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/PySys_SetObject/correct/input.c', line=40), region=RegionForGlobal(gcc.VarDecl('_Py_NoneStruct'))) + str(): (struct PyObject *)&RegionForGlobal(gcc.VarDecl('_Py_NoneStruct')) from tests/cpychecker/refcounts/PySys_SetObject/correct/input.c:40 + r->ob_refcnt: refs: 1 + N where N >= 1 + r->ob_type: None + 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/PySys_SetObject/correct/input.c', line=28), 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/PySys_SetObject/correct/input.c', line=28), region=Region("region-for-type-of-arg-gcc.ParmDecl('args')")) + PyStringObject allocated at tests/cpychecker/refcounts/PySys_SetObject/correct/input.c:31: + repr(): RegionOnHeap('PyStringObject', gcc.Location(file='tests/cpychecker/refcounts/PySys_SetObject/correct/input.c', line=31)) + str(): PyStringObject allocated at tests/cpychecker/refcounts/PySys_SetObject/correct/input.c:31 + r->ob_refcnt: None + r->ob_type: None + Exception: + (struct PyObject *)0 from tests/cpychecker/refcounts/PySys_SetObject/correct/input.c:29 + +Trace 2: + Transitions: + 'PyString_FromString() succeeds' + 'taking False path' + 'PySys_SetObject() fails' + 'taking True path' + 'returning' + Return value: + repr(): PointerToRegion(gcctype='struct PyObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/PySys_SetObject/correct/input.c', line=40), region=RegionForGlobal(gcc.VarDecl('_Py_NoneStruct'))) + str(): (struct PyObject *)&RegionForGlobal(gcc.VarDecl('_Py_NoneStruct')) from tests/cpychecker/refcounts/PySys_SetObject/correct/input.c:40 + r->ob_refcnt: refs: 1 + N where N >= 1 + r->ob_type: None + 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/PySys_SetObject/correct/input.c', line=28), 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/PySys_SetObject/correct/input.c', line=28), region=Region("region-for-type-of-arg-gcc.ParmDecl('args')")) + PyStringObject allocated at tests/cpychecker/refcounts/PySys_SetObject/correct/input.c:31: + repr(): RegionOnHeap('PyStringObject', gcc.Location(file='tests/cpychecker/refcounts/PySys_SetObject/correct/input.c', line=31)) + str(): PyStringObject allocated at tests/cpychecker/refcounts/PySys_SetObject/correct/input.c:31 + r->ob_refcnt: refs: 0 + N where N >= 0 + r->ob_type: PointerToRegion(gcctype='struct PyTypeObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/PySys_SetObject/correct/input.c', line=31), region=RegionForGlobal(gcc.VarDecl('PyString_Type'))) + Exception: + RegionForGlobal(gcc.VarDecl('PyExc_MemoryError')) + +Trace 3: + Transitions: + 'PyString_FromString() succeeds' + 'taking False path' + 'PySys_SetObject() fails' + 'taking False path' + 'calling tp_dealloc on PyStringObject allocated at tests/cpychecker/refcounts/PySys_SetObject/correct/input.c:31' + 'returning' + Return value: + repr(): PointerToRegion(gcctype='struct PyObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/PySys_SetObject/correct/input.c', line=40), region=RegionForGlobal(gcc.VarDecl('_Py_NoneStruct'))) + str(): (struct PyObject *)&RegionForGlobal(gcc.VarDecl('_Py_NoneStruct')) from tests/cpychecker/refcounts/PySys_SetObject/correct/input.c:40 + r->ob_refcnt: refs: 1 + N where N >= 1 + r->ob_type: None + 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/PySys_SetObject/correct/input.c', line=28), 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/PySys_SetObject/correct/input.c', line=28), region=Region("region-for-type-of-arg-gcc.ParmDecl('args')")) + PyStringObject allocated at tests/cpychecker/refcounts/PySys_SetObject/correct/input.c:31: + repr(): RegionOnHeap('PyStringObject', gcc.Location(file='tests/cpychecker/refcounts/PySys_SetObject/correct/input.c', line=31)) + str(): PyStringObject allocated at tests/cpychecker/refcounts/PySys_SetObject/correct/input.c:31 + r->ob_refcnt: None + r->ob_type: None + Exception: + RegionForGlobal(gcc.VarDecl('PyExc_MemoryError')) + +Trace 4: + Transitions: + 'PyString_FromString() fails' + 'taking True path' + 'returning' + Return value: + repr(): ConcreteValue(gcctype='struct PyObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/PySys_SetObject/correct/input.c', line=33), value=0) + str(): (struct PyObject *)0 from tests/cpychecker/refcounts/PySys_SetObject/correct/input.c:33 + 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/PySys_SetObject/correct/input.c', line=28), 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/PySys_SetObject/correct/input.c', line=28), region=Region("region-for-type-of-arg-gcc.ParmDecl('args')")) + Exception: + RegionForGlobal(gcc.VarDecl('PyExc_MemoryError'))
gcc-python-plugin-commits@lists.stg.fedorahosted.org