Start here

Home
About Klocwork
What's new
Fixed issues
Release notes
Installation

Reference

C/C++ checkers
Java checkers
C# checkers
MISRA C 2004 checkers
MISRA C++ 2008 checkers
MISRA C 2012 checkers
MISRA C 2012 checkers with Amendment 1
Commands
Metrics
Troubleshooting
Reference

Product components

C/C++ Integration build analysis
Java Integration build analysis
Desktop analysis
Refactoring
Klocwork Static Code Analysis
Klocwork Code Review
Structure101
Tuning
Custom checkers

Coding environments

Visual Studio
Eclipse for C/C++
Eclipse for Java
IntelliJ IDEA
Other

Administration

Project configuration
Build configuration
Administration
Analysis performance
Server performance
Security/permissions
Licensing
Klocwork Static Code Analysis Web API
Klocwork Code Review Web API

Community

View help online
Visit RogueWave.com
Klocwork Support
Rogue Wave Videos

Legal

Legal information

Tutorial 3 - Creating a C/C++ KAST checker with custom functions

Tutorial 3 - Creating a C/C++ KAST checker with custom functions

This tutorial describes how to create a C/C++ KAST checker with custom functions. 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. It also assumes that you have read over or performed the previous tutorial: Tutorial 2 - Creating a C/C++ KAST checker with built-in functions.

Run kwcreatechecker with the --kast-library option

For the custom function example, run this command:

kwcreatechecker --language cxx --type kast --kast-library foo --code C.KAST.CUST.FUNC
Note: Multibyte characters are not supported in error IDs (checker names), and there's a 255-character limit.

Result

A directory called C.KAST.CUST.FUNC is created with the name you specified with --code. This directory contains:

  • the checker configuration files (checkers.xml and help.xml)
  • a test case sample (testcase.cc)
  • a build file (Makefile)
  • a plug-in source file (PluginSource.cpp)

Add the test case

To test our KAST expression (which includes a custom function), we'll add the following to the testcase.cc file in the C.KAST.CUST.FUNC directory:

int main() {

   int* x;

//Reporting ckastcustfunc  
   x = 0;  
   cin >> x;
 
   return 0;

}

Locate nodes of interest using Checker Studio

  1. Double-click the Checker Studio icon on your desktop or on the command line, run:
    kwstudio
    
  2. Paste your code snippet in the Source Code section of Checker Studio.
    Viewing KAST node names, example code and hierarchy information is how you get the building blocks for your KAST expression.
  3. In the Source Code pane, click x = 0;
    ExprStmtis highlighted in the Abstract Syntax Tree. ExprStmt has one child in the tree, BinaryExpr.
  4. Click the "=" sign.
    The BinaryExpr node is highlighted in the tree and its attributes are displayed in the Attributes pane.
    Image:test_case_cust_func.png

For more information on using Checker Studio, see Tutorial 1 - Creating a C/C++ KAST checker.

Draft the KAST expression

Using the nodes you identified in the Checker Studio, create a test file to draft your KAST expression. For our example, the KAST expression is:

// ExprStmt / Expr::BinaryExpr [ @Op = KTC_OPCODE_ASR ] [ getMostleftArg().isCin() ] [ Right.isPointer() | Right.isArray() ]

In this expression, there are two custom functions:

  • getMostleftArg
  • isCin

See also C/C++ KAST syntax reference.

Add your plug-in source to the PluginSource.cpp file

In this step we'll be adding your custom functions and their return types to the PluginSource.cpp file.

Each plug-in function must have an associated name, which it will be called by in the KAST checker.

Open the PluginSource.cpp file. For this example, it's located in the C.KAST.CUST.FUNC directory.

The default contents of the file are:
# include <XPath_plugins.h>
# include <ktcAPI.h> int my_int_func(ktc_tree_t node) {

...

} ktc_tree_t my_tree_func(ktc_tree_t node) {

...

} HOOKS_SET_START
XPath_register_int_hook("myInt", my_int_func);
XPath_register_tree_hook("myTree", my_tree_func);

HOOKS_SET_END

Plug-in functions

A plug-in function must have a single parameter of type 'ktc_tree_t' and return either an integer value (int hook) or a pointer of type 'ktc_tree_t' (tree hook).

If a function is supposed to be used as a boolean one, it should return zero for false and a non-zero value for true. When calling a custom function in a KAST checker, one can either specify a single argument of 'tree' type or specify no arguments at all. In the latter case the current node will be processed.

