commit f294898c1dc429e838c1c3e79eff57431a8239a4
Author: David Malcolm <dmalcolm(a)redhat.com>
Date: Thu Dec 22 15:48:04 2011 -0500
cpychecker: implement PyCapsule_GetPointer
libcpychecker/absinterp.py | 3 ++
libcpychecker/refcounts.py | 24 ++++++++++++-
.../refcounts/PyCapsule_GetPointer/basic/input.c | 38 ++++++++++++++++++++
.../refcounts/PyCapsule_GetPointer/basic/script.py | 22 +++++++++++
.../PyCapsule_GetPointer/basic/stdout.txt | 29 +++++++++++++++
5 files changed, 115 insertions(+), 1 deletions(-)
---
diff --git a/libcpychecker/absinterp.py b/libcpychecker/absinterp.py
index 5d69442..acc87ed 100644
--- a/libcpychecker/absinterp.py
+++ b/libcpychecker/absinterp.py
@@ -826,6 +826,9 @@ class UninitializedData(AbstractValue):
def extract_from_parent(self, region, gcctype, loc):
return UninitializedData(gcctype, self.loc)
+def make_null_ptr(gcctype, loc):
+ return ConcreteValue(gcctype, loc, 0)
+
############################################################################
# Various kinds of predicted error:
############################################################################
diff --git a/libcpychecker/refcounts.py b/libcpychecker/refcounts.py
index 4bb4f7f..9df2635 100644
--- a/libcpychecker/refcounts.py
+++ b/libcpychecker/refcounts.py
@@ -98,7 +98,7 @@ def stmt_is_return_of_objptr(stmt):
return True
def make_null_pyobject_ptr(stmt):
- return ConcreteValue(get_PyObjectPtr(), stmt.loc, 0)
+ return make_null_ptr(get_PyObjectPtr(), stmt.loc)
class RefcountValue(AbstractValue):
"""
@@ -960,6 +960,28 @@ class CPython(Facet):
fnmeta.desc_when_call_returns_value('0 (false)'))]
########################################################################
+ # PyCapsule_*
+ ########################################################################
+
+ def impl_PyCapsule_GetPointer(self, stmt, v_capsule, v_name):
+ fnmeta = FnMeta(name='PyCapsule_GetPointer',
+
docurl='http://docs.python.org/c-api/capsule.html#PyCapsule_GetPointe...;,
+ prototype='void* PyCapsule_GetPointer(PyObject *capsule,
const char *name)',
+ defined_in='Objects/capsule.c')
+ # either returns NULL, setting an exception, or returns non-NULL
+ t_success = self.state.mktrans_assignment(stmt.lhs,
+ UnknownValue.make(stmt.lhs.type,
+ stmt.loc),
+ fnmeta.desc_when_call_succeeds())
+ t_failure = self.state.mktrans_assignment(stmt.lhs,
+ make_null_ptr(stmt.lhs.type,
+ stmt.loc),
+ fnmeta.desc_when_call_fails())
+ t_failure.dest.cpython.set_exception('PyExc_ValueError',
+ stmt.loc)
+ return [t_success, t_failure]
+
+ ########################################################################
# PyCObject_*
########################################################################
diff --git a/tests/cpychecker/refcounts/PyCapsule_GetPointer/basic/input.c
b/tests/cpychecker/refcounts/PyCapsule_GetPointer/basic/input.c
new file mode 100644
index 0000000..4868143
--- /dev/null
+++ b/tests/cpychecker/refcounts/PyCapsule_GetPointer/basic/input.c
@@ -0,0 +1,38 @@
+/*
+ Copyright 2011 David Malcolm <dmalcolm(a)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>
+
+/*
+ Basic test coverage for our handler for PyCapsule_GetPointer
+*/
+
+void*
+test(PyObject *capsule, const char *name)
+{
+ return PyCapsule_GetPointer(capsule, name);
+}
+
+/*
+ PEP-7
+Local variables:
+c-basic-offset: 4
+indent-tabs-mode: nil
+End:
+*/
diff --git a/tests/cpychecker/refcounts/PyCapsule_GetPointer/basic/script.py
b/tests/cpychecker/refcounts/PyCapsule_GetPointer/basic/script.py
new file mode 100644
index 0000000..fdd5ba3
--- /dev/null
+++ b/tests/cpychecker/refcounts/PyCapsule_GetPointer/basic/script.py
@@ -0,0 +1,22 @@
+# -*- coding: utf-8 -*-
+# Copyright 2011 David Malcolm <dmalcolm(a)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/PyCapsule_GetPointer/basic/stdout.txt
b/tests/cpychecker/refcounts/PyCapsule_GetPointer/basic/stdout.txt
new file mode 100644
index 0000000..81cee3f
--- /dev/null
+++ b/tests/cpychecker/refcounts/PyCapsule_GetPointer/basic/stdout.txt
@@ -0,0 +1,29 @@
+Trace 0:
+ Transitions:
+ 'when PyCapsule_GetPointer() succeeds'
+ 'returning'
+ Return value:
+ repr(): UnknownValue(gcctype=<gcc.PointerType object at 0xdeadbeef>,
loc=gcc.Location(file='tests/cpychecker/refcounts/PyCapsule_GetPointer/basic/input.c',
line=29))
+ str(): unknown void * from
tests/cpychecker/refcounts/PyCapsule_GetPointer/basic/input.c:29
+ Region("region-for-arg-gcc.ParmDecl('capsule')"):
+ repr(): Region("region-for-arg-gcc.ParmDecl('capsule')")
+ str(): Region("region-for-arg-gcc.ParmDecl('capsule')")
+ r->ob_refcnt: refs: 0 + N where N >= 1
+ r->ob_type: PointerToRegion(gcctype='struct PyTypeObject *',
loc=gcc.Location(file='tests/cpychecker/refcounts/PyCapsule_GetPointer/basic/input.c',
line=27),
region=Region("region-for-type-of-arg-gcc.ParmDecl('capsule')"))
+ Exception:
+ (struct PyObject *)0 from
tests/cpychecker/refcounts/PyCapsule_GetPointer/basic/input.c:28
+
+Trace 1:
+ Transitions:
+ 'when PyCapsule_GetPointer() fails'
+ 'returning'
+ Return value:
+ repr(): ConcreteValue(gcctype='void *',
loc=gcc.Location(file='tests/cpychecker/refcounts/PyCapsule_GetPointer/basic/input.c',
line=29), value=0)
+ str(): (void *)0 from
tests/cpychecker/refcounts/PyCapsule_GetPointer/basic/input.c:29
+ Region("region-for-arg-gcc.ParmDecl('capsule')"):
+ repr(): Region("region-for-arg-gcc.ParmDecl('capsule')")
+ str(): Region("region-for-arg-gcc.ParmDecl('capsule')")
+ r->ob_refcnt: refs: 0 + N where N >= 1
+ r->ob_type: PointerToRegion(gcctype='struct PyTypeObject *',
loc=gcc.Location(file='tests/cpychecker/refcounts/PyCapsule_GetPointer/basic/input.c',
line=27),
region=Region("region-for-type-of-arg-gcc.ParmDecl('capsule')"))
+ Exception:
+ (struct PyObject *)&RegionForGlobal(gcc.VarDecl('PyExc_ValueError')) from
tests/cpychecker/refcounts/PyCapsule_GetPointer/basic/input.c:29