Library: document not-null and not-uninit argument configuration

This commit is contained in:
Daniel Marjamäki 2013-07-15 21:58:29 +02:00
parent 24dfc052e2
commit 2a884446be
3 changed files with 124 additions and 56 deletions

View File

@ -91,14 +91,18 @@ bool Library::load(const char path[])
_noreturn[name] = (strcmp(functionnode->GetText(), "true") == 0); _noreturn[name] = (strcmp(functionnode->GetText(), "true") == 0);
else if (strcmp(functionnode->Name(),"arg")==0 && functionnode->Attribute("nr") != NULL) { else if (strcmp(functionnode->Name(),"arg")==0 && functionnode->Attribute("nr") != NULL) {
const int nr = atoi(functionnode->Attribute("nr")); const int nr = atoi(functionnode->Attribute("nr"));
bool notnull = false;
const char *nullpointer = functionnode->Attribute("nullpointer"); bool notuninit = false;
const char *uninitdata = functionnode->Attribute("uninitdata"); for (const tinyxml2::XMLElement *argnode = functionnode->FirstChildElement(); argnode; argnode = argnode->NextSiblingElement()) {
const char *uninitderefdata = functionnode->Attribute("uninitderefdata"); if (strcmp(argnode->Name(), "not-null") == 0)
notnull = true;
functionArgument[name][nr].nullpointer = (nullpointer != NULL); else if (strcmp(argnode->Name(), "not-uninit") == 0)
functionArgument[name][nr].uninitdata = (uninitdata != NULL); notuninit = true;
functionArgument[name][nr].uninitderefdata = (uninitderefdata != NULL); else
return false;
}
functionArgument[name][nr].notnull = notnull;
functionArgument[name][nr].notuninit = notuninit;
} else } else
return false; return false;
} }

View File

@ -72,9 +72,8 @@ public:
} }
struct Argument { struct Argument {
bool nullpointer; bool notnull;
bool uninitdata; bool notuninit;
bool uninitderefdata;
}; };
// function name, argument nr => argument data // function name, argument nr => argument data
@ -82,12 +81,12 @@ public:
bool isnullargbad(const std::string &functionName, int argnr) const { bool isnullargbad(const std::string &functionName, int argnr) const {
const Argument *arg = getarg(functionName,argnr); const Argument *arg = getarg(functionName,argnr);
return arg && arg->nullpointer; return arg && arg->notnull;
} }
bool isuninitargbad(const std::string &functionName, int argnr) const { bool isuninitargbad(const std::string &functionName, int argnr) const {
const Argument *arg = getarg(functionName,argnr); const Argument *arg = getarg(functionName,argnr);
return arg && arg->uninitdata; return arg && arg->notuninit;
} }
std::set<std::string> returnuninitdata; std::set<std::string> returnuninitdata;

View File

@ -706,12 +706,13 @@ Checking test.c...
<para><literal>Cppcheck</literal> has internal knowledge about how <para><literal>Cppcheck</literal> has internal knowledge about how
standard C/C++ functions work. There is no internal knowledge about how standard C/C++ functions work. There is no internal knowledge about how
various libraries and environments work. <literal>Cppcheck</literal> can all libraries and environments work, and there can't be.
however be told how libraries and environments work by using configuration <literal>Cppcheck</literal> can be told how libraries and environments
files.</para> work by using configuration files.</para>
<para>The idea is that users will be able to download configuration files <para>The idea is that users will be able to download library
for all popular libraries and environments here:</para> configuration files for all popular libraries and environments
here:</para>
<para><uri>http://cppcheck.sourceforge.net/archive</uri></para> <para><uri>http://cppcheck.sourceforge.net/archive</uri></para>
@ -733,9 +734,10 @@ Checking test.c...
<section> <section>
<title>&lt;alloc&gt; and &lt;dealloc&gt;</title> <title>&lt;alloc&gt; and &lt;dealloc&gt;</title>
<para>Allocation and deallocation is defined within <para>Allocation and deallocation is defined <literal>using
<literal>&lt;memory&gt;</literal> or <literal>&lt;resource&gt; using &lt;alloc&gt; and &lt;dealloc&gt;. These are used inside inside
&lt;alloc&gt; and &lt;dealloc&gt;.</literal></para> <literal>&lt;memory&gt;</literal> or
<literal>&lt;resource&gt;.</literal></literal></para>
<para>Here is example code:</para> <para>Here is example code:</para>
@ -765,33 +767,23 @@ Checking test.c...</programlisting>
&lt;/memory&gt; &lt;/memory&gt;
&lt;/def&gt;</programlisting> &lt;/def&gt;</programlisting>
<para>That tells Cppcheck that <literal>alloc_something</literal>
allocates memory and that the matching deallocation function is
<literal>free_something</literal>.</para>
<para>Output from <literal>Cppcheck</literal>:</para> <para>Output from <literal>Cppcheck</literal>:</para>
<programlisting># cppcheck --library=something.cfg test.c <programlisting># cppcheck --library=something.cfg test.c
Checking test.c... Checking test.c...
[test.c:10]: (error) Memory leak: p</programlisting> [test.c:10]: (error) Memory leak: p</programlisting>
<para>Some allocation functions initialize the allocated data. Others
don't. Here is a short code example:</para>
<programlisting>void f()
{
char *p = alloc_something();
char c = *p;
free_something();
}</programlisting>
<para>If alloc_something() initializes the memory that is allocated then
that code is OK. Otherwise that code is bad. To configure that </para>
<para/>
</section> </section>
<section> <section>
<title>&lt;ignore&gt; and &lt;use&gt;</title> <title>&lt;ignore&gt; and &lt;use&gt;</title>
<para>The &lt;ignore&gt; and &lt;use&gt; tells Cppcheck how functions <para>The <literal>&lt;ignore&gt;</literal> and
uses allocated memory. Example code:</para> <literal>&lt;use&gt;</literal> tells Cppcheck how functions uses
allocated memory. Example code:</para>
<programlisting>void f() <programlisting>void f()
{ {
@ -840,7 +832,7 @@ Checking test.c...</programlisting>
</section> </section>
<section> <section>
<title>&lt;alloc init="false"&gt;</title> <title>allocate but not initialize</title>
<para>Some allocation function initialize the data, others don't. Here <para>Some allocation function initialize the data, others don't. Here
is a example code:</para> is a example code:</para>
@ -852,6 +844,11 @@ Checking test.c...</programlisting>
free_something(); free_something();
}</programlisting> }</programlisting>
<para>No error is reported:</para>
<programlisting># cppcheck --library=something.cfg test.c
Checking test.c...</programlisting>
<para>Here is a configuration that tells cppcheck that alloc_something <para>Here is a configuration that tells cppcheck that alloc_something
doesn't initialize the data:</para> doesn't initialize the data:</para>
@ -865,11 +862,79 @@ Checking test.c...</programlisting>
<para>Now you will get this error message:</para> <para>Now you will get this error message:</para>
<programlisting>daniel@dator:~/cppcheck$ ./cppcheck --library=something.cfg test.c <programlisting># cppcheck --library=something.cfg test.c
Checking test.c... Checking test.c...
[test.c:4]: (error) Memory is allocated but not initialized: p</programlisting> [test.c:4]: (error) Memory is allocated but not initialized: p</programlisting>
</section> </section>
<section>
<title>function arguments: null pointers</title>
<para>You can define if a function parameter can be NULL or if it must
be non-NULL.</para>
<para>Example code:</para>
<programlisting>void do_something(char *p);
void f()
{
do_something(NULL);
}</programlisting>
<para>Normally no error is reported for that code.</para>
<para>But if the do_something() parameter should be non-NULL you can use
this configuration:</para>
<programlisting>&lt;?xml version="1.0"?&gt;
&lt;def&gt;
&lt;function name="do_something"&gt;
&lt;arg nr="1"&gt;
&lt;not-null/&gt;
&lt;/arg&gt;
&lt;/function&gt;
&lt;/def&gt;</programlisting>
<para>Now the output from cppcheck is:</para>
<programlisting># cppcheck --library=something.cfg test1.c
Checking test1.c...
[test1.c:5]: (error) Null pointer dereference</programlisting>
</section>
<section>
<title>Function arguments: uninitialized data</title>
<para>Here is example code:</para>
<programlisting>void do_something(char *p);
void f()
{
char str[10];
do_something(str);
}</programlisting>
<para>Normally <literal>Cppcheck</literal> doesn't report any error
message for that. However if the parameter must be initialized there is
a problem. Here is a configuration that says that the parameter must be
initialized:</para>
<para><programlisting>&lt;?xml version="1.0"?&gt;
&lt;def&gt;
&lt;function name="do_something"&gt;
&lt;arg nr="1"&gt;
&lt;not-uninit/&gt;
&lt;/arg&gt;
&lt;/function&gt;
&lt;/def&gt;</programlisting>Now the cppcheck output is:</para>
<programlisting># cppcheck --library=something.cfg test1.c
Checking test1.c...
[test1.c:6]: (error) Uninitialized variable: str</programlisting>
</section>
<section> <section>
<title>no return</title> <title>no return</title>