Tutorial 3 - Creating a C/C++ KAST checker with custom functions
Tutorial 3 - Creating a C/C++ KAST checker with custom functionsThis 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 optionFor 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:
Add the test caseTo 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
For more information on using Checker Studio, see Tutorial 1 - Creating a C/C++ KAST checker. Draft the KAST expressionUsing 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:
See also C/C++ KAST syntax reference. Add your plug-in source to the PluginSource.cpp fileIn 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 fileNow 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.
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.
Create help for your checkerAdd 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 checkerUnix: 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:
Test the checker
|