Note: You can delete the return type template you don't use or re-order them as desired.

Example: Function return type of "int"

Our KAST expression contains the custom functions isCin and getMostleftArg.

// ExprStmt / Expr::BinaryExpr [ @Op = KTC_OPCODE_ASR ] [ getMostleftArg().isCin() ] [ Right.isPointer() | Right.isArray() ]

The isCin custom function has a return type of integer (int), so for the integer value in the PluginSource.cpp file we'll use:

int is_cin_function(ktc_tree_t node) {    
   if (ktc_is_IdExpr(node)) {      
      char *name = (char *)ktc_getIdentifier(node);       
      if (name && ! strcmp(name, "cin"))            
         return 1;   
   }   
   return 0;
}

Example: Function return type of pointer 'ktc_tree_t'

Our KAST expression also contains the custom function getMostleftArg, which has a return type of ktc_tree_t, so we'll add the following to the ktc_tree_t template in the PluginSource.cpp:

ktc_tree_t get_mostleft_arg_function(ktc_tree_t node) {    
   int isBinary = ktc_is_BinaryExpr(node);    
   if (! isBinary)        
      return 0;    
   do {        
      node = ktc_proceed(node, cid_Left);    
   } while(ktc_is_BinaryExpr(node));    
   return node;
}

Register the custom function

All function registrations should be placed between HOOKS_SET_START and HOOKS_SET_END macros. We'll need to register both of the custom functions in our KAST expression.

Example: Registering isCin and getMostleftArg

HOOKS_SET_START
XPath_register_int_hook("isCin", is_cin_function);
XPath_register_tree_hook("getMostleftArg", get_mostleft_arg_function);

HOOKS_SET_END

Next, we'll update the checkers.xml file.

Update the checkers.xml file

Now it's time to add your KAST expression to the <pattern> tags in the checkers.xml file. This file should also contain an accurate title and message for your custom checker.

  1. Open the checkers.xml file in an editor of your choice. For our example, this file is located in C.KAST.CUST.FUNC/checkers.xml.

When the file was generated, its values were automatically populated with an error ID, severity, message, and title, as well as a sample KAST expression. For more information about the tags in this file, see checkers.xml: Checker configuration.

  1. Look for the <pattern> tag.
  2. Replace the sample KAST expression with the KAST expression:
    ExprStmt / Expr::BinaryExpr [ @Op = KTC_OPCODE_ASR ] [ getMostleftArg().isCin() ] [ Right.isPointer() | Right.isArray() ]
    
  3. You can also edit the <error> node's attributes, as required. For this tutorial, we'll change the title attribute to read "C_KAST_Custom_Function" and the message attribute to read "dangerous input stream usage".
  4. Save the file.

Create help for your checker

Add documentation for your custom checker in the help.xml file. This file is located in the directory that you specified with the --code option of kwcreatechecker.

At minimum, you must provide a description of the issue within the <description> tags.

For an example, see Tutorial 1 - Creating a C/C++ KAST checker.

Build the checker

Unix:

make install buildspec

Windows:From the Visual Studio prompt, run:

nmake install buildspec
Tip: This is the equivalent of running the two commands make buildspec and make install (or for Windows, nmake buildspec and nmake install).

This generates:

  • a file called C.KAST.CUST.FUNC.zip
  • a build specification file that allows you to test your compiled checker

Test the checker

  1. Deploy the custom checker to your desktop by extracting the zip file into the <username>/.klocwork/plugins directory, creating the directory if it doesn't already exist.

    If the C/C++ checker is platform-specific, the extracted files may include a subdirectory, for example, <username>/.klocwork/plugins/ix86-pc-linux or <username>/.klocwork/plugins/ix86-pc-win32.

  2. Set up a local project in the directory where you developed the checker.
    kwcheck create -b <build_specification>
    
    where

    <build_specification> was created with make install buildspec or nmake install buildspec. By default, the build specification is written to kwinject.out in the current working directory.

  3. Run kwcheck to see if the issue is detected in your test case:
    kwcheck run
    

    Your checker will detect the issue from your test case.

    Tip: When you're running the kwcheck command repeatedly, use kwcheck with the -r option to make sure Klocwork doesn't skip files that have no apparent changes.
  4. If you are satisfied with the results, you can deploy your checker to the server.
  5. Uninstall the checker from your desktop by deleting the files that you extracted in Step 1 from the plugins directory .