HP Code Advisor C.02.
© Copyright 2012 Hewlett-Packard Development Company L.P. Confidential computer software. Valid license from HP required for possession, use or copying. Consistent with FAR 12.211 and 12.212, Commercial Computer Software, Computer Software Documentation, and Technical Data for Commercial Items are licensed to the U.S. Government under vendor's standard commercial license. The information contained herein is subject to change without notice.
Contents About this document......................................................................................5 Intended audience....................................................................................................................5 Document conventions and symbols............................................................................................5 Related information...................................................................................................................
6.6 Generating HTML report....................................................................................................29 6.7 Generating XML report......................................................................................................30 6.8 Printing diagnostics with specific diagnostic numbers.............................................................30 6.9 Generating reports based on severity..................................................................................31 6.
About this document This document discusses the invocation and usage of HP Code Advisor. Intended audience This document is intended for programmers who want to detect the potential errors or warnings in C, C++ applications by using HP Code Advisor. Document conventions and symbols Table 1 (page 5) lists the conventions and symbols used in this white paper.
HP encourages your comments HP encourages your comments concerning this document. We are committed to providing documentation that meets your needs. Send any errors found, suggestions for improvement, or compliments to: cadvise-help@lists.hp.
1 Introduction HP Code Advisor (cadvise) is a static analysis tool for C and C++ programs. Cadvise reports various programming errors in the source code. This tool enables programmers to identify potential coding errors, porting issues, and security vulnerabilities. Cadvise leverages the advanced analysis capabilities of HP C and HP aC++ compilers available on the HP Integrity systems. This chapter addresses the following topics: • “Cadvise user interface” (page 7) • “Features” (page 7) 1.
• “Detection of pre-defined or user-defined coding guideline violation” (page 8) • “Easy to integrate and use” (page 8) 1.2.1 Advanced static code analysis Cadvise is a powerful static code analysis tool that automatically diagnoses various issues in a source program. It improves developer productivity by finding defects at code development time, and leads to more robust and secure software because of fewer escaped defects. Cadvise leverages advanced cross-file analysis technology from HP compilers.
$ cadvise -pdb ./mypdb +wlint aCC hello.cpp 1.2.7 Supported compilers Cadvise is shipped and supported with the HP aC++ and HP C compilers on the latest HP Integrity and PA-RISC HP-UX platforms. Cadvise can also be used with GNU gcc and g++ compilers, however it does not support all gcc/g++ built-ins and extensions. Cadvise will emit a parsing error if it comes across an unsupported built-in or extension. If you need support for a specific built-in or extension please send an email to cadvise-help@lists.
2 Using Cadvise This chapter addresses the following topics: • “Getting started” (page 10) • “Steps in using cadvise” (page 10) • “Invoking Cadvise” (page 11) • “Using Cadvise as a wrapper around Compiler or Linker” (page 12) • “Integrating Cadvise with the makefiles and build process” (page 12) • “Enabling different categories of diagnostic messages” (page 13) • “Generating code complexity metrics” (page 13) • “Detecting violation of pre-defined or user-defined coding guidelines” (page 17)
Figure 2 Steps in Using Cadvise To use cadvise, you perform the following steps: 1. Build the application with the set of compiler or linker options. Ensure that the application builds successfully. 2. Run cadvise with desired options and create the PDB. 3. Use the reporting utility for generated reports from the PDB in various formats. 4. Make suggested changes based on generated reports. The suggested changes are for defect prevention, memory leaks, secutity issues, coding guideline violation, and so on.
The cadvise command has the following modes of operation: • Analysis mode Used to analyze and create the Program Database (PDB). To invoke cadvise in this mode, enter the cadvise command in the following format: cadvise [cadvise-options] compile-cmd [compile-options] • Report mode Used to create reports.
Example 2 Sample wrapper script $ cat cadvise_cc #!/bin/sh # # wrapper script to invoke cadvise # exec /opt/cadvise/bin/cadvise -pdb mypdb +wlint /opt/ansic/bin/cc "$@" Now cadvise_cc can be used instead of cc in the build line to invoke cadvise analysis in addition to the compilation process. NOTE: You need not create separate dependency rules for cadvise in the makefiles. Cadvise must be invoked only when the existing dependency rules in the makefile lead to a compile.
Example 3 Generating code complexity metrics To store the code complexity metrics in the PDB with Indirect Call Targets, use the following command. $cadvise +metrics=ict -pdb test.pdb aCC -c example.c To get the metrics in the my.metrics file, use the following command. $cadvise +metrics :out=my.metrics aCC -c example.c To store the metrics in the my.metrics file without Indirect Call Targets, use the following command. $cadvise +metrics :out=pdb -pdb test.pdb aCC -c example.
◦ Number of blank lines ◦ Number of lines of code ◦ Number of mixed lines ◦ Number of macros used ◦ Number of local variables defined ◦ Number of static variables defined ◦ Number of if statements ◦ Number of return statements ◦ Number of loop nests ◦ Nesting level of each loop nest ◦ Number of indirect calls ◦ Number of direct calls ◦ Targets of direct calls ◦ Cyclomatic complexity ◦ Cyclomatic complexity without switch ◦ Cyclomatic complexity without exception handling ◦ C
Example 4 Code complexity metrics $ cat /tmp/example.c #include #include
Lines of Code: 13 Mixed Lines: 1 No. of Macros Used: 3 No. of Locals: 3 No. of Statics: 0 No. of Ifs: 0 No. of Returns: 1 No. of Loops: 1 Loop Nesting Levels: 3 No. of Indirect Calls: 0 No. of Direct Calls: 1 Functions called: print_output() Cyclomatic Complexity: 4 Cyclomatic complexity without switches: 4 Cyclomatic complexity without eh: 4 Cyclomatic complexity without switches and eh: 4 No. of Thread Local Variables: 0 No. of Mutexes: 0 No. of Lock Calls: 0 No.
Table 2 Source structure in the rules library include/ • HPCodeGuideConstructs.h Contains the APIs required for (re)writing the rules to enforce coding guidelines. • HPCodeGuideDiagnosticTags.h Contains the various diagnostic tags that you can use to emit the diagnostics from the rules library. lib/ • libcodeguide.a This is provided to fill in the implementation stubs for recompilation of the rules' library, and must be linked in while compiling the rules' library. • librules.
3 Using the Program Database (PDB) The PDB is a repository of errors, warnings, diagnostic messages, and metrics generated while analyzing the application. The HP Code Advisor uses the PDB also to store the information required for the analysis. If you want to perform cross-file analysis of the application, you need to use a PDB.
3.1 PDB options table The following options help you manage the PDB: “-pdb location” (page 20) Enables you to specify the location (path) of the PDB. “-pdb_destroy” (page 20) Removes the PDB specified with the –pdb option. “-pdb_no_locking” (page 20) Allows you to not to use locks in PDB operations. “-remove” (page 20) Removes information related to the specified object files from the PDB. “-snapshot location” (page 21) Creates a snapshot of the PDB at the specified location (path).
Following is the syntax for removing information from the PDB: $cadvise -pdb -remove:objs/ Following is an example to remove object file information from the PDB: Example 8 Removing object file information from the PDB $cadvise -pdb testpdb /opt/aCC/bin/aCC foo.c -c -o objs/foo.o $cadvise -pdb testpdb -remove:objs/foo.o NOTE: For information on how cadvise searches for object files, see Example 15 “Specifying the location of object files”. 3.
4 Using cross-file analysis Cadvise provides different operating modes for performing cross-file analysis of the application. The cross-file analysis can be performed along with the regular build of the application, or separated from the regular build. You can also initiate it either on all the files or only on a selected group of files or modules. It can also be disabled completely. The default and recommended mode is to enable cross-file analysis at link time.
Example 11 Using cross-file analysis automatically during linking -crossfile=auto The default cross-file option is -crossfile=auto. The cross-file analysis occurs automatically when you invoke cadvise during linking. $cadvise –pdb testpdb cc a.c b.c –c $cadvise –pdb testpdb cc a.o b.o –o test.
NOTE: The combined use of the –crossfile=defer and –crossfile=[pdb|module|list|listfile] options are useful in the following situations: • If you want to perform cross-file analysis on a set of object files that is bigger than the set of object files linked during the application build process, for example, if the application build creates multiple shared libraries, the default automatic cross-file analysis is done only across the files specified for each shared-library link command.
5 Configuring diagnostic messages You may want to limit the cadvise diagnostic messages depending on the need, such as the following cases: • Generate all possible messages to ensure that you get the maximum information about potential problems detected by cadvise. • Reduce the number of messages so that you are not overwhelmed by the sheer magnitude of the warnings. • Eliminate or reduce the number of benign or misleading messages.
Example 17 Enabling warnings selectively $cadvise +wall -pdb testpdb +Ww600 cc -c foo.c 5.4 Interpreting selective warnings as errors The +Wearg1[,arg2,..,argn] option selectively interprets specified warning messages as errors. arg1 through argn must be valid warning message numbers. This option allows you to enforce a policy to disallow specific warnings by forcing an error at compile time. +Wearg1[,arg2,..,argn] Following is the syntax for selectively enabling warnings.
6 Generating reports Cadvise either stores the diagnostic messages in the PDB or outputs them into the stderr. To analyze these diagnostic messages, you can generate a report using the cadvise report command. Cadvise report provides multiple options for filtering the diagnostic messages stored in the log files. These reports can also be viewed and saved as HTML files. Using these options, you can view a selected set of diagnostic messages.
“-basepdb ” (page 34) Enables you to compare PDB with the PDB specified using -pdb option. “+opts ” (page 38) Reads the report options from the specified file. 6.2 Generating summary reports The -summary option prints the summary information about all messages in the log file in the order of security level. This is the default. The following example shows the summary report.
Example 23 Generating function summary report $cadvise report -func_summary -pdb testpdb =========================== FUNCTION SUMMARY REPORT ============================ Count Duplicate Funcname -------------------------------------------------------------------------1 0 /user/rajen/cadvise/Doc_release_tests/example.C::foo 1 0 /user/rajen/cadvise/Doc_release_tests/example.C::main ___________________________________________________________ 6.
The HTML report has the following options when it is viewed from the web browser: • Tabbed Interface: Summary report and warnings for each severity level are placed in different tabs, which is named according to severity level. • Hot Keys to Navigate Tabs: ◦ Ctrl + Alt + 0 : Shows summary tab. ◦ Ctrl + Alt + (1-9): Shows severity tab corresponding to pressed numeric key. • Sorting and Text filtering options are available in the severity tabs.
Example 26 Printing report for a specific diagnostic number(s) $ cadvise report -pdb testpdb -diag 2549 Report generated using "HP Code Advisor C.XX.XX [Release Time]" on at Report command line: " cadvise report -pdb testpdb -diag 2549" "a.c", line 14: warning #2549-D: variable "struct_obj" is used before its value is set LocalVar = struct_obj.a ; ^ "b.c", line 6: warning #2549-D: variable "b" is used before its value is set c = b; ^ "b.
Example 28 Suppressing diagnostics for specific file(s) $ cadvise report -pdb test.pdb -summary -exclude "inflate.c" Report generated using "HP Code Advisor C.XX.XX [Release Time]" on at Report command line: " cadvise report -pdb test.pdb -summary -exclude "inflate.c " =============================== SUMMARY REPORT ================================= Unique warnings: 257 Duplicate warnings: 0 Sev.
Example 30 Reporting program complexity metrics $ cadvise report -pdb gzip.pdb +metrics -include "inflate.c" ================================================================================ Begin program complexity data for /vws/cal-bear_2/zhang/gzip-1.2.4a/inflate.
Example 31 Generating report for a module $ cadvise report -pdb test.pdb -summary -module test1 =============================== SUMMARY REPORT ================================= Report generated using "HP Code Advisor C.XX.XX [Release Time]" on at Report command line: " cadvise report -pdb test.pdb -summary -module test1" Unique warnings:29 Duplicate warnings: 0 Sev.
6.16.1 Generating summary diff report Using the PDB comparison option along with the -summary option displays the difference between the summary reports of 2 PDBs. The following example shows the usage of -basepdb summary difference report: Example 34 Generating summary diff report without the header $ cadvise report -pdb test.pdb -basepdb test0.pdb -summary -noheader Sev.
Example 36 Generating diff report for any particular warning $ cadvise report -pdb tmp.pdb -basepdb tmp1.pdb -diag 2549 Report generated using "HP Code Advisor C.XX.XX [Release Date]" on at
Example 39 Generating detailed diff report in the warnings greater than or equal to any particular severity $ cadvise report -pdb tmp.pdb -basepdb tmp1.pdb -severity 1 Report generated using "HP Code Advisor C.XX.XX [Release Date]" on at
Example 40 Generating detailed diff report without using -approot option $ cadvise report -pdb new.pdb -basepdb old.pdb -all Report generated using "HP Code Advisor C.XX.XX [Release Date]" on at
Example 42 Report options file $ cat my_opts -diag 3348 $ cadvise report -pdb test.pdb +opts my_opts "test.c", line 1320: remark #3348-D: declaration hides variable "ifd" (declared at line 237) int ifd; /* input file descriptor */ ^ "test.c", line 1321: remark #3348-D: declaration hides variable "method" (declared at line 216) int method; /* compression method */ ^ "unlzw.c", line 337: remark #3348-D: declaration hides variable "i" (declared at line 247) REG1 int i; ^ "unzip.
Example 44 Generating a consolidated cadvise report from multiple PDBs $ cadvise report -pdb 1.pdb:2.pdb:3.pdb:4.pdb -all Report generated using "HP Code Advisor C.XX.XX [Release Date]" on at
Example 45 Reporting options interoperability $ cadvise report -pdb test.pdb -diag 2549 -exclude b.c Report generated using "HP Code Advisor C.XX.XX [Release Time]" on at Report command line: " cadvise report -pdb test.pdb -diag 2549 -exclude b.c" "a.c", line 14: warning #2549-D: variable "struct_obj" is used before its value is set LocalVar = struct_obj.a ; $ cadvise report -pdb test.pdb -include "a.c:b.c" Report generated using "HP Code Advisor C.XX.
7 Miscellaneous driver options You can also use the following cadvise options to manage the static analysis and the compilation processes: -compiler Specifies the compiler or linker command used in the command line. [aCC|cc|c89|c99|gcc|g++|ld] -help|-h|-H Displays the complete list of cadvise options with a brief description for each option. -[no]abort Determines whether to return a non-zero exit value for cadvise errors. The default is -noabort.
• -nobuild The cross-file analysis is disabled when you use the -nobuild option. You can use the -crossfile=defer option to enable cross-file analysis. The default is -build. The syntax for determining the invocation of the compile or link command after the cadvise static analysis is as mentioned below: $ cadvise -nobuild -w The following example shows the usage of -[no]build option. Example 50 Using -nobuild option $ cadvise -nobuild /opt/ansic/bin/cc -w t1.
Example 53 Using +opts option $cat warnings_config # warnings_config # change warning about use of undefined variable to an error +We2549 # enable warning about redeclaration of variable +Ww3348 # disable warning: statement is unreachable +W2111 $ cadvise +opts warnings_config +wlint cc -c uninit.c at the command line generates the following messages: "uninit.c", line 6: warning #3348-D: declaration hides variable "i" (declared at line 3) int i; ^ "uninit.
8 Categories of diagnostics with examples Cadvise detects a wide range of coding errors and potential problems such as memory leaks, used after free, double free, array/buffer out of bounds access, illegal pointer access, un-initialized variables, unused variables, format string checks, suspicious conversion and casts, out of range operations, and C++ coding style warnings. 8.
- Type conversion may truncate value Unsigned value cannot be less than zero Missing return statement at end of non-void function Nested comment is not allowed Signed bitfield of length 1 Potential memory leak detection Potential null pointer dereference detection Out of bound access Out of scope access Use of pointer after free Allocator/deallocator mismatch The following are some detailed examples of warnings generated by +wlint checks: 46 Categories of diagnostics with examples
Example 54 Null pointer dereference check A null pointer may result from null assignment or from a call to the APIs that may return a null value. If a pointer that is not guarded when it is dereferenced, unexpected runtime results may occur. For example, see the following program fragment: #include
Example 55 Potential memory leak check Cadvise detects potential memory leaks in the program where the memory allocated in the program is not freed. If a dynamically allocated memory becomes unreachable from any other pointers, then the memory is leaked after that point in the program, assuming that there is no garbage collection in the allocator. Cadvise flags such situations as shown in the following example code fragment: #include #include #include
Example 56 Out of bound access When an array is referenced and the index is greater than the declared (or dynamically allocated) size, unexpected runtime behavior may occur. In such cases, cadvise flags it as potential array out of bound access violation.
Example 58 Use of pointer after free When there is reference to a memory through a pointer that has been previously freed, cadvise detects such potential issues as Use After Free cases. For example, see the following code: void use_after_free () { char *p = malloc (20); strcpy (p, "hello"); free (p); *p = 'c'; } In such cases, cadvise generates the following error: free.
Example 60 Signed bit field of length 1 Cadvise warns cases where signed bit field of length 1 is being used and then assigned with a value, which is excessive of its size. For example, see the tags in the following code: $ cat bitfield.c struct { int bit:1; } s; void test() { s.bit = 1; } In such cases, cadvise generates the following warnings: "bitfield.c", line 1: warning #2108-D: signed bit field of length 1 struct { int bit:1; } s; ^ "bitfield.
Example 62 Detecting endian dependent code fragments Consider the following code fragment. union Endian { char c[4]; int v; }; In such cases, cadvise generates the following warning: "endian1.c", line 2: warning #4289-D: endian porting: the definition of the union may be endian dependent union Endian { ^ The +wendian option can catch various potential endian dependent data structures and usage.
Example 63 Enabling compile time diagnostic messages for potential security vulnerabilities #include #include char* get_path() { return getenv("BLAHBLAH"); } int main() { char* path = get_path(); // line 11 FILE* my_pipe = popen(path, "r"); // line 13 printf ("%p\n", my_pipe); } In this case, cadvise generates the following error: "popen.
Example 64 Detecting multi-threaded programming issues #include #include int a; pthread_mutex_t Mutex; void perform_operation(pthread_mutex_t* mutex1, int increment, int* global) { if (increment > 10) { int status = pthread_mutex_lock(mutex1); } *global = *global + increment; int status = pthread_mutex_unlock(&Mutex); } int main(void) { int i; scanf("%d", &i); perform_operation(&Mutex, i, &a); printf("%d is value\n", a); } Running cadvise generates the following error: "1.
Example 65 Detecting potential performance improvement opportunities bash-2.05b$ cat /tmp/example.c struct X{ int i; int arr[100]; } x; int foo( struct X); int main() { foo (x); //line 16 } $ cadvise +wperfadvice aCC -c /example.c "/example.c", line 16: warning #4319-D: performance advice: passing a large (404 bytes) parameter by value is inefficient, consider passing by reference foo (x); ^ 8.
9 Fixing the warnings by source change The HP Code Advisor Diagnostics Reference Guide document enables you fix the warnings with a brief description for a partial list of diagnostics emitted by cadvise. In this document, there are four sections for each description as mentioned below: • The Cause section Discusses the possible reasons for the diagnostic to be emitted. • The Example section Provides relevant sample code segments that result in the specific diagnostic.
10 Incompatibilities on PA-RISC based systems On PA-RISC-based systems, a few non-standard source constructs may not be accepted by cadvise. In such cases, cadvise generates an error and continues processing the next source file. For more information, see the following page: aC++ standard conformance and compatibility changes. In such cases, the best way is to modify the source code so that the code is more standards compliant and is compilable on platforms based on both Integrity and PA-RISC.
Index Symbols G +metrics, 32 +opts , 38 +opts , 43 +w, 45 +w64bit, 51 +wall, 45 +Warg1[,arg2,...,argn], 25 +Wearg1[,arg2,..,argn], 26 +wendian, 51 +wlint, 45 +wlock, 53 +Wmacro:MACRONAME:d1,d2,d3,..dn, 26 +wperfadvice[=1|2|3|4], 54 +wsecurity[=1|2|3|4], 52 +Wwarg1[,arg2,..,argn], 25 -[no]abort, 42 -all, 29 -approot, 37 -basepdb , 34 -build, 43 -chseverity , 34 -compiler [aCC|cc|c89|c99|gcc|g++|ld], 42 -diag N1,N2,N3,...