Tutorial 2 - Creating a C/C++ KAST checker with built-in functions
Tutorial 2 - Creating a C/C++ KAST checker with built-in functionsIn this tutorial, we create a custom C/C++ KAST checker that searches code for assignment statements and finds instances of possible data loss through the assignment. To do this, we define a KAST expression that uses KAST built-in functions to specify the way the checker will work. This tutorial assumes that you've become familiar with Checker Studio and the basic process of creating a checker through Tutorial 1 - Creating a C/C++ KAST checker. Generate the checker stub filesUsing a checker name of CHECK.VAR.SIZE, run kwcreatechecker to generate the checker files: kwcreatechecker --language cxx --type kast --code CHECK.VAR.SIZE The stub files are placed in the CHECK.VAR.SIZE directory. Create the test caseTo start with, the test case for the checker should be the simplest code that includes the situations the checker will be looking for. You can extend the test cases and add more complexity as you develop the checker. Edit the automatically generated testcase.cc file and replace the template code with this sample code: int main(){ short x; int y = 4; x = y; short* xp = 3; int yy = 4; *xp = yy; short xx; int ya[7]; xx = &ya; return 0; } Create the KAST expressionIn this step, we begin finding the building blocks that will form our KAST expression, starting by studying the AST hierarchical tree that Checker Studio creates from our test case code.
Finding the KAST nodes of interestIn the AST tree, we can find the first elements of the expression: the KAST node names, hierarchy information, and operation attributes.
Defining KAST conditionsThe next few elements of the KAST expression provide the conditions we want to apply to the checker's search. Using KAST variables (terms prefixed by "$"), we can define the LHS and RHS of our search expressions:
In accordance with KAST syntax, the square brackets indicate conditions in the expression. We also want to specify that we're only looking for variables in this checker, and we can do that using our variables and the KAST built-in functions isConstant, isArray, and isPointer in the following conditions:
Adding these conditions to our KAST expression, we get:
The next step in creating the KAST expression is to add conditions that retrieve the variable size by using two new KAST variables and the built-in function, getTypeSize:
The last step is to add the conditions that compare the variables from each side of the statement to zero and to each other:
When we add these conditions, we have the completed KAST expression:
This expression can now be read as "Find all binary operations whose operation is assign, and in which the LHS type size is less than the RHS type size."
Test the expression in Checker StudioTo make sure the checker is working the way you want it to, type or copy the KAST expression into the Pattern pane in Checker Studio, and adjust your KAST expression and test case in Checker Studio as needed. For more examples of KAST expressions, see C/C++ KAST examples, and for more details of KAST syntax, see C/C++ KAST syntax reference. Edit the stub filesAt this stage, we edit the automatically generated checkers.xml and help.xml files with the information specific to our new checker.
Edit the checkers.xml fileEdit the checkers.xml file with the KAST expression: checkers version="1.3"> <categories> <category name="C and C++"> <category name="Custom checkers"> <error id="CHECK.VAR.SIZE"/> </category> </category> </categories> <checkergroup language="C/C++" api="tree_pattern"> <checker id="CHECK.VAR.SIZE"> <libraries> <library path=""/> </libraries> <error id="CHECK.VAR.SIZE" enabled="true" severity="3" title="Check variable size" message="Assignment with possible loss of data"> <pattern> //ExprStmt / Expr::BinaryExpr [@Op = KTC_OPCODE_ASSIGN] [$expr1:=Left] [$expr2:=Right] [not $expr2.isConstant()] [not $expr1.isPointer() | not $expr2.isArray()] [$size1:=$expr1.getTypesize()] [$size2:=$expr2.getTypesize()] [$size1 > 0] [$size2 > 0] [$size1 < $size2] </pattern> </error> </checker> </checkergroup> </checkers> In this file, we've replaced the original template data with
Edit the help.xml fileWhen you create and deploy a checker, the help.xml file populates Klocwork Documentation and is available through context-sensitive help in Klocwork Static Code Analysis. At minimum, you must provide a description of the issue. Build the checkerBuild the checker with make install buildspec in Linux, or nmake install buildspec in Windows (from the VS prompt). This process generates:
Test the checkerWhile you're still testing, it's best to deploy the checker to your desktop, rather than the server project.
What's next?Now that you've successfully created and run your checker, you could add more complex test cases to this checker, or create a new checker for your own project using some of the other Klocwork built-in functions. For a list of the built-in functions, launch Checker Studio, and go to Help > Help topics > KAST reference > C/C++ KAST built-in functions reference. Always make sure you consult the latest list of built-in functions to avoid recreating something that's already available. Then check out the links below for more checker activity. |