cppcheck/man/writing-rules.docbook

148 lines
4.7 KiB
Plaintext
Raw Normal View History

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE article PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN"
"http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd">
<article>
<articleinfo>
<title>Writing Cppcheck rules</title>
<author>
<firstname>Daniel</firstname>
<surname>Marjamäki</surname>
<affiliation>
<orgname>Cppcheck</orgname>
</affiliation>
</author>
<pubdate>2010</pubdate>
</articleinfo>
<section>
<title>Introduction</title>
2010-12-06 19:36:51 +01:00
<para>This is a short and simple guide that describes how rules are
written for Cppcheck.</para>
2010-12-06 19:36:51 +01:00
<para>The patterns are defined with regular expressions. It is required
that you know how regular expressions work.</para>
</section>
<section>
<title>Data representation of the source code</title>
<para>The data used by the rules are not the raw source code.
<literal>Cppcheck</literal> will read the source code and process it
before the rules are used.</para>
<para>Cppcheck is designed to find bugs and dangerous code. Stylistic
2010-12-06 19:36:51 +01:00
information (such as indentation, comments, etc) are filtered out at an
early state. You don't need to worry about such stylistic information when
you write rules.</para>
<para>Between each token in the code there is always a space. For instance
the raw code "1+f()" is processed into "1 + f ( )".</para>
2010-12-06 19:36:51 +01:00
<para>The code is simplified in many ways.</para>
</section>
2010-12-06 19:36:51 +01:00
<section>
<title>Creating a simple rule</title>
2010-12-06 19:36:51 +01:00
<para>When creating a rule there are two steps:</para>
2010-12-06 19:36:51 +01:00
<orderedlist>
<listitem>
2010-12-06 19:36:51 +01:00
<para>Create the regular expression</para>
</listitem>
<listitem>
2010-12-06 19:36:51 +01:00
<para>Create a XML based rule file</para>
</listitem>
2010-12-06 19:36:51 +01:00
</orderedlist>
<section>
2010-12-06 19:36:51 +01:00
<title>Step 1 - Creating the regular expression</title>
2010-12-06 19:36:51 +01:00
<para>Cppcheck uses the <literal>PCRE</literal> library to handle
regular expressions. <literal>PCRE</literal> stands for "Perl Compatible
Regular Expressions". The homepage for <literal>PCRE</literal> is
<literal>http://www.pcre.org</literal>.</para>
<para>Let's create a regular expression that checks for code such
as:</para>
<programlisting>if (p)
free(p);</programlisting>
2010-12-06 19:36:51 +01:00
<para>For such code the condition is often redundant (on most
implementations it is valid to free a NULL pointer).</para>
2010-12-05 21:50:17 +01:00
<para>The regular expression must be written for the simplified code. To
see what the simplified code looks like you can create a source file
2010-12-06 19:36:51 +01:00
with the code:</para>
<programlisting>void f() {
if (p)
free(p);
}</programlisting>
2010-12-06 19:36:51 +01:00
<para>Save that code as <literal>dealloc.cpp</literal> and then use
2010-12-05 21:50:17 +01:00
<literal>cppcheck --rule=".+" dealloc.cpp</literal>:</para>
<programlisting>$ ./cppcheck --rule=".+" dealloc.cpp
Checking dealloc.cpp...
[dealloc.cpp:1]: (style) found ' void f ( ) { if ( p ) { free ( p ) ; } }'</programlisting>
2010-12-06 19:36:51 +01:00
<para>The regular expression <literal>.+</literal> matches everything
and the matching text is shown on the screen.</para>
2010-12-05 21:50:17 +01:00
<para>From that output we can see that the simplified code is:</para>
<programlisting> void f ( ) { if ( p ) { free ( p ) ; } }</programlisting>
2010-12-06 19:36:51 +01:00
<para>Now that we know how the simplified code looks. We can create a
regular expression that matches it properly:</para>
<programlisting>$ cppcheck --rule="if \( p \) { free \( p \) ; }" dealloc.cpp
Checking dealloc.cpp...
[dealloc.cpp:2]: (style) found 'if ( p ) { free ( p ) ; }'</programlisting>
</section>
<section>
2010-12-06 19:36:51 +01:00
<title>Step 2 - Create rule file</title>
2010-12-06 19:36:51 +01:00
<para>A rule file is a simple XML file that contains:</para>
<itemizedlist>
<listitem>
2010-12-05 21:50:17 +01:00
<para>a pattern to search for</para>
</listitem>
<listitem>
2010-12-05 21:50:17 +01:00
<para>an error message that is reported when pattern is found</para>
</listitem>
</itemizedlist>
<para>Here is a simple example:</para>
<programlisting>&lt;?xml version="1.0"?&gt;
&lt;rule version="1"&gt;
&lt;pattern&gt;if \( p \) { free \( p \) ; }&lt;/pattern&gt;
&lt;message&gt;
&lt;id&gt;redundantCondition&lt;/id&gt;
&lt;severity&gt;style&lt;/severity&gt;
&lt;summary&gt;Redundant condition. It is valid to free a NULL pointer.&lt;/summary&gt;
&lt;/message&gt;
&lt;/rule&gt;</programlisting>
<para>If you save that xml data in <literal>dealloc.rule</literal> you
can test this rule:</para>
<programlisting>$ cppcheck --rule-file=dealloc.rule dealloc.cpp
Checking dealloc.cpp...
[dealloc.cpp:2]: (style) Redundant condition. It is valid to free a NULL pointer.</programlisting>
</section>
</section>
</article>