[prev in list] [next in list] [prev in thread] [next in thread] 

List:       gcc-python-plugin-commits
Subject:    [gcc-python-plugin] cpychecker: Py_BuildValue("s") expects a (char*)
From:       dmalcolm () fedoraproject ! org (dmalcolm)
Date:       2011-10-27 14:46:53
Message-ID: 20111027144653.8194A1202D3 () lists ! fedorahosted ! org
[Download RAW message or body]

commit eaf9b8665be224c47bb2371e3748232fdd4a8b07
Author: David Malcolm <dmalcolm at redhat.com>
Date:   Thu Oct 27 10:46:22 2011 -0400

    cpychecker: Py_BuildValue("s") expects a (char*)
    
    Py_BuildValue("s") expects a (char*), but can also accept a (const char*)

 libcpychecker/Py_BuildValue.py                     |    4 +-
 libcpychecker/formatstrings.py                     |   17 ++++++-
 .../code_s/incorrect-constness/input.c             |   48 ++++++++++++++++++++
 .../code_s/incorrect-constness/script.py           |   19 ++++++++
 .../code_s/incorrect-constness/stderr.txt          |    7 +++
 .../refcounts/Py_BuildValue/correct-code-s/input.c |    2 +-
 6 files changed, 92 insertions(+), 5 deletions(-)
---
diff --git a/libcpychecker/Py_BuildValue.py b/libcpychecker/Py_BuildValue.py
index 508ee56..79afcd3 100644
--- a/libcpychecker/Py_BuildValue.py
+++ b/libcpychecker/Py_BuildValue.py
@@ -205,12 +205,12 @@ class PyBuildValueFmt(ParsedFormatString):
             if c in 'sz':
                 if next == '#':
                     result.add_argument(c + '#',
-                                        [get_const_char_ptr(),
+                                        [get_char_ptr(),
                                          get_hash_size_type(with_size_t).pointer])
                     i += 1
                 else:
                     result.add_argument(c,
-                                        [get_const_char_ptr()])
+                                        [get_char_ptr()])
                 continue
 
             if c in 'NSO':
diff --git a/libcpychecker/formatstrings.py b/libcpychecker/formatstrings.py
index 11dfb1c..3037f6d 100644
--- a/libcpychecker/formatstrings.py
+++ b/libcpychecker/formatstrings.py
@@ -24,6 +24,9 @@ from libcpychecker.utils import log
 
 const_correctness = True
 
+def get_char_ptr():
+    return gcc.Type.char().pointer
+
 def get_const_char_ptr():
     return gcc.Type.char().const_equivalent.pointer
 
@@ -272,6 +275,16 @@ def compatible_type(exp_type, actual_type, actualarg=None):
         if compatible_type(exp_type.dereference, actual_type.dereference):
             return True
 
+    # Support (const char*) vs (char*)
+    # Somewhat counter-intuitively, the APIs that expect a char* are those that
+    # read the string data (Py_BuildValue); those that expect a const char* are
+    # those that write back a const char* value (PyArg_ParseTuple)
+    #
+    # Hence it's OK to accept a (const char*) when a (char*) was expected:
+    if str(exp_type) == 'char *':
+        if str(actual_type) == 'const char *':
+            return True
+
     # Don't be too fussy about typedefs to integer types
     # For instance:
     #   typedef unsigned PY_LONG_LONG gdb_py_ulongest;
@@ -288,8 +301,8 @@ def compatible_type(exp_type, actual_type, actualarg=None):
         if compare_int_types():
             return True
 
-    # Support character arrays vs const char*:
-    if str(exp_type) == 'const char *':
+    # Support character arrays vs char*:
+    if str(exp_type) == 'char *':
         if isinstance(actual_type, gcc.PointerType):
             if isinstance(actual_type.dereference, gcc.ArrayType):
                 if actual_type.dereference.dereference == gcc.Type.char():
diff --git a/tests/cpychecker/PyArg_ParseTuple/code_s/incorrect-constness/input.c \
b/tests/cpychecker/PyArg_ParseTuple/code_s/incorrect-constness/input.c new file mode \
100644 index 0000000..6e56419
--- /dev/null
+++ b/tests/cpychecker/PyArg_ParseTuple/code_s/incorrect-constness/input.c
@@ -0,0 +1,48 @@
+/*
+   Copyright 2011 David Malcolm <dmalcolm at 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/>.
+*/
+
+/*
+  Verify that the checker emits a warning for code "s" with a non-const
+  char*
+
+  Code "s" writes a pointer back to the insides of an object's representation,
+  so it really should be a (const char*), not just a (char*)
+*/
+#include <Python.h>
+
+PyObject *
+test(PyObject *self, PyObject *args)
+{
+    char *str;
+
+    if (!PyArg_ParseTuple(args, "s",
+                          &str)) {
+        return NULL;
+    }
+
+    Py_RETURN_NONE;
+}
+
+/*
+  PEP-7
+Local variables:
+c-basic-offset: 4
+indent-tabs-mode: nil
+End:
+*/
diff --git a/tests/cpychecker/PyArg_ParseTuple/code_s/incorrect-constness/script.py \
b/tests/cpychecker/PyArg_ParseTuple/code_s/incorrect-constness/script.py new file \
mode 100644 index 0000000..e120c53
--- /dev/null
+++ b/tests/cpychecker/PyArg_ParseTuple/code_s/incorrect-constness/script.py
@@ -0,0 +1,19 @@
+#   Copyright 2011 David Malcolm <dmalcolm at 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()
diff --git a/tests/cpychecker/PyArg_ParseTuple/code_s/incorrect-constness/stderr.txt \
b/tests/cpychecker/PyArg_ParseTuple/code_s/incorrect-constness/stderr.txt new file \
mode 100644 index 0000000..7aa7320
--- /dev/null
+++ b/tests/cpychecker/PyArg_ParseTuple/code_s/incorrect-constness/stderr.txt
@@ -0,0 +1,7 @@
+tests/cpychecker/PyArg_ParseTuple/code_s/incorrect-constness/input.c: In function \
'test': +tests/cpychecker/PyArg_ParseTuple/code_s/incorrect-constness/input.c:34:26: \
error: Mismatching type in call to PyArg_ParseTuple with format code "s" \
[-fpermissive] +  argument 3 ("&str") had type
+    "char * *"
+  but was expecting
+    "const char * *"
+  for format code "s"
diff --git a/tests/cpychecker/refcounts/Py_BuildValue/correct-code-s/input.c \
b/tests/cpychecker/refcounts/Py_BuildValue/correct-code-s/input.c index \
                2c2c2c6..3c4ed33 100644
--- a/tests/cpychecker/refcounts/Py_BuildValue/correct-code-s/input.c
+++ b/tests/cpychecker/refcounts/Py_BuildValue/correct-code-s/input.c
@@ -24,7 +24,7 @@
 */
 
 PyObject *
-test(const char *foo, const char *bar)
+test(const char *foo, char *bar)
 {
     return Py_BuildValue("(s, s)",
                          foo, bar);


[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic