Skip to content

Commit 2a88444

Browse files
committed
Library: document not-null and not-uninit argument configuration
1 parent 24dfc05 commit 2a88444

3 files changed

Lines changed: 124 additions & 56 deletions

File tree

lib/library.cpp

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -91,14 +91,18 @@ bool Library::load(const char path[])
9191
_noreturn[name] = (strcmp(functionnode->GetText(), "true") == 0);
9292
else if (strcmp(functionnode->Name(),"arg")==0 && functionnode->Attribute("nr") != NULL) {
9393
const int nr = atoi(functionnode->Attribute("nr"));
94-
95-
const char *nullpointer = functionnode->Attribute("nullpointer");
96-
const char *uninitdata = functionnode->Attribute("uninitdata");
97-
const char *uninitderefdata = functionnode->Attribute("uninitderefdata");
98-
99-
functionArgument[name][nr].nullpointer = (nullpointer != NULL);
100-
functionArgument[name][nr].uninitdata = (uninitdata != NULL);
101-
functionArgument[name][nr].uninitderefdata = (uninitderefdata != NULL);
94+
bool notnull = false;
95+
bool notuninit = false;
96+
for (const tinyxml2::XMLElement *argnode = functionnode->FirstChildElement(); argnode; argnode = argnode->NextSiblingElement()) {
97+
if (strcmp(argnode->Name(), "not-null") == 0)
98+
notnull = true;
99+
else if (strcmp(argnode->Name(), "not-uninit") == 0)
100+
notuninit = true;
101+
else
102+
return false;
103+
}
104+
functionArgument[name][nr].notnull = notnull;
105+
functionArgument[name][nr].notuninit = notuninit;
102106
} else
103107
return false;
104108
}

lib/library.h

Lines changed: 20 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -72,23 +72,22 @@ class CPPCHECKLIB Library {
7272
}
7373

7474
struct Argument {
75-
bool nullpointer;
76-
bool uninitdata;
77-
bool uninitderefdata;
75+
bool notnull;
76+
bool notuninit;
7877
};
7978

8079
// function name, argument nr => argument data
8180
std::map<std::string, std::map<int, Argument> > functionArgument;
8281

83-
bool isnullargbad(const std::string &functionName, int argnr) const {
84-
const Argument *arg = getarg(functionName,argnr);
85-
return arg && arg->nullpointer;
86-
}
82+
bool isnullargbad(const std::string &functionName, int argnr) const {
83+
const Argument *arg = getarg(functionName,argnr);
84+
return arg && arg->notnull;
85+
}
8786

88-
bool isuninitargbad(const std::string &functionName, int argnr) const {
89-
const Argument *arg = getarg(functionName,argnr);
90-
return arg && arg->uninitdata;
91-
}
87+
bool isuninitargbad(const std::string &functionName, int argnr) const {
88+
const Argument *arg = getarg(functionName,argnr);
89+
return arg && arg->notuninit;
90+
}
9291

9392
std::set<std::string> returnuninitdata;
9493

@@ -98,16 +97,16 @@ class CPPCHECKLIB Library {
9897
std::map<std::string, int> _dealloc; // deallocation functions
9998
std::map<std::string, bool> _noreturn; // is function noreturn?
10099

101-
const Argument * getarg(const std::string &functionName, int argnr) const {
102-
std::map<std::string, std::map<int, Argument> >::const_iterator it1;
103-
it1 = functionArgument.find(functionName);
104-
if (it1 != functionArgument.end()) {
105-
const std::map<int,Argument>::const_iterator it2 = it1->second.find(argnr);
106-
if (it2 != it1->second.end())
107-
return &it2->second;
108-
}
109-
return NULL;
110-
}
100+
const Argument * getarg(const std::string &functionName, int argnr) const {
101+
std::map<std::string, std::map<int, Argument> >::const_iterator it1;
102+
it1 = functionArgument.find(functionName);
103+
if (it1 != functionArgument.end()) {
104+
const std::map<int,Argument>::const_iterator it2 = it1->second.find(argnr);
105+
if (it2 != it1->second.end())
106+
return &it2->second;
107+
}
108+
return NULL;
109+
}
111110

112111
int getid(const std::map<std::string,int> &data, const std::string &name) const {
113112
const std::map<std::string,int>::const_iterator it = data.find(name);

man/manual.docbook

Lines changed: 92 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -706,12 +706,13 @@ Checking test.c...
706706

707707
<para><literal>Cppcheck</literal> has internal knowledge about how
708708
standard C/C++ functions work. There is no internal knowledge about how
709-
various libraries and environments work. <literal>Cppcheck</literal> can
710-
however be told how libraries and environments work by using configuration
711-
files.</para>
709+
all libraries and environments work, and there can't be.
710+
<literal>Cppcheck</literal> can be told how libraries and environments
711+
work by using configuration files.</para>
712712

713-
<para>The idea is that users will be able to download configuration files
714-
for all popular libraries and environments here:</para>
713+
<para>The idea is that users will be able to download library
714+
configuration files for all popular libraries and environments
715+
here:</para>
715716

716717
<para><uri>http://cppcheck.sourceforge.net/archive</uri></para>
717718

@@ -733,9 +734,10 @@ Checking test.c...
733734
<section>
734735
<title>&lt;alloc&gt; and &lt;dealloc&gt;</title>
735736

736-
<para>Allocation and deallocation is defined within
737-
<literal>&lt;memory&gt;</literal> or <literal>&lt;resource&gt; using
738-
&lt;alloc&gt; and &lt;dealloc&gt;.</literal></para>
737+
<para>Allocation and deallocation is defined <literal>using
738+
&lt;alloc&gt; and &lt;dealloc&gt;. These are used inside inside
739+
<literal>&lt;memory&gt;</literal> or
740+
<literal>&lt;resource&gt;.</literal></literal></para>
739741

740742
<para>Here is example code:</para>
741743

@@ -765,33 +767,23 @@ Checking test.c...</programlisting>
765767
&lt;/memory&gt;
766768
&lt;/def&gt;</programlisting>
767769

770+
<para>That tells Cppcheck that <literal>alloc_something</literal>
771+
allocates memory and that the matching deallocation function is
772+
<literal>free_something</literal>.</para>
773+
768774
<para>Output from <literal>Cppcheck</literal>:</para>
769775

770776
<programlisting># cppcheck --library=something.cfg test.c
771777
Checking test.c...
772778
[test.c:10]: (error) Memory leak: p</programlisting>
773-
774-
<para>Some allocation functions initialize the allocated data. Others
775-
don't. Here is a short code example:</para>
776-
777-
<programlisting>void f()
778-
{
779-
char *p = alloc_something();
780-
char c = *p;
781-
free_something();
782-
}</programlisting>
783-
784-
<para>If alloc_something() initializes the memory that is allocated then
785-
that code is OK. Otherwise that code is bad. To configure that </para>
786-
787-
<para/>
788779
</section>
789780

790781
<section>
791782
<title>&lt;ignore&gt; and &lt;use&gt;</title>
792783

793-
<para>The &lt;ignore&gt; and &lt;use&gt; tells Cppcheck how functions
794-
uses allocated memory. Example code:</para>
784+
<para>The <literal>&lt;ignore&gt;</literal> and
785+
<literal>&lt;use&gt;</literal> tells Cppcheck how functions uses
786+
allocated memory. Example code:</para>
795787

796788
<programlisting>void f()
797789
{
@@ -840,7 +832,7 @@ Checking test.c...</programlisting>
840832
</section>
841833

842834
<section>
843-
<title>&lt;alloc init="false"&gt;</title>
835+
<title>allocate but not initialize</title>
844836

845837
<para>Some allocation function initialize the data, others don't. Here
846838
is a example code:</para>
@@ -852,6 +844,11 @@ Checking test.c...</programlisting>
852844
free_something();
853845
}</programlisting>
854846

847+
<para>No error is reported:</para>
848+
849+
<programlisting># cppcheck --library=something.cfg test.c
850+
Checking test.c...</programlisting>
851+
855852
<para>Here is a configuration that tells cppcheck that alloc_something
856853
doesn't initialize the data:</para>
857854

@@ -865,11 +862,79 @@ Checking test.c...</programlisting>
865862

866863
<para>Now you will get this error message:</para>
867864

868-
<programlisting>daniel@dator:~/cppcheck$ ./cppcheck --library=something.cfg test.c
865+
<programlisting># cppcheck --library=something.cfg test.c
869866
Checking test.c...
870867
[test.c:4]: (error) Memory is allocated but not initialized: p</programlisting>
871868
</section>
872869

870+
<section>
871+
<title>function arguments: null pointers</title>
872+
873+
<para>You can define if a function parameter can be NULL or if it must
874+
be non-NULL.</para>
875+
876+
<para>Example code:</para>
877+
878+
<programlisting>void do_something(char *p);
879+
880+
void f()
881+
{
882+
do_something(NULL);
883+
}</programlisting>
884+
885+
<para>Normally no error is reported for that code.</para>
886+
887+
<para>But if the do_something() parameter should be non-NULL you can use
888+
this configuration:</para>
889+
890+
<programlisting>&lt;?xml version="1.0"?&gt;
891+
&lt;def&gt;
892+
&lt;function name="do_something"&gt;
893+
&lt;arg nr="1"&gt;
894+
&lt;not-null/&gt;
895+
&lt;/arg&gt;
896+
&lt;/function&gt;
897+
&lt;/def&gt;</programlisting>
898+
899+
<para>Now the output from cppcheck is:</para>
900+
901+
<programlisting># cppcheck --library=something.cfg test1.c
902+
Checking test1.c...
903+
[test1.c:5]: (error) Null pointer dereference</programlisting>
904+
</section>
905+
906+
<section>
907+
<title>Function arguments: uninitialized data</title>
908+
909+
<para>Here is example code:</para>
910+
911+
<programlisting>void do_something(char *p);
912+
913+
void f()
914+
{
915+
char str[10];
916+
do_something(str);
917+
}</programlisting>
918+
919+
<para>Normally <literal>Cppcheck</literal> doesn't report any error
920+
message for that. However if the parameter must be initialized there is
921+
a problem. Here is a configuration that says that the parameter must be
922+
initialized:</para>
923+
924+
<para><programlisting>&lt;?xml version="1.0"?&gt;
925+
&lt;def&gt;
926+
&lt;function name="do_something"&gt;
927+
&lt;arg nr="1"&gt;
928+
&lt;not-uninit/&gt;
929+
&lt;/arg&gt;
930+
&lt;/function&gt;
931+
&lt;/def&gt;</programlisting>Now the cppcheck output is:</para>
932+
933+
<programlisting># cppcheck --library=something.cfg test1.c
934+
Checking test1.c...
935+
[test1.c:6]: (error) Uninitialized variable: str</programlisting>
936+
</section>
937+
873938
<section>
874939
<title>no return</title>
875940

0 commit comments

Comments
 (0)