248
Compass User Manual: A Tool for Source Code Checking (A ROSE Tool) Draft User Manual (Associated with ROSE Version 0.9.5a) ROSE Team Lawrence Livermore National Laboratory Livermore, CA 94550 925-423-2668 (office) 925-422-6278 (fax) [email protected] Project Web Page: http://www.rosecompiler.org UCRL Number for ROSE User Manual: UCRL-SM-210137-DRAFT UCRL Number for ROSE Tutorial: UCRL-SM-210032-DRAFT UCRL Number for ROSE Source Code: UCRL-CODE-155962 ROSE User Manual (pdf) ROSE Tutorial (pdf) ROSE HTML Reference (html only) July 8, 2013

Compass User Manual: A Tool for Source Code Checking (A ROSE

  • Upload
    others

  • View
    4

  • Download
    0

Embed Size (px)

Citation preview

Compass User Manual:

A Tool for Source Code Checking

(A ROSE Tool)

Draft User Manual

(Associated with ROSE Version 0.9.5a)

ROSE TeamLawrence Livermore National Laboratory

Livermore, CA 94550925-423-2668 (office) 925-422-6278 (fax)

[email protected] Web Page: http://www.rosecompiler.org

UCRL Number for ROSE User Manual: UCRL-SM-210137-DRAFTUCRL Number for ROSE Tutorial: UCRL-SM-210032-DRAFTUCRL Number for ROSE Source Code: UCRL-CODE-155962

ROSE User Manual (pdf)ROSE Tutorial (pdf)

ROSE HTML Reference (html only)

July 8, 2013

2

Contents

1 Introduction 51.1 Overview . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5

2 Design and Verification 72.1 Usage Model . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 72.2 Trust Model . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 82.3 Architecture . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 92.4 Design . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 102.5 Compass Verifier . . . . . . . . . . . . . . . . . . . . . . . . . . . 102.6 Future Work . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14

3 Using Compass 153.1 Installation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 153.2 Running Compass . . . . . . . . . . . . . . . . . . . . . . . . . . 163.3 Output from Compass . . . . . . . . . . . . . . . . . . . . . . . . 163.4 Including/Excluding Checkers in the Compass Build Process . . 233.5 Including/Excluding Checkers During Compass Execution . . . . 243.6 Including/Excluding Paths and Filenames with Compass . . . . . 263.7 Checking Security Properties of Checkers . . . . . . . . . . . . . 263.8 Testing Compass and its Checkers . . . . . . . . . . . . . . . . . 273.9 How To Write A New Checker . . . . . . . . . . . . . . . . . . . 283.10 Extending the Compass Infrastructure . . . . . . . . . . . . . . . 29

4 Using Compass GUI 334.1 Running Compass GUI on a Single File . . . . . . . . . . . . . . 334.2 Running Compass GUI on an Autotools Project . . . . . . . . . 34

5 Using Compass Verifier 37

6 Categories of Compass Checkers 396.1 Common Styles . . . . . . . . . . . . . . . . . . . . . . . . . . . . 396.2 C styles . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 406.3 C++ styles . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 406.4 Correctness . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 416.5 OpenMP . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 416.6 Security . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 426.7 Portability . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 426.8 Clarity . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 42

3

4 CONTENTS

6.9 Complexity . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 426.10 Consistency . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 436.11 Better choices . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 436.12 Dangerous choices . . . . . . . . . . . . . . . . . . . . . . . . . . 436.13 Performance/Effectiveness . . . . . . . . . . . . . . . . . . . . . . 446.14 Misc or Undocumented . . . . . . . . . . . . . . . . . . . . . . . . 44

7 List of Compass Checkers 457.1 Allocate And Free Memory In The Same Module At The Same

Level Of Abstraction . . . . . . . . . . . . . . . . . . . . . . . . . 467.2 Allowed Functions . . . . . . . . . . . . . . . . . . . . . . . . . . 497.3 Assignment Operator Check Self . . . . . . . . . . . . . . . . . . 517.4 Assignment Return Const This . . . . . . . . . . . . . . . . . . . 537.5 Avoid Using The Same Handler For Multiple Signals . . . . . . . 557.6 Bin Print Asm Functions . . . . . . . . . . . . . . . . . . . . . . 587.7 Bin Print Asm Instruction . . . . . . . . . . . . . . . . . . . . . . 597.8 Binary Buffer Overflow . . . . . . . . . . . . . . . . . . . . . . . . 607.9 Binary Interrupt Analysis . . . . . . . . . . . . . . . . . . . . . . 617.10 Boolean Is Has . . . . . . . . . . . . . . . . . . . . . . . . . . . . 627.11 [No Reference] Buffer Overflow Functions . . . . . . . . . . . . . 647.12 Secure Coding : EXP04-A. Do not perform byte-by-byte com-

parisons between structures . . . . . . . . . . . . . . . . . . . . . 667.13 Char Star For String . . . . . . . . . . . . . . . . . . . . . . . . . 687.14 Comma Operator . . . . . . . . . . . . . . . . . . . . . . . . . . . 707.15 [No Reference] Computational Functions . . . . . . . . . . . . . . 717.16 Const Cast . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 737.17 Secure Coding : STR05-A. Prefer making string literals const-

qualified . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 757.18 Constructor Destructor Calls Virtual Function . . . . . . . . . . 787.19 Control Variable Test Against Function . . . . . . . . . . . . . . 807.20 Copy Constructor Const Arg . . . . . . . . . . . . . . . . . . . . 827.21 Cpp Calls Setjmp Longjmp . . . . . . . . . . . . . . . . . . . . . 847.22 Cycle Detection . . . . . . . . . . . . . . . . . . . . . . . . . . . . 867.23 Paper: Cyclomatic Complexity . . . . . . . . . . . . . . . . . . . 877.24 Data Member Access . . . . . . . . . . . . . . . . . . . . . . . . . 887.25 Deep Nesting . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 907.26 Default Case . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 927.27 Default Constructor . . . . . . . . . . . . . . . . . . . . . . . . . 947.28 Discard Assignment . . . . . . . . . . . . . . . . . . . . . . . . . 967.29 Do Not Assign Pointer To Fixed Address . . . . . . . . . . . . . 987.30 Do Not Call Putenv With Auto Var . . . . . . . . . . . . . . . . 1007.31 Do Not Delete This . . . . . . . . . . . . . . . . . . . . . . . . . . 1037.32 Do Not Use C-style Casts . . . . . . . . . . . . . . . . . . . . . . 1057.33 Duffs Device . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1077.34 Dynamic Cast . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1097.35 Empty Instead Of Size . . . . . . . . . . . . . . . . . . . . . . . . 1117.36 Enum Declaration Namespace Class Scope . . . . . . . . . . . . . 1137.37 CERT-DCL04-A: Explicit Char Sign . . . . . . . . . . . . . . . . 1157.38 Explicit Copy . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 117

CONTENTS 5

7.39 Explicit Test For Non Boolean Value . . . . . . . . . . . . . . . . 1187.40 File Read Only Access . . . . . . . . . . . . . . . . . . . . . . . . 1207.41 Float For Loop Counter . . . . . . . . . . . . . . . . . . . . . . . 1227.42 Floating Point Exact Comparison . . . . . . . . . . . . . . . . . . 1247.43 Fopen Format Parameter . . . . . . . . . . . . . . . . . . . . . . 1267.44 For Loop Construction Control Stmt . . . . . . . . . . . . . . . . 1287.45 For Loop Cpp Index Variable Declaration . . . . . . . . . . . . . 1307.46 Forbidden Functions . . . . . . . . . . . . . . . . . . . . . . . . . 1327.47 Friend Declaration Modifier . . . . . . . . . . . . . . . . . . . . . 1357.48 Function Call Allocates Multiple Resources . . . . . . . . . . . . 1377.49 CERT-DCL31-C: Function Definition Prototype . . . . . . . . . 1397.50 Paper: Function Documentation . . . . . . . . . . . . . . . . . . 1417.51 Induction Variable Update . . . . . . . . . . . . . . . . . . . . . . 1427.52 Internal Data Sharing . . . . . . . . . . . . . . . . . . . . . . . . 1447.53 [No Reference] : Loc Per Function . . . . . . . . . . . . . . . . . 1467.54 Localized Variables . . . . . . . . . . . . . . . . . . . . . . . . . . 1487.55 Lower Range Limit . . . . . . . . . . . . . . . . . . . . . . . . . . 1507.56 Magic Number . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1527.57 Malloc Return Value Used In If Stmt . . . . . . . . . . . . . . . . 1547.58 Multiple Public Inheritance . . . . . . . . . . . . . . . . . . . . . 1567.59 Name All Parameters . . . . . . . . . . . . . . . . . . . . . . . . 1587.60 [No Reference] : New Delete . . . . . . . . . . . . . . . . . . . . . 1597.61 No Asm Stmts Ops . . . . . . . . . . . . . . . . . . . . . . . . . . 1617.62 No Exceptions . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1637.63 No Exit In Mpi Code . . . . . . . . . . . . . . . . . . . . . . . . . 1647.64 No Goto . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1667.65 No Overload Ampersand . . . . . . . . . . . . . . . . . . . . . . . 1687.66 CERT-MSC30-C: No Rand . . . . . . . . . . . . . . . . . . . . . 1707.67 No Second Term Side Effects . . . . . . . . . . . . . . . . . . . . 1727.68 Secure Coding : EXP06-A. Operands to the sizeof operator

should not contain side effects . . . . . . . . . . . . . . . . . . . . 1747.69 No Template Usage . . . . . . . . . . . . . . . . . . . . . . . . . . 1767.70 No Variadic Functions . . . . . . . . . . . . . . . . . . . . . . . . 1787.71 CERT-POS33-C: No Vfork . . . . . . . . . . . . . . . . . . . . . 1807.72 Non Associative Relational Operators . . . . . . . . . . . . . . . 1827.73 Non Standard Type Ref Args . . . . . . . . . . . . . . . . . . . . 1847.74 Non Standard Type Ref Returns . . . . . . . . . . . . . . . . . . 1867.75 Non Virtual Redefinition . . . . . . . . . . . . . . . . . . . . . . . 1887.76 Nonmember Function Interface Namespace . . . . . . . . . . . . 1907.77 CERT EXP33-C and EXP34-C : Null Dereference . . . . . . . . 1927.78 Omp Private Lock . . . . . . . . . . . . . . . . . . . . . . . . . . 1967.79 CERT-DCL04-A: One Line Per Declaration . . . . . . . . . . . . 1987.80 Operator Overloading . . . . . . . . . . . . . . . . . . . . . . . . 2007.81 Other Argument . . . . . . . . . . . . . . . . . . . . . . . . . . . 2027.82 Place Constant On The Lhs . . . . . . . . . . . . . . . . . . . . . 2037.83 Pointer Comparison . . . . . . . . . . . . . . . . . . . . . . . . . 2057.84 Prefer Algorithms . . . . . . . . . . . . . . . . . . . . . . . . . . . 2067.85 Secure Coding : FIO07-A. Prefer fseek() to rewind() . . . . . . . 2087.86 Prefer Setvbuf To Setbuf . . . . . . . . . . . . . . . . . . . . . . . 210

6 CONTENTS

7.87 Protect Virtual Methods . . . . . . . . . . . . . . . . . . . . . . . 2127.88 Push Back . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2147.89 Right Shift Mask . . . . . . . . . . . . . . . . . . . . . . . . . . . 2177.90 Set Pointers To Null . . . . . . . . . . . . . . . . . . . . . . . . . 2197.91 Single Parameter Constructor Explicit Modifier . . . . . . . . . . 2217.92 Size Of Pointer . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2237.93 Secure Coding : INT06-A. Use strtol() to convert a string token

to an integer . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2257.94 Sub Expression Evaluation Order . . . . . . . . . . . . . . . . . . 2287.95 Ternary Operator . . . . . . . . . . . . . . . . . . . . . . . . . . . 2307.96 Time t Direct Manipulation . . . . . . . . . . . . . . . . . . . . . 2327.97 Unary Minus . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2347.98 Uninitialized Definition . . . . . . . . . . . . . . . . . . . . . . . 2357.99 Upper Range Limit . . . . . . . . . . . . . . . . . . . . . . . . . . 2377.100Variable Name Equals Database Name . . . . . . . . . . . . . . . 2397.101Void Star . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 241

8 Appendix 2438.1 Design And Extensibility of Compass Detectors . . . . . . . . . . 243

CONTENTS 7

Acknowledgments

This tool is the product of the entire ROSE team. Compass depends upon theROSE open compiler infrastructure and is a simple application of mechanismsin ROSE which have been developed over several years and contributed to by alarge number of people.

This currently includes:

• Staff: Dan Quinlan

• Post docs: Thomas Panas, Chunhua Liao, and Jeremiah Willcock

• Ex Post doc: Richard Vuduc

• Students:Gergo Barany, Michael Byrd, Valentin David, Han Kim, Robert Preissl,Andreas Saebjornsen, Jacob Sorensen, Ramakrishna Upadrasta, JeremiahWillcock, Gary Yuan

• Internal LLNL Contributors: Greg White

• External Collaborators:We want to thank CERT, who has been particularly helpful and supportiveboth with the development of checkers for their Secure Coding Rules andwith numerous suggestions.

8 CONTENTS

Chapter 1

Introduction

A software analysis story about four people named: Everybody,Somebody, Anybody, and Nobody. There was an important job tobe done and Everybody was sure that Somebody would do it. Any-body could have done it, but Nobody did it. Somebody got angryabout that because it was Everybody’s job. Everybody thought thatAnybody could do it, but Nobody realized that Everybody wouldn’tdo it. It ended up that Everybody blamed Somebody when Nobodydid what Anybody could have done. 1

1.1 Overview

Compass is a tool for the checking of source code. It is based on theROSE compiler infrastructure and demonstrates to use of ROSE tobuild lots of simple pattern detectors for analysis of C, C++, andFortran source code.

The purpose of this work is several fold:

• Provide a concrete tool to support interactions with lab cus-tomers.

• Provide a home for the security analysis specific detectors beingbuilt within external research projects.

• Provide an external tool for general analysis of software.

• Provide a tool to support improvements to the ROSE sourcecode base.

• Define an infrastructure for an evolving and easily tailored pro-gram analysis tool.

• Provide a simple motivation for expanded use of ROSE by ex-ternal users. Development, testing, and evaluation of ROSEinfrastructure is best facilitated through its expanded use by

1Story not really specific to softare analysis found athttp://www.corsinet.com/braincandy/hlife.html

9

10 CHAPTER 1. INTRODUCTION

others and this provides a specific and attractive tool that canprovide feedback to users about their own code projects. Eventhough optimization research is our focus, this gets our sup-porting infrastructure for optimization research out and intouse by others in the form of an extensible tool.

Note that as the collection of detectors grows we will periodically re-organize the collection. At some point soon we will build a hierarchyto organize the evolving collection.

A basis for other source analysis tools Input and output toROSE is organized so that any number of sources could be used.So although we provide a compiler interface (for simplicity), we willalso provide a GUI interface as an alternative interface to demon-strate that the detectors are orthogonal to there use in alternativetools. Alternative tool interfaces should be possible and will furtherdemonstrate the independence of the input and output mechanismsto the designs and implementation of the core detectors.

Add Your Own Detector Detectors written in Compass makedirect use of ROSE and are designed to be copied and extended byusers to develop their own detectors. We welcome the contributionof these detectors back to the ROSE team for inclusion into futurereleases of Compass; full credit for all work will be provide to allauthors. Compass is an open source project using ROSE, an opensource compiler infrastructure.

Each of the detectors are examples of how to add your own detectorto Compass. If you build a detector that you would like to havebe distributed with Compass, please send it to us and we will addyour as an external contributor.

Guidelines for contributions:

• Use any Compass detector and an example.

• provide the documentation about your detector.

• Use any features in ROSE to support your detector; AST, Con-trol Flow graph, System dependence Graph, Call Graph, ClassHierarchy Graph, etc.

• Your detector should have NO side-effects on the AST.

Chapter 2

Design and Verification

Compass is a tool is used to analyze software (both source codeand binaries). A collection of checkers are built with each of themdetecting the violation of a rule. By reporting on the violations ofrules Compass provides a way to enforce predefined or arbitrary userspecified properties on software. This chapter covers the design ofCompass and the design of the verification in the Compass Verifier,used to verify properties of the checkers implemented and submittedto Compass.

2.1 Usage Model

Figure 2.1 shows the usage model (use cases) of Compass. The anal-ysis is triggered by the user running Compass over an input file(source code or binary). The user implicitly selects which checkersto execute (defining what rules are to be enforced); by default allcheckers are run. The user also specifies the input file to be checked;for source code the specification is similar to the command line re-quired for the compilation in the case of a source file. Results of theanalysis are presented to the user, a number of mechanisms can beused to display the results.

Either the same user or a different user/developer can also implementand submit checkers to be built into Compass. Since external usersmay contribute checker automatically via scripts, a verification ofthe validity and safety of these checkers is necessary. We providea Compass Verifier that helps to check that all checkers are safe.Currently, the verifier is run by an administrative person but mayrun automatically in the future.

11

12 CHAPTER 2. DESIGN AND VERIFICATION

Figure 2.1: Compass Use Case

2.2 Trust Model

By design we make a few assumptions about the use of Compass inorder to define a secure tool. We assume:

1. For now, there is an assumption of trust in the person writingthe checker.We use the Compass Verifier as a way to double check thecheckers so that we can eventually weaken the level of trustassumed for people writing checkers. However, the design ofthe Compass Verifier is not likely to ever be robust enoughto guarantee an automated proof of security for each checker.Thus, we also assume that someone trusted will also review thechecker. not implemented: We expect that a digital signature(using a key mechanism) is possible to associate a trusted re-viewer with a review of the checker together with a strong hashfunction that digitally signs the checker source code.

2. Since running Compass Verifier is an optional part of build-ing the Compass executable, the person running these test istrusted. There are two ways to run the Compass Verifier (seesection 3.7 for details):

• Slow: once on each checker (make verify). This mecha-nism tests all the files one checker at a time and thus cannot miss a file. Note that even the counter examples aretests which can be a problem when the counter example forthe checker is detected as a violation for Compass Verifier.

2.3. ARCHITECTURE 13

Counter examples for checkers have to be carefully writtento not represent examples that violate Compass Verifier.

• Fast: once on the union of all the checkers (makeoneBigVerify). This step forms a single file of all thecheckers (and in-doing so can miss some files, and so is lesssecure). It is mostly for testing purposes.

3. The person building the Compass executable is trusted.

4. The environment where the testing using Compass is done istrusted.

5. Compass is designed so that the user running Compass neednot be trusted.

It is unclear at present how weak the assumption of trust on thecompass checker developer can be and it may ultimately dependdirectly on the capabilities of the Compass Verifier.

2.3 Architecture

Figure 2.2: Compass Architecture

Compass is a tool that allows users to implement checkers to lo-cate and report software defects. Documentation of various kindsof software defects can be found in sources such as the CERT Se-cure Coding Rules, Common Weakness Enumeration from MITRE,and other sources. Our focus is not to define new software defectsbut rather to provide a platform that allows the easy implemen-tation of defect checkers. Compass has been designed to be easyto extend, allowing users to implement their own custom checkers(custom source code analyses for identifying defects), as shown inFigure 2.2. Compass supports the implementation of both simple

14 CHAPTER 2. DESIGN AND VERIFICATION

as well as more advanced defect checkers. For the latter, Compassutilizes the ROSE infrastructure to perform a wide range of generalpurpose program analyses, such as control flow analysis, data flowanalysis, program slicing, etc.

Compass is designed in a way that allows users who do not neces-sarily have compiler backgrounds to utilize the ROSE infrastructureto build their own analysis tools. Compass is foremost an extensibleopen source infrastructure for the development of large collections ofrules. Our current implementation supports automatic defect check-ing, programming language restriction, and malware detection in C,C++, and object code. Support for Fortran is a new addition toROSE and will be supported in Compass in the near future.

2.4 Design

Compass is designed to be easy to extend. Any user may writea checker and add it to Compass. Figure 2.3 illustrates the UMLdesign decisions behind Compass.

Most of the functionality of Compass is in abstract classes hidden inthe Compass namespace within compass.h - a file within the com-passSupport directory. The figure uses a specific example, Const-Cast, for illustration; Compass is designed to support a large numberof checkers (hundreds). All checkers, such as the ConstCast checker(illustrated in figure 2.3), utilize the abstract classes to traverse aprogram with all its nodes and to output violations found in thatcode according to the local algorithm.

CompassMain is the main executable that initially calls ROSE toparse a program. Then buildCheckers is called to load all checkersthat are specified within a configuration file. The configuration fileallows users to turn on and turn off specific checkers for their run-time analyses. However, the configuration file only permits checkersto be loaded that were part of Compass at compile-time.

The main interface file compass.h contains the class Checker andthe abstract class OutputObject. Checker is the interface to ROSE,giving the metadata for a checker and a function to apply the checkerto a given AST. OutputObject aids to output defects found by aspecific checker. More functionality to handle e.g. file input andparameters provided to Compass, is provided within the Compassnamespace.

2.5 Compass Verifier

Compass must be safe, so that analyses and their results can betrusted. The Compass Verifier is used at build time to run a specificset of separate compass rules offer the source code of all the checkers.

2.5. COMPASS VERIFIER 15

Figure 2.3: Compass Design

For simplicity it runs in two modes: fast, for checking specific namedchecker source files; and slow, for testing all checker source files.

2.5.1 Threats

In order to define a complete design for security we outline thethreats that understand to be relevant. The main threats to thevalidity of Compass checkers are:

• Malicious UserA malicious user is an external user of Compass contributing achecker that performs malicious behavior.

• Malicious CheckerCompass is extensible and new checkers can be added externally(users outside the main development group). A checker can be

16 CHAPTER 2. DESIGN AND VERIFICATION

programmed arbitrarily using the C/C++ and assembly pro-gramming languages. It is therefore possible for a skilled pro-grammer to hide malicious operations within a checker. Com-pass must prevent checkers with malicious behavior to be partof the Compass system. Threats are:

– exfiltrationA checker should act in a secure way with the input files itis given. Securing the inputs to Compass (e.g. the inputsto each checker) from exfiltation is a first priority. Allowinga checker to scan the host machine to exfiltrate arbitrarydata (this is a threat that any secure software will have).

– modification of filesystemA checker should be side-effect free, or have only well de-fined side-effects, but a malicious checker could modify orerase parts of the accessible file system (e.g. deleting wholedirectory structures).

• Malicious CompassSince Compass is built from ROSE, it is possible to modifycompass (or any checker) to generate source code that couldbe compiled to replace the existing executable (there are someconstraints here) or regenerate the source code to replace theexisting source code or perhaps just provide an alternative copyof the source code. This indirect transformation of the inputcode is a threat.

• Source Code ReplacementIt should not be possible for users to exchange the source codeof checkers within a running system, i.e. Compass cannot im-plement dynamic loading of checkers. Such a feature wouldcompromise its safety.

• Binary ReplacementAnother threat is the replacement of a valid Compass checkerwith a modified malicious version within a binary release ofCompass. Therefore, Compass should be aware if parts of itselfwere modified and should not execute.

2.5.2 Mitigation of Threats

Compass is designed to be safe. The Compass Verifier is a stableseparate copy of Compass that contains only a few checkers to check(external and internal) user delivered checkers for safety. We havehopefully designed Compass in a way that it addresses the threatsmentioned above:

• Malicious UserInitially, we permit only trusted individuals to add new checkersto Compass. Once the verification process is matured, we willextend this policy to allow less trusted users to contribute to

2.5. COMPASS VERIFIER 17

Compass. A goal will be to allow arbitrary users to contributecheckers, however, a review of the whole Compass design (andthe Compass Verifier especially) will be required to define re-quired trust levels for user/developers who implement checkers.

FIXME: We might definetrusted and untrusted checkers as

a way to have checkers fromarbitrary users, but mark them

as untrusted.

• Malicious CheckerTo prevent Compass from executing malicious code, the Com-pass Verifier executes its own checkers on any user definedchecker that is being considered to be added to Compass. Cur-rently, the Compass Verifier contains three checkers:

– fileReadOnlyAccess ensures that a user defined checker per-forms no write or execute operations on files.

– allowedFunctions is a white list of function calls permittedin a checker. This list contains functions that are trustedand hence considered safe when integrated to Compass. FIXME: This is not yet

implemented as a white list andis instead currently a black list;

called: forbiddenFunctions.

– noAsmStmtsOps searches for assembly instructions in achecker and flags and reports all cases as unsafe.

– To avoid modifications of the AST for the purpose of al-lowing other checkers to pass, the AST should not be mod-ified (this should extend to all the program analysis graphsgenerated and used by other checkers). This is not imple-mented yet.

• Malicious CompassSince Compass does not generate code, it can not be used tomodify the input software (source code or binary) or generatea new copy that could be confused with the input. However,future versions of Compass make make transformation to in-troduce greater levels of security; fix flaws, mitigate specificforms of threats, etc. It will be important to make sure thatsuch transformation can not change the behavior of an inputcode to make the modified input code malicious. Current pro-posed approaches would build a patch which would have to beinspected by a trusted developer before it would be applied tomodify the input code.

• Source Code ReplacementCheckers can only be added at compile time to Compass, not atrun-time. This means that checkers (meaning the source code)cannot be exchanged against unsafe versions at run-time. Fur-thermore, we allow only the Compass tool builder (admin) tobuild versions of Compass that must pass the Compass Verifier.

• Binary ReplacementOur goal is to perform a strong hash (e.g. Secure Hash Algo-rithm - SHA2) as a checksum on all the checkers part of thebinary Compass distribution before Compass is executed. Inthis way Compass will not run if parts of it were modified.This is not implemented yet. FIXME: We should describe the

policy for allowing SHA2 to beverified. Where the SHA2 results

for checkers would be published(e.g. web site), etc.

18 CHAPTER 2. DESIGN AND VERIFICATION

2.6 Future Work

Currently we are engaged in design reviews with CERT, we expectthat this will lead to improvements in the security to support akey based approach to a trusted execution of tools built within thecompass infrastructure, including Compass itself.

Chapter 3

Using Compass

Compass is currently distributed as part of ROSE, and representsone of many tools that can be built using the ROSE open com-piler infrastructure. The source code of Compass resides in theROSE/projects/compass. The compass project is currently dividedinto three subdirectories representing the compass infrastructure,extensions (checkers), and individual compass-like tools. As part ofbuilding ROSE Compass will be automatically built in the compassdirectory.

3.1 Installation

Please follow ROSE Installation Guide to configure, make, and makeinstall ROSE. The Compass executable file (compassMain) will beavailable from YOUR ROSE INSTALL PATH/bin. compassMainneeds to know where to find its own configuration information fromtwo files:

• compass parameters: configuration information for compasscheckers. A default parameter file is generated in your ROSEbuild tree: buildrose/projects/compass/tools/compass/com-pass parameters. You can save a copy to your home directoryfor customization.

• RULE SELECTION: This file lists which checkers to be used.A sample file is provided in the ROSE source tree: source/pro-jects/compass/tools/compass/RULE SELECTION.in. Youcan save it as RULE SELECTION in your home directory andflip the + or − sign before each checker to turn on or off themwhen running compassMain. This file is specified as Com-pass.RuleSelection=/home/youraccount/RULE SELECTIONinside of the compass parameters file.

19

20 CHAPTER 3. USING COMPASS

After preparing compassMain’s configuration files, you can set envi-ronment variables as follows (assuming using bash and you config-ured ROSE using –prefix=/home/youraccount/opt/roseLatest):

PATH=/home/youraccount/opt/roseLatest/bin:$PATHexport PATH

LD_LIBRARY_PATH=/home/youraccount/opt/roseLatest/lib:$LD_LIBRARY_PATHexport LD_LIBRARY_PATH

export COMPASS_PARAMETERS=/home/youraccount/compass_parameters

3.2 Running Compass

Once properly installed and configured, running compass is a matterof typing compassMain and handing in a number of options. ThecompassMain program acts just like a compiler so it is appropriateto hand it the same options required to compile your source file (e.g-I directory paths and a source file. Compass will figure out thelanguage from the source file suffix. Using the --help option willprovide a more complete list of options available to ROSE basedtools. See also the section of this chapter on the include/excludeoptions for path and file names as these will permit the output fromheader files to be tailored.

For example, to test a checker which warns about error-pronepointer comparison. You can modify RULE SELECTION to onlyturn on PointerComparison. A test input code (pointerCompar-isonTest1.C) is provided in sourcetree/projects/compass/extension-s/checkers/pointerComparison.

# command line to run compassMain on a source filecompassMain pointerComparisonTest1.C# output of the commandRunning Prerequisite SgProject

Running checker PointerComparisonPointerComparison: pointerComparisonTest1.C:16.7-19:Warning: Error-prone pointer comparison using <,<=,>,or >=

3.3 Output from Compass

Output from compass can be generated in a number of forms, thedefault is ASCII text output of the messages about rule violationswith the source code position in GNU standard source code positionformat. This form can be used to interact with external tools (e.g.Emacs) to permit alternative interface to Compass. Mechanismsavailable include:

3.3. OUTPUT FROM COMPASS 21

• Emacs:Detecting errors while you type 3.5 and 3.1.

• Vim 7:Compass can work with Vim 7’s QuickFix commands to high-light source lines with error messages 3.9.

• CompassGUI:There is also a Compass GUI for reviewing Compass output andinteractively rerunning compass and sifting through the outputwhile relating them to the source code 3.2. This work uses theQRose library produced at Imperial College London by GabrielCoutinho, as part of their development of FPGA tools usingROSE. QRose is based on the Qt library and provides a widenumber of ROSE aware components to make the developmentof GUIs for ROSE based tools easy. The source code for theCompass GUI is provided, but this work is unfinished (andrequired the QRose library available from Imperial).

• ToolGear post-processing:Output in XML permits the use of ToolGear (LLNL tool avail-able on the web) for viewing Compass generated output. Thismechanism is particularly useful for reviewing the results ofnightly builds (and associated runs of large projects using Com-pass). See figure 3.3

• ASCII output:Output in ASCII format is of the form shown in 3.4. This formpermits the connection to multiple external tools (the Emacsinterface reads the ASCII output format directly).

3.3.1 Using Compass With Emacs

Compass as a checker is most useful when the user is notified asearly as possible when he violates a desired software property. Al-though for many purposes it is sufficient to run Compass separately;it is possible to use compass seamlessly when developing in emacs.By using an emacs extension called flymake together with Compasserroneous lines can be highlighted while programming, and the rele-vant error messages displayed in a dialog. Syntax errors from ROSEwill be displayed as well, see figure 3.1.Much thanks for David Svoboda at CERT at CMU for first config-uring Flymake to work with Compass and demonstrating the idea.It has provided a great way to check code using compass and its usein Emacs has stimulate a number of ideas that have made their wayback into Compass.

Emacs .emacs Code Requirement

Figure 3.5 shows the code that is required to be added to the .emacsfile. A copy of this code is available in the compass source directory

22 CHAPTER 3. USING COMPASS

Figure 3.1: Compass error messages integrated into Emacs

3.3. OUTPUT FROM COMPASS 23

Figure 3.2: Compass GUI for interpretation of rule violations

24 CHAPTER 3. USING COMPASS

Figure 3.3: Processing of XML Compass output using ToolGear

LocalizedVariables: /home/ROSE/projects/compass/tests/Cxx_tests/test2006_117.C:30.5: Variable pmNull does not seem to be used.FunctionDefinitionPrototype: /home/ROSE/projects/compass/tests/Cxx_tests/test2006_123.C:27.1-10: matching function prototype not availableLocPerFunction: /home/ROSE/projects/compass/tests/Cxx_tests/test2006_117.C:23.1-20: This function has too many lines of code :: LOC = 14 > 10MagicNumber: /home/ROSE/projects/compass/tests/Cxx_tests/test2006_117.C:33.14: Occurrence of integer or floating constant.MagicNumber: /home/ROSE/projects/compass/tests/Cxx_tests/test2006_117.C:36.14: Occurrence of integer or floating constant.MagicNumber: /home/ROSE/projects/compass/tests/Cxx_tests/test2006_117.C:37.14: Occurrence of integer or floating constant.FunctionDocumentation: /home/ROSE/projects/compass/tests/Cxx_tests/test2006_123.C:27.1-10: function is not documented: name = ::mainFunctionDocumentation: /home/ROSE/projects/compass/tests/Cxx_tests/test2006_123.C:9.10: function is not documented: name = ::X < int , int , 10 > ::fFunctionDocumentation: /home/ROSE/projects/compass/tests/Cxx_tests/test2006_123.C:12.10: function is not documented: name = ::X < int , int * , 5 > ::fFunctionDocumentation: /home/ROSE/projects/compass/tests/Cxx_tests/test2006_123.C:16.10: function is not documented: name = ::X < int * , float , 10 > ::f

Figure 3.4: Example of ASCII output from Compass.

3.3. OUTPUT FROM COMPASS 25

in the file emacs compass config.el.

Emacs Version Requirement

Emacs version 22 or newer is required to take advantage of the emacsintegration of Compass. Before using Compass a 3 step process mustbe followed:

• Add the text in figure 3.5 (inROSE/AUG0508/ROSE/projects/compass/tools/compass/emacs compass config.el)to .emacs

• Change /path/to/makefile in figure 3.5 to the path to theproject you are editing in Compass

• Add a ’check-syntax’ rule to the makefile of the project thatyou are working on in Compass. This rule should compile allthe files you want Compass to check or all files that you areediting with Compass as the compiler.

Figure 3.5 shows the needed changes in .emacs for integrating Com-pass. The last two lines are the most interesting lines since theyintroduce two shortkeys. [f3] can be clicked in order to display allerrors for the current line while [f4] will move the cursor to the nexterror.

A short explanation of the code in figure 3.5 is that the first line willrequire the flymake extension to be available upon loading emacswhile the second line will load the find-file-hook and flymake-find-file-hook functions. The ”setq” sections that follows runs Compassfor all files that are being edited that has the c and C extensions.The “list” section tells flymake to execute the check-syntax rule inthe makefile.

Example check-syntax rule

Figure 3.6 shows an example makefile that compiles a file ”one.C”using g++. If ”one.C” is edited using emacs the addition of the”check-syntax” rule is needed, as shown in figure 3.7.

3.3.2 Using Compass With Vim

Compass can be used with Vim 7’s QuickFix commands to displaywarning messages and highlight the source lines in question. A com-pass compiler plugin (compass.vim as shown in Figure 3.8) has beenprovided for Vim to parse the warning messages outputted by Com-pass.

Steps to make Compass work with Vim 7

• Save compass.vim into .vim/compiler. Create the target di-rectory if it does not exist.

26 CHAPTER 3. USING COMPASS

; New Compass support for Emacs using version 22 of Emacs and Flymake.; Comment out these two lines to use older version of emacs.(require ’flymake)(setq flymake-allowed-file-name-masks (cons ’(".+\\.C\\’" flymake-simple-make-init flymake-simple-cleanup flymake-get-real-file-name) flymake-allowed-file-name-masks))

(defun flymake-master-make-header-init ()(flymake-master-make-init ’flymake-get-include-dirs

’("\\.C\\’" "\\.c\\’")"[ \t]*#[ \t]*include[ \t]*\"\\([[:word:]0-9/\\_.]*%s\\)\""))

(add-hook ’find-file-hook ’flymake-find-file-hook)

(setq flymake-log-level 3)(setq flymake-no-changes-timeout 0.5)

(defcustom rose-source-tree "/home/dquinlan/ROSE/NEW_ROSE/" "Location of top of ROSE source tree")(defcustom rose-build-tree "/home/dquinlan/ROSE/ROSE_CompileTree/LINUX-64bit-3.4.6/" "Location of top of ROSE build tree")(defun add-buildfile-dir-for-rose ()

(let ((source-dir-name (file-name-directory buffer-file-name)));(message "%S" ‘(source dir ,source-dir-name))(if

; (string-equal rose-source-tree (substring source-dir-name 0 (length rose-source-tree)))(string-equal rose-source-tree (substring source-dir-name 0 (min (length source-dir-name) (length rose-source-tree))))(let ((buildfile-dir (concat "../../../../../../../../../../../../../../../../../../../" rose-build-tree "/" (substring source-dir-name (length rose-source-tree))))); (message "%S" ‘(buildfile-dir ,buildfile-dir)); (set-variable ’flymake-buildfile-dirs (cons buildfile-dir flymake-buildfile-dirs) ’local))

(set-variable ’flymake-buildfile-dirs (append (mapcar (lambda (dir) (concat buildfile-dir "/" dir)) flymake-buildfile-dirs) flymake-buildfile-dirs) ’local))(progn

;(message "%S" ‘(bad-prefix))source-dir-name))))

(defun set-rose-source-dir (dir) "Set the top of the ROSE source tree to use with Flymake" (interactive "DThe top of the ROSE source tree: \n")(setq rose-source-tree dir ’local)(add-buildfile-dir-for-rose))

(defun set-rose-build-dir (dir) "Set the top of the ROSE build tree to use with Flymake" (interactive "DThe top of the ROSE build tree: \n")(setq rose-build-tree dir ’local)(add-buildfile-dir-for-rose))

(add-hook ’find-file-hook ’add-buildfile-dir-for-rose)

;(list "make";; (list "-s" "-C" "/home/dquinlan/ROSE/NEW_ROSE/developersScratchSpace/Dan/EmacsCompass_tests/"; (list "-s"; (list "-s -C" "‘pwd | sed ’s@^/home/dquinlan/ROSE/NEW_ROSE/@/home/dquinlan/ROSE/ROSE_CompileTree/LINUX-64bit-3.4.6/@’‘"; (concat "CHK_SOURCES=" source); "SYNTAX_CHECK_MODE=1"; "check-syntax"))

(global-set-key [f3] ’flymake-display-err-menu-for-current-line)(global-set-key [f4] ’flymake-goto-next-error)

Figure 3.5: Addition to .emacs when integrating Compass into emacs.

one: inc.h one.Cg++ -c one.C

Figure 3.6: Example makefile before the Compass addition

3.4. INCLUDING/EXCLUDING CHECKERS IN THE COMPASS BUILD PROCESS27

one: inc.h one.Cg++ -c one.C

check-syntax: inc.h one.C/path/to/compass/executable/compassMain -c one.C

Figure 3.7: Example makefile after addition to support integration of compass

• Download errormarker.vim fromhttp://www.vim.org/scripts/script.php?script id=1861 andsave it into .vim/plugin . Again, create the target directoryfirst when it does not exist.

• Change your Makefile to use an installed compassMain as thecompiler to compile your code.

• Use quickfix features of Vim 7 as documented athttp://vimdoc.sourceforge.net/htmldoc/quickfix.html. Somefrequently used commands are:

– Specifying the compass plugin to use by typing a command:compiler compass

– Open your source code using gvim and set the compiler toCompass by

– Compile you code using compassMain, type :make– Display current message, type :cc– Display all messages, type :clist– Jump to next message, type :cnext

Figure 3.9 shows an example of Compass error messages integratedinto Vim 7.

3.4 Including/Excluding Checkers in theCompass Build Process

This section describes how to select which of the checkers to integrateinto Compass out of all the checkers available in source form in theCompass source directory. For security reasons Compass uses thisstatic build process since it is a central goal of Compass that it shouldrun as a trusted part of a project’s build process. If the integration ofcheckers had been automatic through a dynamic plugin mechanismit would be hard to ensure that the dynamic list of checkers wassecure, but for a static list of trusted checkers this is possible.

The file ROSE SOURCE DIR/projects/compass/tools/compass/CHECKER LISTis used to control which checkers are selected to be compiled intocompassMain. It can use the ‘#’ comment delimiter at the begin-ning of any checker name to remove that checker from compilation.

28 CHAPTER 3. USING COMPASS

" Vim compiler file" Compiler: ROSE Compass 0.9.2a" Maintainer: Chunhua Liao <[email protected]>" Last Change: 2008 Apr. 3"if exists("current_compiler")

finishendiflet current_compiler = "compass"

if exists(":CompilerSet") != 2 " older Vim always used :setlocalcommand -nargs=* CompilerSet setlocal <args>

endif

" single line warning" multiple line warning, %W, %C continue line %Z end of multiple lineCompilerSet errorformat=%s:\ %f:%l%.%c:\ %m,

\%s:\ %f:%l%.%c-%*\\d:\ %m,\%s:\ %f:%l%.%c-%*\\d%.%*\\d:\ %m,\\\"%f\"\\,\ line\ %l%*\\D%c%*[^\ ]\ %m

"some notes about the error/warning message format"Official guide: http://vimdoc.sourceforge.net/htmldoc/quickfix.html#error-file-format" Each new rule start with a leading \ unless it is the first rule in the" first line" %f: filename %l: line number %c: column number, only one is permitted %m" actual error/warning message \ :matching a space" %*\\d: matching any number

Figure 3.8: A compiler plugin for Vim 7 compass.vim

The hash mark may only appear at the beginning of the line. Thecompass submission setup.sh script must be run again with the“regenerate” option if any checkers are commented out. Note thatno space is permitted between the ‘#’ and the name of thechecker.

Usually the CHECKER LIST is only modified when a user or de-veloper wants to add a new checker or select a subset of trustedcheckers. Checkers can be commented out using a #, no space isallowed between the # and the checker name.

3.5 Including/Excluding Checkers Dur-ing Compass Execution

This section describes how to execute a subset of the checkers pro-vided in the build process (see section 3.4). This process is sig-nificantly more interactive than defining what checkers to includein the Compass build process. Since it is not unheard of thatrules implemented by different checkers can be mutually exclusiveor even contradicting this mechanism is essential for selecting thesubset of checkers that are interesting for a specific program thatis checked. Separate projects of developers could easily have theirown RULE SELECTION file to permit high levels of customizationin the use of a Compass tool containing a large number of checkers(e.g. for different languages).

3.5. INCLUDING/EXCLUDING CHECKERS DURING COMPASS EXECUTION29

Figure 3.9: Compass error messages integrated into Vim 7

30 CHAPTER 3. USING COMPASS

When used with the Emacs interface this provides a simple wayto turn on and off specific checkers by editing a single file(RULE SELECTION). The name of this file is specified in thecompass parameters file, this name may be changed. The directo-ries searched are: current directory, user home directory, and Com-pass source tree (respectively).FIXME: The current

implementation may not supportall of the mentioned search paths.

Compass.RuleSelection=/path/to/your/RULE_SELECTION

In order to select a checker to run the user must:

• Add a line ’-:<name of checker>’ in a file calledRULE SELECTION.

• If a line ’-:<name of checker>’ already exist the ’-’ can be mod-ified into a ’+’ to enable the checker or into a ’-’ to disable achecker.

It is required that every checker integrated into the Compass buildis mentioned in the RULE SELECTION.

3.6 Including/Excluding Paths and File-names with Compass

Compass permits paths and filenames to be specified for in-clusion/exclusion in reporting checker rule violations. RuncompassMain --help to see the commandline options. Numerousother commandline options provided for all tools build using ROSEmay also be relevant.

3.7 Checking Security Properties ofCheckers

Compass is designed for extensibility while providing the securityfor the codes being checked. To support this Compass provides asimple mechanism for verifying specific properties of the checkersused in Compass. Compass implements a specific small number ofcheckers that are used for checking the checkers in Compass. The di-rectory compassVerify contains the implementation of this subset ofCompass that is used on itself. These checkers may not be modifiedand in the future MD-5 checksums will be provided to ensure theintegrity of this subset of Compass. To verify the compass checkersrun:

• make verifyThis makefile rule runs the compassVerify/compassMain on all

3.8. TESTING COMPASS AND ITS CHECKERS 31

the source files in all the checkers directories in Compass. Be-cause it runs compass on so many separate files this step cantake a long time.

• Or make oneBigVerifyThe makefile rule runs the compassVerify/compassMain on asingle generated file built from all the checker source files andis particularly quick to run.

3.8 Testing Compass and its Checkers

The tests directory contains directories of tests that are languagespecific:

• C testsThis directory contains a Makefile which will use the ROSE Ctest codes to test Compass.

• Cxx testsThis directory contains a Makefile which will use the ROSEC++ test codes to test Compass.

To run these tests type make check at any level on the Compassdirectory hierarchy of the build tree.

32 CHAPTER 3. USING COMPASS

3.9 How To Write A New Checker

3.9.1 Creating A Skeleton

Compass has scripts for creating a skeleton for a new Compasschecker. This skeleton can be easily adapted to write all checkers.

Follow these steps to generate a checker skeleton:

1. Enter a directory where you want the directory of your checkerto be created: For example, rosesourcetree/projects/com-pass/extensions/checkers.

2. Execute ROSE SRC DIR/projects/compass/src/compass scripts/gen checker.sh<name of your checker> (the name of your checker canhave space and the script will automatically concatenate themto camel case, e.g: ”multiple case on same line”)

The results of executing gen checker.sh script is that a new directoryname “multipleCasesOnSameLine” (name of your checker in camelcase) is created with the following files:

• compass parameters : internal parameters for this checker

• multipleCasesOnSameLine.C : main source file

• multipleCasesOnSameLine.compass.external.makefile : make-file if this checker is to be built outside of the ROSE sourcetree.

• multipleCasesOnSameLineDocs.tex : documentation

• multipleCasesOnSameLine.inc : Makefile include file

• multipleCasesOnSameLine.h : header

• multipleCasesOnSameLineMain.C : main driver

• multipleCasesOnSameLineTest1.C : test input code

Some of these files (compass parameters) are copied from the com-pass template generator directory; while others are generated (mul-tiple*, *.makefile)

It is suggested that you keep the following in mind when usinggen checker.sh:

• It is advised that you do not invoke the script gen checker withwords like checker, detector, tester, etc. Adding these verbs atthe command line means that these words are added as suffixesinto the directory-name. Which will make it redundant, as thecompass project is about writing style-checkers!

• Some of the files have read-only permissions and are intendedFIXME: What are the readonlyfiles exactly? only for such use. Please do not change the permissions of these

files.

3.10. EXTENDING THE COMPASS INFRASTRUCTURE 33

3.9.2 Integrating New Checkers Into CompassTool

The process for integrating a new checker into Compass has beenautomated. These directions are meant for checkers generated usinggen checker.sh. The process is similar for all compass-like tools thatare built using the common infrastructure.

The steps to integrate a new checker is (note that both of the sourcetree and build tree of ROSE are involved):

1. Add <camel case of your checker name > toROSE SOURCE DIR/projects/compass/tools/compass/CHECKER LIST

2. Enter ROSE BUILD DIR/projects/compass/tools/compass

3. Execute ’make regenerate’

4. After running ’make regenerate’ in the build tree then you mayrun make as usual.

5. Examine the ROSE SOURCE DIR/projects/compass/tools/compass/RULE SELECTION.infile and confirm it reflects your most recent additionalchecker(s) choice of execution at run-time; the default settingis “on”. Please refer to section 3.5.

3.10 Extending the Compass Infrastruc-ture

Compass, as well as being a tool for software analysis, is also a capa-ble infrastructure for building other tools like Compass that utilizesthe work put into Compass checkers. There are many reasons whyone would like to have a separate executable tool beneath Compassrather than simply customizing a particular build of the Compasstool. An individual or organization may consider a specific subset ofCompass checker rules to be particularly relevant; thus would like tohave a custom tool to check only these rules. Another scenario mayfind that the particular interface for Compass through the commandline needs to be changed; but, it is not advisable to alter Compassmain directly!

This section will demonstrate how to extend the Compass infras-tructure and checkers to build a separate executable tool beneaththe Compass project. A simple tutorial will detail the steps nec-essary to instantiate the Compass infrastructure. The these stepshave been followed and the mechanism is demonstrated in an exam-ple directory (sampleCompassSubset; this directory can be copied.

Suppose one wishes to build a version of Compass with only thosechecker rules authored by an individual for debugging purposes. Cer-tainly, it would not be desirable for the main Compass tool to onlyconsist of this subset of rules; yet this specialized version might be

34 CHAPTER 3. USING COMPASS

required regularly enough for repeatedly altering of the static ordynamic checker rule selection files to become troublesome. The so-lution is to use the Compass infrstructure to build a separate toolby creating a subdirectory under Compass with a small portion ofCompass infrastructure files. Only four files are required: com-passMain.C, CHECKER LIST, RULE SELECTION, Makefile.am.Note also that the compassMain.C file can be any name, but mustonly be consistant with the Makefile.am. This example of usingthe compass infrastructure is compiled as part of compiling com-pass and defines a compass-infrastructure-based tool that imple-ments about 25 randomly selected checkers (form the collection inprojects/compass/extensions/checkers).

Assume that the present working directory isprojects/compass/tools of the ROSE source tree. First,create a directory for the new Compass subset tool.

mkdir sampleCompassSubset

then add this directory in the SUBDIRS variable of the automakefile projects/compass/tools/Makefile.am. Additionally, intro-duce this new Makefile into the top level source tree configure.infile. A snippet concerning these changes is given below:

projects/compass/tools/Makefile.am:SUBDIRS = compass compassVerifier sampleCompassSubset

configure.in:projects/compass/tools/sampleCompassSubset/Makefileprojects/compass/tools/compassVerifier/Makefile

Note that after any modification of configure.in, the configurecommand for ROSE will have to be rerun (else the makefile willcause it to be called for you).

To specify how this tool is to be con-figured and built create a Makefile.am,projects/compass/tools/sampleCompassSubset/Makefile.amis provided as an example. This example can be a template andmay be used in general for any Compass-like tool. Any tool thatis an extension of the Compass infrastructure will reuse much ofthe Compass infrastructure such as compassSupport. Furthermore,much of the Compass build process requires the automatic gen-eration of files in the build tree such as compass makefile.inc,compass parameters, etc. Thus an include file has been providedin Compass to define these common rules– compass.inc; and isincluded in this Makefile.am. A more advanced implementation ofthis automake file template is located in Compass Verifier; which is

3.10. EXTENDING THE COMPASS INFRASTRUCTURE 35

itself another tool extended off Compass and designed to check therules implemented in Compass.

So far, a blank Compass-like tool has been created and config-ured to build with ROSE. Still missing are a few Compass filesthat produce a successful compile and linked executable. Thenext step is to populate the empty Compass-like tool with check-ers from Compass. Note that all checkers reside as subdirectoriesin projects/compass/extensions/checkers; but that subsets ofthese are selected for use, thus all checkers are always optionallyavailable to all compass-infrastructure-based tools. Create a newfile called CHECKER LIST under the sampleCompassSubset directory(an example has been provided) and insert the names of the desiredcheckers into this file. One may also create the dynamic rule selectionfile RULE SELECTION or defer this file to be automatically generatedwith all checker rules activated by default. Finally, it is necessaryto write or copy the compassMain.C file that defines (among otherfunction) the command line processing options where one may al-ter the interface. For sampleCompassSubset the compassMain.C ofprojects/compass/src/compassSupport is symbolically linked inplace. The complete directory list for sampleCompassSubset nowlooks like

CHECKER_LISTcompassMain.C -> ../../src/compassSupport/compassMain.CMakefile.amRULE_SELECTION

The source tree creation and configuration of a new Compass-like tool is complete with Makefile.am, CHECKER LIST,RULE SELECTION, and compassMain.C (rename compassMain.Cas you like just make sure that the name is consistant with theMakefile.am). Build and configure ROSE as usual and theninvoke Make at the top level build tree or projects/compasssubdirectory to compile and link the new Compass-like toolexecutable. In this tutorial example the new target location isprojects/compass/tools/sampleCompassSubset.

36 CHAPTER 3. USING COMPASS

Chapter 4

Using Compass GUI

Compass has a GUI available for exploring the checker warnings foreither the compilation of a single source file or the compilation ofa whole project. This GUI allow the user to interactively selectcheckers, run those checkers on the source file(s) of interest anddisplay the source location of each violation. As a user conveniencethe interface will either display the violating source region in a texteditor or a non-editable display window.

The Compass GUI is located in the ’projects/compass/tools/com-pass/gui’ directory of the ROSE distribution. The Compass GUIis build as part of the standard Compass build when ROSE is con-figured with qt4. In order to enable simple compilation of wholeprojects using one-button clicks in the Compass GUI ROSE mustbe configured with sqlite3 as well.

4.1 Running Compass GUI on a SingleFile

Before running the Compass GUI on a single file the files listedin 3.1 must be available and the environment variable ’$COM-PASS PARAMETERS’ must specify which compass paramaters fileto use. CompassGUI can then be invoked as a normal compiler likee.g:

compassMainGui -o ex1 ex1.C

If it is not desirable to export the ’$COMPASS PARAMETERS’variable a shorthand is:

env COMPASS_PARAMETERS=/location/of/compass_pramateres compassMainGui -o ex1 ex1.C

37

38 CHAPTER 4. USING COMPASS GUI

4.2 Running Compass GUI on an Auto-tools Project

A goal of this section is to show how to run the compass checkerson a whole project (like e.g ROSE) using a one button click in theCompass GUI and present an easy interface for exploring the viola-tions as found during the build. This interface is currently limitedto sequentially building the project and it requires ROSE to be con-figured with sqlite3. The Compass GUI does not try to replace thebuild system; it simply captures how the build system compiles thesource files for a specific version of the project. Although there isno guarantee that this will work when the source code changes itis reasonable to expect the capturing of the build system should bethe same as the code evolves as long as no changes are done to thebuild system.

These instructions can apply to Autotool projects as well as projectsbuild in other build systems, but the shorthands used here for dis-cerning the build system are specific for Autotools.

4.2.1 Capturing a Build System StateFIXME: Document: that this

requires –with-sqlite3 The first step of running the Compass GUI on an autotools projectis to figure out how the build system works. Capturing thebuild system state is done with the ’buildInterpreter’ tool providedin the Compass distribution in the ’projects/compass/tools/com-pass/buildInterpreter’ directory.

In order to facilitate capturing the build system once and movingthe source files around the ’$ROSE TEST REGRESSION ROOT’environment variable must be defined to the string that should bereplaced. For instance if a projects is build within /home/user/pro-ject and it is desired to move the files inside that directoy to adifferent directory define it to be

export ROSE_TEST_REGRESSION_ROOT=/home/user/projectFIXME: Document: Need to bein the buildInterpreter directory. The buildInterpreter tool works as a replacement for the C/C++

compiler during compilation like e.g:

buildInterpreter -o ex1 ex1.C

The output of the run is a database representing how to compileex1.C. The name of the output database is specified by the ’dbname’field in the rqmc file found in the ROSE build directory under ’pro-jects/compass/tools/compass/buildInterpreter/rqmc’ and defaultsto ’test.db’.

To capture the state of a whole build system use ’buildInterpreter’as a replacement for the C/C++ compiler during the build. E.g forgnu make:

4.2. RUNNING COMPASS GUI ON AN AUTOTOOLS PROJECT 39

make CC=buildInterpreter CXX=buildInterpreter

4.2.2 Build A Project Using the Discerned Build

To build a project using Compass specify the output database fromthe capturing of the build state with the ’–outputDb’ paramater tothe Compass GUI. The environment variable must be defined like in4.1, e.g:

cd /directory/with/build/project/sourcesenv COMPASS_PARAMETERS=/location/of/compass_pramateres /compass/gui/build/compassMainGui --outputDb test.db

In the GUI click on regenerate to build the project. The viola-tions found during the build is put into the database for subsequentlookup. After regenerating select the checkers that you are interestedand and click ’refresh’ to display the corresponding violations.

40 CHAPTER 4. USING COMPASS GUI

Chapter 5

Using Compass Verifier

Compass Verifier is a tool extended from Compass to analyze thesource code of Compass and its checkers to detect certain properties.The motivation and design of this tool are discussed in Chapter 2(Design and Verification). This chapter will detail the Make ruleswritten to run Compass Verifier and to setup the parameters to theAllowedFunctions checker.

The rules to setup and run Compass Verifier are found inprojects/compass/tools/compassVerifier/Makefile.am. Fol-lows is an overview of their usage labels, (make oneBigVerify,verify, ...). Verifier is designed to examine the compass toolreferenced in the environment variable $(TOOLBUILD) which by de-fault is projects/compass/tools/compass. This variable may bechanged in the Makefile.am of the source directory or on the com-mand line to make in the build tree.

• oneBigVerify: a fast but rough static analysisover the Compass checker sources. This rule exe-cutes compassVerifier over the concatenation of allsources with names matching those checkers listed in$(TOOLBUILD)/CHECKER LIST WITHOUT COMMENTS with exten-sion (.C). These should be the only sources from the checkersubdirectories that are built with Compass. The consistencyof this concatenation depends on no global (function, variable,etc.) declaration conflicts; usually, this is perserved by defaultas all checkers employ their own namespace.

• verify: a slow and more complete analysis overall files found in the checker directories listed in$(TOOLBUILD)/CHECKER LIST WITHOUT COMMENTS. Theindividual rule labels for verify are generated inverify.makefile identically to those lower case namesfound in $(TOOLBUILD)/CHECKER LIST WITHOUT COMMENTS.Each rule logs the standard output and error to files suffixedout.txt and err.txt respectively and the measure of a

41

42 CHAPTER 5. USING COMPASS VERIFIER

passing checker is an empty standard error log file. Concur-rency may be used with (-j#) option to GNU Make to reducethe time to complete verify.

• new allow list: regenerates the parameter fileprojects/compass/extensions/checkers/allowedFunctions/compass parametersin the source tree used as the allowed functions list in CompassVerifier. The present list assumes that all sources found inthe present source tree of Compass are trusted in their useof function calls and whatever functions are referenced areallowed. Sources processed by Compass Verifier to build thelist of allowed functions consist of compass.C, compassTest-Main.C, buildCheckers.C, and the concatenation of checkersources identical to that of oneBigVerify. Please see thedocumentation for allowedFunctions 7.2 for the details of howthe new list of allowed functions is created and maintained.Not implemented: we plan to limit the recursion of functionreferences to exclude those functions called by calls to libraryfunctions. This should greatly reduce the number of allowedfunctions such that an individual may inspect the generatedfile.

These three Make rules describe the basic user interface for CompassVerifier. Other parameters such as those for ForbiddenFunctionsshould be changed manually. And an individual should examine theresults of Compass Verifier to ensure a checker meets the validationstandards sought-after.

Chapter 6

Categories of CompassCheckers

All available Compass checkers can be roughly categorized as follows:

6.1 Common Styles

• forLoopConstructionControlStmt: for () loop must only includestatements that control the loop or related to the loop control

• inductionVariableUpdate: Do not alter a control variable morethan once in a loop

• uninitializedDefinition: Always initial variables at their initialdeclaration

• unaryMinus: Do not use unary minus on unsigned types

• noGoto: Do not use goto

• nonAssociativeRelationalOperators: Do not associate rela-tional operators (e.g. a == b == c)

• magicNumber: Avoid using integer or floating point literalsoutside of initializer expressions.

• nameAllParameters: Every function parameters should has aname in a function declaration

• oneLinePerDeclaration: Do not declare more than one variablein a single declaration statement.

• placeConstantOnTheLhs: Always put constant on the left sidefor comparison expressions

• functionDefinitionPrototype: Every function should have afunction prototype

43

44 CHAPTER 6. CATEGORIES OF COMPASS CHECKERS

6.2 C styles

• allocateAndFreeMemoryInTheSameModule: malloc()/ free()in a same piece of code to avoid mismatch

• discardAssignment: assignment operator should be used as astand-alone expression statement.

• setPointersToNull: Always set pointers to NULL after theyhave been freed by free()

6.3 C++ styles

• assignmentOperatorCheckSelf: check self-assignment in assign-ment operator

• assignmentReturnConstThis: operator= return type

• booleanIsHas: functions returning boolean should have nameslike isXXX or hasXXX

• constCast: should never cast the constness away

• constructorDestructorCallsVirtualFunction : Don’t direct-ly/indirectly call virtual functions from constructors or destruc-tors: pure virtual function become undefined behaviors

• copyConstructorConstArg: copy constructors should use constreference as an argument

• cppCallsSetjmpLongjmp: should not use C style setjmp() andlong jmp() in C++ code

• dataMemberAccess: Good classes should not have both publicand non-public data members.

• defaultConstructor: Each class should have a user defined de-fault constructor

• doNotUseCstyleCasts: Do not use C-style casts in C++ code

• dynamicCast: Downcast should be done using a dynamic cast

• enumDeclarationNamespaceClassScope: enum types should bedeclared within a class or namespace.

• explicitCopy: A class should have a user-defined copy construc-tor and a copy operator, unless annotated to use default ones

• forLoopCppIndexVariableDeclaration: C++ loop index vari-able should be declared in for (...)

• friendDeclarationModifier: Avoid using friend declarations

• internalDataSharing: Class member functions should not ex-pose data member handles

• voidStar: Public methods should not use void* for argumentsor return types.

• noExceptions: Avoid using C++ exceptions

6.4. CORRECTNESS 45

• nonmemberFunctionInterfaceNamespace: Keep classes andtheir non-member interfaces (friend functions) within the samenamespace

• multiplePublicInheritance: Avoid multiple public inheritance

• noTemplateUsage: Do not use C++ templates

• protectVirtualMethods: Do not expose virtual methods as pub-lic interface

• singleParameterConstructorExplicitModifier: Single parameterconstructor used as converting constructor should have the ’ex-plicit’ modifier

6.4 Correctness

• cycleDetection: control flow graph of code should not containcycles

• defaultCase: Each switch statement should have a default case

• doNotCallPutenvWithAutoVar: Do not use an auto/local vari-able as the parameter of putenv()

• noExitInMpiCode: No exit() from within a parallel code por-tion (MPI)

• sizeOfPointer: Do not computing sizeof(pointer) when youwant to get the size of object pointed to.

• newDelete: Detect several common mistakes when using new,delete: deleting array using delete, not delete[]; deleting NULLpointers; deleting uninitialized pointers

• mallocReturnValueUsedInIfStmt: Always check the returnvalue for malloc() and new

• nullDeref: Several checkers for NULL pointers: checking apointer’s validity before dereferencing it; Do not reference uni-tialized variables

• floatingPointExactComparison: Avoid exact comparisons be-tween a variable to a floating point value

• floatForLoopCounter: floating point variables should not beused as loop counters

6.5 OpenMP

• ompPrivateLock: locks within parallel regions should be beprivate

46 CHAPTER 6. CATEGORIES OF COMPASS CHECKERS

6.6 Security

• allowedFunctions: security analysis, limit the use to a set ofallowed functions

• forbiddenFunctions: Avoid using a set of dangerous functions

• avoidUsingTheSameHandlerForMultipleSignals: dedicatedhandler for each signal

• constStringLiterals: protect string literals using const qualifi-cation

• doNotDeleteThis: Do not delete ’this’ pointer

• functionCallAllocatesMultipleResources: Avoid allocating mul-tiple resources within a single statement(e.g. a function call)

• rightShiftMask: Always use a shift mask for >> to avoid bufferoverflow

6.7 Portability

• charStarForString: C strings must be used instead of STLstrings

• fopenFormatParameter: Format parameter of fopen() shouldnot contain non-portable value

• noAsmStmtsOps: warn the use of embedded assembly code

6.8 Clarity

• explicitTestForNonBooleanValue: Non-boolean values shouldbe compared to explicit values of the same type.

• localizedVariables: Variable declaration should be close to itsfirst use.

• functionDocumentation: Every function should have documen-tation/comments

• variableNameEqualsDatabaseName: Member functions access-ing local variables that get assigned. The result of the functioncall should have a name equal to the first argument

• ternaryOperator: Prefer explicit conditional statements toternary operator a?x:y

6.9 Complexity

• computationalFunctions: check functions exceeding max al-lowed computation operations

6.10. CONSISTENCY 47

• cyclomaticComplexity: a function should not exceed a com-plexity threshold

• deepNesting: functions should not exceed a threshold for scopesinside its body. (too complex)

• locPerFunction: A function should not contain code exceedinga line count threshold

6.10 Consistency

• lowerRangeLimit: Always use inclusive lower limits and exclu-sive upper limits

• upperRangeLimit: same as lower range limit: always using in-clusive lower limits and exclusive upper limit

• otherArgument: Always name the parameter as ’other’, ’that’,or lower case of the class name, for copy constructors

6.11 Better choices

• stringTokenToIntegerConverter: Prefer strtol()/strtoll() toatoi()/atol()/atoll() for better error handling

• preferFseekToRewind: Prefer fseek() to rewind() since fseek()has return code

• preferSetvbufToSetbuf: Prefer setvbuf() to setbuf() for bettererror checking

• preferAlgorithms: Warning hand writing loops when equivalentSTL algorithms exist

6.12 Dangerous choices

• commaOperator: avoid using this confusing language features(,)

• noSecondTermSideEffects: No side effects for second (and be-yond) logical operator in expressions with combined &$ and——.

• noSideEffectInSizeof: Should not have side effects in sizeof().

• noVariadicFunctions: Do not use variadic functions: functionswith varying parameter lists

• noVfork: Do not use vfork()

• operatorOverloading: Avoid operator overloading for &&,——, or , .

• pointerComparison: Avoid error-prone pointer comparison us-ing <,>, <=,and >=

48 CHAPTER 6. CATEGORIES OF COMPASS CHECKERS

• noRand: Do not use the rand() function,• byteByByteStructureComparison: avoid byte-to-byte compar-

ison between structures, they maybe padded.• nonVirtualRedefinition: Do not redefine an inherited non-

virtual functions in a class hierarchy.• noOverloadAmpersand: Operator & should not be overloaded

6.13 Performance/Effectiveness

• controlVariableTestAgainstFunction: Warning about loop con-trol by comparing to a function call

• emptyInsteadOfSize: Using container.empty() instead of con-tainer.size()==0

• pushBack: Warning the use of container.insert()/resize() whichcan be replaced by push back() or push front()

• nonStandardTypeRefArgs: Always pass objects by references,C++

• nonStandardTypeRefReturns: Always return objects by refer-ences, C++

6.14 Misc or Undocumented

• duffsDevice: Detect Duffs Device(a switch statement contain-ing a loop that contains one of the switch’s case or defaultlabels.)

• explicitCharSign: ??• fileReadOnlyAccess: Readonly access to fopen(), used inter-

nally for Compass Verifier• time tDirectManipulation: Do not directly manipulate time t

values. Use difftime()• nameConsistency:• possiblyReplicatedVariables:• staticConstructorInitialization:• subExpressionEvaluationOrder:• typeTypedef:• binaryBufferOverflow• binaryInterruptAnalysis• binPrintAsmFunctions• binPrintAsmInstruction• asynchronousSignalHandler• bufferOverflowFunctions

Chapter 7

List of CompassCheckers

49

50 CHAPTER 7. LIST OF COMPASS CHECKERS

7.1 Allocate And Free Memory In TheSame Module At The Same Level Of Ab-straction

Allocating and freeing memory in different modules and levels ofabstraction burdens the programmer with tracking the lifetime ofthat block of memory. This may cause confusion regarding whenand if a block of memory has been allocated or freed, leading toprogramming defects such as double-free vulnerabilities, accessingfreed memory, or writing to unallocated memory.

To avoid these situations, it is recommended that memory be allo-cated and freed at the same level of abstraction, and ideally in thesame code module.

The affects of not following this recommendation are best demon-strated by an actual vulnerability. Freeing memory in different mod-ules resulted in a vulnerability in MIT Kerberos 5 MITKRB5-SA-2004-002 . The problem was that the MIT Kerberos 5 code containederror-handling logic, which freed memory allocated by the ASN.1decoders if pointers to the allocated memory were non-NULL. How-ever, if a detectable error occured, the ASN.1 decoders freed thememory that they had allocated. When some library functions re-ceived errors from the ASN.1 decoders, they also attempted to free,causing a double-free vulnerability.

7.1.1 Parameter Requirements

No Parameter specifications.

7.1.2 Implementation

No implementation yet!

7.1.3 Non-Compliant Code Example

This example demonstrates an error that can occur when memoryis freed in different functions. The array, which is referred to bylist and its size, number, are then passed to the verify list() func-tion. If the number of elements in the array is less than the valueMIN SIZE ALLOWED, list is processed. Otherwise, it is assumedan error has occurred, list is freed, and the function returns. If theerror occurs in verify list(), the dynamic memory referred to by listwill be freed twice: once in verify list() and again at the end ofprocess list().

7.1. ALLOCATE AND FREE MEMORY IN THE SAME MODULE AT THE SAME LEVEL OF ABSTRACTION51

% write your non-compliant code exampleint verify_size(char *list, size_t list_size) {if (size < MIN_SIZE_ALLOWED) {/* Handle Error Condition */free(list);return -1;

}return 0;

}

void process_list(size_t number) {char *list = malloc(number);

if (list == NULL) {/* Handle Allocation Error */

}

if (verify_size(list, number) == -1) {/* Handle Error */

}

/* Continue Processing list */

free(list);}

7.1.4 Compliant Solution

To correct this problem, the logic in the error handling code in ver-ify list() should be changed so that it no longer frees list. Thischange ensures that list is freed only once, in process list().

% write your compliant code exampleint verify_size(char *list, size_t list_size) {if (size < MIN_SIZE_ALLOWED) {/* Handle Error Condition */return -1;

}return 0;

}

void process_list(size_t number) {char *list = malloc(number);

if (list == NULL) {

52 CHAPTER 7. LIST OF COMPASS CHECKERS

/* Handle Allocation Error */}

if (verify_size(list, number) == -1) {/* Handle Error */

}

/* Continue Processing list */

free(list);}

7.1.5 Mitigation Strategies

Static Analysis

Compliance with this rule can be checked using structural staticanalysis checkers using the following algorithm:

1. Write your checker algorithm

7.1.6 References

ISO/IEC9899-1999 MEM00-A. Allocate and free memory in thesame module, at the same level of abstraction

7.2. ALLOWED FUNCTIONS 53

7.2 Allowed Functions

The validation of code properties often requires the detection of cer-tain functions used. In some cases, the list of undesirable functionsis too large for a mechanism like forbidden functions to be effec-tive. This allowed functions checker performs the opposite by fil-tering function references against a premade accepted list. Onlythose function on this list are allowed in the source and any otherfunction reference used is a reported violation. Usually, the list ofallowed functions is generated based off “trusted sources” input tothe checker.

7.2.1 Parameter Requirements

The compass parameter requirement for this checker has several op-tions including

• AllowedFunctions.OutFile specifies the file name path forthe output of this checker. The list of all allowed func-tions are written to this file formatted identically to com-pass parameters. All other options passed to allowedFunctionsby compass parameters is also preserved in this output file.

• AllowedFunctions.Function# appends an allowed functiongiven in the manged name format written by this checker. Theparameters of this format must start sequentially at zero andincrement until FunctionNum minus one.

• AllowedFunctions.FunctionNum a simultaneous boolean flagand state variable; specifies the total number of allowed func-tions in the accepted list. If this number is postive, the allowedfunction checker executes in testing mode, where all new func-tion references are written to OutFile as new allowed functions.A negative value for FunctionNum switches the checker into de-tection mode where all function references not read from thelist in compass parameters are flagged as violations.

• AllowedFunctions.Library# adds to a list of paths treated assafe libraries. Any sources found in these paths will be ignoredby allowedFunctions.

7.2.2 Implementation

This checker functions in two modes depending on the boolean signof the AllowedFunctions.FunctionNum parameter.

Positive signed FunctionNum puts this checker into testing modewhere new function references are added to the list of allowed func-tions. This mode begins by reading the compass parameters file forfound allowed functions and other options given to allowedFunctions.The existing list of allowed functions is output in-order to the output

54 CHAPTER 7. LIST OF COMPASS CHECKERS

file specified by OutFile. The allowedFunctions traversal then beginsby visiting all function and member function references and detect-ing their membership in the set of allowed functions. Functions notfound in this set are added and written to the OutFile while thosealready found do nothing.

The function reference is detected and output using a special man-gled string generated by allowedFunctions that serves as its uniqueidentifier. This format is recursively generated by looking at thetypes of a functions return and argument parameters as well as itsqualified name joined in a comma-separated string. The string se-quence is return type, qualified name with scope, and arguments orvoid, etc. One simple example is for the memchr function

AllowedFunctions.Function39=*void,::memchr,*void,int,size_t,

After all existing and new allowed functions are written, the Func-tionNum parameter is updated with the current number of allowedfunctions in the list given in OutFile. Essentially, the testing modeis designed for multiple executions of compass with different sourcessuch that a list of allowed functions grows and is maintained in aformat usable for compass parameters.

The other operation mode (detection), reads from com-pass parameters the set of allowed functions. Similarly, the traversalvisits all function and member function references and constructsthe unique manged string identifier for the function. This mangledstring is looked up in the set of all allowed functions. If the functionis found then execution continues; but a function that is not foundin the set of allowed functions is reported as a violation. In general,this will be the mode most users will run AllowedFunctions under.

Several exclusion mechanism are implemented by allowedFunctionsfor ignoring local function definitions and function calls occuringfrom source designated as a safe library. Their implementation re-lies on the file classification mechanism in ROSE string support todistinguish between user, system, and library sources.

7.3. ASSIGNMENT OPERATOR CHECK SELF 55

7.3 Assignment Operator Check Self

This test checks to make sure that the first statement in a assignmentoperator is a check for self-assignment. As noted in An AbbreviatedC++ Code Inspection Checklist 12.1.3 . This will save time allo-cating new memory and (hopefully) deleting the previous copy. Thecheck for return this; is handled by another checker.

7.3.1 Parameter Requirements

No parameters required.

7.3.2 Implementation

This test checks to make sure that the first statement in a assignmentoperator is a check for self-assignment. As noted in An AbbreviatedC++ Code Inspection Checklist 12.1.3 . This will save time allo-cating new memory and (hopefully) deleting the previous copy. Thecheck for return this; is handled by another checker.

7.3.3 Non-Compliant Code Example

class bike{public:const bike& operator= (const bike& other);};

const bike& bike::operator= (const bike& other){...return *this;}

7.3.4 Compliant Solution

const bike& bike::operator= (const bike& other){if (this == &other)

{return *this;}

...return *this;

56 CHAPTER 7. LIST OF COMPASS CHECKERS

}

7.3.5 Mitigation Strategies

Static Analysis

Compliance with this rule can be checked using structural staticanalysis checkers using the following algorithm:

1. Identify member function

2. Check name for operator=

3. Check first statement as If Statement

4. Check arguments to expression to be this and the right handargument.

7.3.6 References

Abbreviated Code Inspection Checklist Section 12.1.3, AssignmentOperator”

7.4. ASSIGNMENT RETURN CONST THIS 57

7.4 Assignment Return Const This

Here we check to make sure that all assignment operators (opera-tor=) return const classType&. By making the return a referencewe can use a = b = c; which is legal C++. By making the referenceconst we prevent (a = b) = c; which is illegal C++.

7.4.1 Parameter Requirements

No parameters necessary.

7.4.2 Implementation

Every member function is checked to see if the name matches ’oper-ator=’. If so we check to make sure the return type is const nameof-class&. All three (const, ref, classname) must be present. We thenmake sure there is at least one explicit return of *this and no ex-plicit returns of anything else. Note: At this time we do not makesure that all paths must reach an explicit return. This is, however,already a warning in ROSE when there is not an explicit return for anon-void returning function. There is also another checker to ensureexplicit returns.

7.4.3 Non-Compliant Code Example

class smallCat{smallCat& operator=(smallCat& other);}

smallCat& smallCat::operator=(smallCat& other){...}

7.4.4 Compliant Solution

class smallCat{const smallCat& operator=(smallCat& other);}

const smallCat& smallCat::operator=(smallCat& other)

58 CHAPTER 7. LIST OF COMPASS CHECKERS

{...}

7.4.5 Mitigation Strategies

Static Analysis

Compliance with this rule can be checked using structural staticanalysis checkers using the following algorithm:

1. Identify member function

2. Check Name for operator=

3. Get return type

4. check for typename and const

5. find explicit return and check for this.

7.4.6 References

Abbreviated Code Inspection Checklist Section 12.1.4, AssignmentOperator”

7.5. AVOID USING THE SAME HANDLER FOR MULTIPLE SIGNALS 59

7.5 Avoid Using The Same Handler ForMultiple Signals

It is possible to safely use the same handler for multiple signals,but doing so increases the likelihood of a security vulnerability. Thedelivered signal is masked and is not delivered until the registeredsignal handler exits. However, if this same handler is registered tohandle a different signal, execution of the handler may be inter-rupted by this new signal. If a signal handler is constructed withthe expectation that it cannot be interrupted, a vulnerability mightexist. To eliminate this attack vector, each signal handler should beregistered to handle only one type of signal.

7.5.1 Parameter Requirements

No Parameter specifications.

7.5.2 Implementation

No implementation yet!

7.5.3 Non-Compliant Code Example

This non-compliant program registers a single signal handler to pro-cess both SIGUSR1 and SIGUSR2. The variable sig2 should be setto one if one or more SIGUSR1 signals are followed by SIGUSR2.

% write your non-compliant code example#include <signal.h>#include <stdlib.h>#include <string.h>

volatile sig_atomic_t sig1 = 0;volatile sig_atomic_t sig2 = 0;

void handler(int signum) {if (sig1) {

sig2 = 1;}if (signum == SIGUSR1) {sig1 = 1;

}}

int main(void) {

60 CHAPTER 7. LIST OF COMPASS CHECKERS

signal(SIGUSR1, handler);signal(SIGUSR2, handler);

while (1) {if (sig2) break;sleep(SLEEP_TIME);

}

/* ... */

return 0;}

The problem with this code is that there is a race condition in theimplementation of handler(). If handler() is called to handle SI-GUSR1 and is interrupted to handle SIGUSR2, it is possible thatsig2 will not be set. This non-compliant code example also violatesSIG31-C. Do not access or modify shared objects in signal handlers.

7.5.4 Compliant Solution

This compliant solution registers two separate signal handlers to pro-cess SIGUSR1 and SIGUSR2. The sig1 handler() handler waits forSIGUSER1. After this signal occurs, the sig2 handler() is registeredto handle SIGUSER2. This solution is fully compliant and accom-plishes the goal of detecting whether one or more SIGUSR1 signalsare followed by SIGUSR2.

% write your compliant code example#include <signal.h>#include <stdlib.h>#include <string.h>

volatile sig_atomic_t sig1 = 0;volatile sig_atomic_t sig2 = 0;

void sig1_handler(int signum) {sig1 = 1;

}

void sig2_handler(int signum) {sig2 = 1;

}

int main(void) {signal(SIGUSR1, handler);

7.5. AVOID USING THE SAME HANDLER FOR MULTIPLE SIGNALS 61

while (1) {if (sig1) break;sleep(SLEEP_TIME);

}

signal(SIGUSR2, handler);while (1) {if (sig2) break;sleep(SLEEP_TIME);

}

/* ... */

return 0;}

7.5.5 Mitigation Strategies

Static Analysis

Compliance with this rule can be checked using structural staticanalysis checkers using the following algorithm:

1. Write your checker algorithm

7.5.6 References

ISO/IEC 03 SIG00-A. Avoid using the same handler for multiplesignals

62 CHAPTER 7. LIST OF COMPASS CHECKERS

7.6 Bin Print Asm Functions

This binary analysis traverses over the AST and prints all functionswithin the binary.

This is an example of how to traverse a binary. This is not a securitychecker per se.

7.6.1 Parameter Requirements

None.

7.6.2 Implementation

See binPrintAsmFunctions.C

7.7. BIN PRINT ASM INSTRUCTION 63

7.7 Bin Print Asm Instruction

This binary analysis traverses over the AST and prints all instruc-tions within the binary.

This is an example of how to traverse a binary. This is not a securitychecker per se.

7.7.1 Parameter Requirements

None.

7.7.2 Implementation

See binPrintAsmInstructions.C

64 CHAPTER 7. LIST OF COMPASS CHECKERS

7.8 Binary Buffer Overflow

This analysis looks for buffer overflows in binaries.

7.8.1 Parameter Requirements

None.

7.8.2 Implementation

The implementation is dependent on the availability of symbols.Functions must have names. The algorithm looks then for the mallocfunction and determines the memory allocation made.

Using the def-use algorithm, uses of the allocated variable are lookedfor and any access beyond the allocation size are flagged as a bufferoverflow.

This analysis operates on a graph, not an AST.

7.8.3 Non-Compliant Code Example

This is an example of a code that will trigger a buffer overflow.

#include <stdio.h>#include <stdlib.h>

int main(int argc, char* argv) {int* arr = malloc( sizeof(int)*10);

int i=0;for (i=0; i<10;++i) {arr[i]=5;

}int x = arr[12];

}

7.9. BINARY INTERRUPT ANALYSIS 65

7.9 Binary Interrupt Analysis

This analysis looks for intx80 instruction calls. If such a call is de-tected, a dataflow analysis traces back the eax register to determinewhat Linux system call will being executed.

E.g. if eax == 1 , its a sys exit, eax == 3, its a sys read or eax ==4 is a sys write.

7.9.1 Parameter Requirements

None.

7.9.2 Implementation

This analysis operates on a graph, not an AST.

See binaryInterruptAnalysis.C

66 CHAPTER 7. LIST OF COMPASS CHECKERS

7.10 Boolean Is Has

This checker makes sure that all boolean variables and functionsthat return a boolean are all named following the convention ‘is ”or ‘has ” per the ALE3D manual.

7.10.1 Parameter Requirements

No parameters required.

7.10.2 Implementation

This implementation checks to see if a function returns a boolean, ifso it checks the first 4 characters in the name of the function for ‘is ”or ‘has ”. It also checks all variable declarations, checks for booleantype, then does the same substring match on its name.

7.10.3 Non-Compliant Code Example

bool chosen_poorly (){return true;}

int main(){bool badly_named;return 0;}

7.10.4 Compliant Solution

bool has_chosen_poorly (){return true;}

int main(){bool is_badly_named;return 0;}

7.10. BOOLEAN IS HAS 67

7.10.5 Mitigation Strategies

Static Analysis

Compliance with this rule can be checked using structural staticanalysis checkers using the following algorithm:

1. finds bool declarations or bool return function declarations

2. checks name

7.10.6 References

ALE3D Section 3.6 Booleans”

68 CHAPTER 7. LIST OF COMPASS CHECKERS

7.11 [No Reference] Buffer OverflowFunctions

This analysis detects possible buffer overflows due to the usage of’unsafe’ function calls. The results need to be either inspected by theuser or if applicable, unsafe function calls can be exchanged againsttheir safe counterparts.

7.11.1 Non-Compliant Code Examples

1 #include <stdio.h>2 #include <string.h>34 using namespace std;56 void fail() {7 char string[50];8 int file number = 0;9 sprintf( string, "file.%d", file number );

1011 char result[100];12 float fnum = 3.14159;13 sprintf( result, "%f", fnum );141516 char str1[]="Sample string";17 char str2[40];18 char str3[40];19 memcpy (str2,str1,strlen(str1)+1);20 memcpy (str3,"copy successful",16);21 printf ("str1: %s\nstr2: %s\nstr3: %s\n",str1,str2,str3);2223 }

7.11.2 Compliant Solution

Example as above; use snprintf instead of sprintf.

7.11.3 Parameter Requirements

None.

7.11.4 Implementation

The following functions are checked for

• sprintf

• scanf

• sscanf

• gets

• strcpy

7.11. [NO REFERENCE] BUFFER OVERFLOW FUNCTIONS 69

• mbscpy

• lstrcat

• memcpy

• strcat

7.11.5 References

Foster , “James C.Foster, Vitaly Osipov, Nish Bhalla, Niels Heinen,Buffer Overflow Attacks, ISBN 1-932266-67-4, p. 211”

70 CHAPTER 7. LIST OF COMPASS CHECKERS

7.12 Secure Coding : EXP04-A. Donot perform byte-by-byte comparisons be-tween structures

Structures may be padded with data to ensure that they are properlyaligned in memory. The contents of the padding, and the amount ofpadding added is implementation defined. This can can lead to in-correct results when attempting a byte-by-byte comparison betweenstructures.

7.12.1 Non-Compliant Code Example

This example uses memcmp() to compare two structures. If the struc-tures are determined to be equal, buf compare() should return 1otherwise, 0 should be returned. However, structure padding maycause memcmp() to evaluate the structures to be unequal regardlessof the contents of their fields.

1 struct my buf {2 size t size;3 char buffer[50];4 };56 unsigned int buf compare(struct my buf *s1, struct my buf *s2) {7 if (!memcmp(s1, s2, sizeof(struct my struct))) {8 return 1;9 }

10 return 0;11 }12

7.12.2 Compliant Solution

To accurately compare structures it is necessary to perform a field-by-field comparison [ Summit 95 ]. The buf compare() function hasbeen rewritten to do this.

1 struct my buf {2 size t size;3 char buffer[50];4 };56 unsigned int buf compare(struct buffer *s1, struct buffer *s2) {7 if (s1->size != s2->size) return 0;8 if (strcmp(s1->buffer, s2->buffer) != 0) return 0;9 return 1;

10 }11

7.12.3 Risk Assessment

Failure to correctly compare structure can lead to unexpected pro-gram behavior.

7.12. SECURE CODING : EXP04-A. DO NOT PERFORM BYTE-BY-BYTE COMPARISONS BETWEEN STRUCTURES71

Rule Severity Likelihood Remediation Cost Priority LevelEXP04-A 2 (medium) 1 (unlikely) 1 (high) P2 L3

Related Vulnerabilities

Search for vulnerabilities resulting from the violation of this rule onthe CERT website .

7.12.4 References

[ Dowd 06 ] Chapter 6, ”C Language Issues” (Structure Padding284-287) [ISO/IEC 9899-1999 ] Section 6.7.2.1, ”Structure and union speci-fiers” [Kerrighan 88 ] Chapter 6, ”Structures” (Structures and Functions129) [Summit 95 ] comp.lang.c FAQ list - Question 2.8

72 CHAPTER 7. LIST OF COMPASS CHECKERS

7.13 Char Star For String

This checker will report when STL strings are used.

7.13.1 Parameter Requirements

The checker does not take any parameters.

7.13.2 Implementation

The checker finds variables declarations, function arguments andtypedefs of string type. The string type may be of pointer type, ref-erence type, array type or it can be modified without any problems.

7.13.3 Non-Compliant Code Example

#include <string>

typedef std::string string2;void bar(std::string arg1){

};

int main(){std::string foo1;std::string* foo2;std::string foo4[4];

};

7.13.4 Compliant Solution

typedef char* string2;void bar(char* arg1){

};

int main(){char* foo1;char** foo2;char foo4[4];

};

7.13. CHAR STAR FOR STRING 73

7.13.5 Mitigation Strategies

Static Analysis

Compliance with this rule can be checked using structural staticanalysis checkers using the following algorithm:

1. Traverse the AST

2. If a variable declaration, functions argument or typedef has astring base type report an error.

7.13.6 References

The ALE3D style guide section 16.2 states that C strings must beused instead of STL strings due to portability problems.

74 CHAPTER 7. LIST OF COMPASS CHECKERS

7.14 Comma Operator

The comma operator is commonly considered confusing without anyredeeming value. This checker makes sure that it is not used. Itreports any use of the built-in comma operator and any declarationof an overloaded comma operator.

7.14.1 Parameter Requirements

This checker does not require any parameters.

7.14.2 Non-Compliant Code Example

int f_noncompliant(int n){

return (n++, n++, n); // not OK (twice): comma operator}

7.14.3 Compliant Solution

int f_compliant(int n){

n++;n++;return n;

}

7.14.4 Mitigation Strategies

Static Analysis

Compliance with this rule can be checked using structural staticanalysis checkers identifying any appearance of the built-in commaoperator and any declaration of a function overloading the commaoperator.

7.14.5 References

A reference to this pattern is: The Programming Research Group:“High-Integrity C++ Coding Standard Manual”, Item 10.19: “Donot use the comma operator.”

7.15. [NO REFERENCE] COMPUTATIONAL FUNCTIONS 75

7.15 [No Reference] ComputationalFunctions

This analysis computes the amount of floating point, integer, floatingpoint pointer and integer pointer operations within each function. Ifthe value is larger than specified, than a warning is triggered. Theanalysis helps to identify functions with high computatuional value.

7.15.1 Non-Compliant Code Examples

void fail() {int x=4;int y=x+5+7;int *z = &x;y = *z+*z+6+8+9;

}

7.15.2 Compliant Solution

void pass() {int x= 4;int y = x+5+7;

}

7.15.3 Parameter Requirements

computationalFunctions.maxIntOps defines the maximum of inte-ger operations permitted. computationalFunctions.maxFloatOpsdefines the maximum of floating point operations permitted.

7.15.4 Implementation

The implementation checks for the following direct types:

• SgAddOp

• SgSubtractOp

• SgDivideOp

• SgMultiplyOp

The implementation checks for the following indirect types:

• SgCastExp - operations hidden behind cast

• SgVarRefExp - variable operations

• SgPointerDerefExp - pointer operations

• SgPntrArrRefExp - array operations

76 CHAPTER 7. LIST OF COMPASS CHECKERS

7.15.5 References

7.16. CONST CAST 77

7.16 Const Cast

Casting the constness away should never be done.

Casting away constness via const cast is just plain false advertising.If a member function’s signature is void someFunc(const foo& arg);then the function advertises to it’s clients that it will not call anynon-const member functions on the arg. Casting the constness ofarg away to allow the use of non-const member functions can createunexpected results for clients of this function.

7.16.1 Parameter Requirements

No paramaters are needed.

7.16.2 Implementation

The checker inspects every cast in the AST. If the type casted to isequal to the type casted from minus the const-modifier it is an error.

7.16.3 Non-Compliant Code Example

void foo(){const int x = 2;int y = (int) x;

}

7.16.4 Compliant Solution

void foo(){int x = 2;int y = x;

}

7.16.5 Mitigation Strategies

Static Analysis

Compliance with this rule can be checked using structural staticanalysis checkers using the following algorithm:

1. Traversee the AST

2. If a cast expression casts away constness report an error.

78 CHAPTER 7. LIST OF COMPASS CHECKERS

7.16.6 References

ALE3D Style Guide section 14.4.

7.17. SECURE CODING : STR05-A. PREFER MAKING STRING LITERALS CONST-QUALIFIED79

7.17 Secure Coding : STR05-A. Prefermaking string literals const-qualified

String literals are constant and should consequently be protected bythe const qualification. This recommendation supports rule STR30-C. Do not attempt to modify string literals .

7.17.1 Non-Compliant Code Example

In the following non-compliant code, the const keyword has beenomitted.

1 char *c = "Hello";2

If a statement such as c[0] = ’C’ were placed following the abovedeclaration, the code would likely still compile cleanly, but the re-sult of the assignment is undefined as string literals are consideredconstant.

7.17.2 Compliant Solution 1

In this compliant solution, the characters referred to by the pointerc are const-qualified, meaning that any attempts to assign them todifferent values is an error.

1 char const *c = "Hello";2

7.17.3 Compliant Solution 2

In cases where the string is meant to be modified, use initializationinstead of assignment. In this compliant solution, c is a modifi-able char array which has been initialized using the contents of thecorresponding string literal.

1 char c[] = "Hello";2

Thus, a statement such as c[0] = ’C’ is valid and will do what isexpected.

7.17.4 Non-Compliant Code Example 1

Although this code example is not compliant with the C99 Stan-dard, it executes correctly if the contents of CMUfullname are notmodified.

1 char *CMUfullname = "Carnegie Mellon University";2 char *school;3

80 CHAPTER 7. LIST OF COMPASS CHECKERS

4 /* Get school from user input and validate */56 if (strcmp(school, "CMU")) {7 school = CMUfullname;8 }9

7.17.5 Non-Compliant Code Example 2

Adding in the const keyword will likely generate a compiler warning,as the assignment of CMUfullname to school discards the constqualifier. Any modifications to the contents of school after thisassignment will lead to errors.

1 char const *CMUfullname = "Carnegie Mellon University";2 char *school;34 /* Get school from user input and validate */56 if (strcmp(school, "CMU")) {7 school = CMUfullname;8 }9

7.17.6 Compliant Solution

The compliant solution uses the const keyword to protect the stringliteral, as well as using strcpy() to copy the value of CMUfullnameinto school, allowing future modification of school.

1 char const *CMUfullname = "Carnegie Mellon University";2 char *school;34 /* Get school from user input and validate */56 if (strcmp(school, "CMU")) {7 /* Allocate correct amount of space for copy */8 strcpy(school, CMUfullname);9 }

10

7.17.7 Risk Assessment

Modifying string literals causes undefined behavior, resulting in ab-normal program termination and denial-of-service vulnerabilities.

Rule Severity Likelihood Remediation Cost Priority LevelSTR05-A 1 (low) 3 (likely) 2 (medium) P6 L3

Related Vulnerabilities

Search for vulnerabilities resulting from the violation of this rule onthe CERT website .

7.17. SECURE CODING : STR05-A. PREFER MAKING STRING LITERALS CONST-QUALIFIED81

http://www.open-std.org/jtc1/sc22/wg21/docs/papers/1993/N0389.asc[ISO/IEC 9899-1999:TC2 ] Section 6.7.8, ”Initialization” [Lock-heed Martin 2005] Lockheed Martin. Joint Strike Fighter AirVehicle C++ Coding Standards for the System Development andDemonstration Program. Document Number 2RDU00001, Rev C.December 2005. AV Rule 151.1

82 CHAPTER 7. LIST OF COMPASS CHECKERS

7.18 Constructor Destructor Calls Vir-tual Function

C++ Coding Standards, states that:

Virtual functions only “virtually” always behave virtu-ally: Inside constructors and destructrors, they don’t.Worse, any direct or indirect call to an unimplementedpure virtual function from a constructor or destructor re-sults in undefined behavior. If your design wants virtualdispatch into a derived class from a base class construc-tor or destructor, you need other techniques such as post-constructors.

7.18.1 Parameter Requirements

This checker takes no parameters and inputs source file

7.18.2 Implementation

This pattern is checked using a nested AST traversal in which thetop level traversal seeks out definitions of constructors and destruc-tors and two nested traversals seek out calls to virtual functions ofmember functions and non-member functions respectively.

7.18.3 Non-Compliant Code Example

The following code calls a virtual function from a public constructor.This is a contrived trivial example.

class Class{int n;

public:Class() { n = Classy(); } //constructor~Class() {} //Destructor

virtual int Classy() { return 1; }}; //class Class

int main(){Class c;return 0;

} //main()

7.18. CONSTRUCTOR DESTRUCTOR CALLS VIRTUAL FUNCTION 83

7.18.4 Compliant Solution

class Class{int n;

public:Class() { n = 1; } //constructor~Class() {} //Destructor

}; //class Class

int main(){Class c;return 0;

} //main()

7.18.5 Mitigation Strategies

Static Analysis

Compliance with this rule can be checked using structural staticanalysis checkers using the following algorithm:

1. Perform a AST traversal visiting class constructors and destruc-tors.

2. Flag any calls to virtual functions in class constructor or de-structor nodes.

3. Report any violations.

7.18.6 References

Alexandrescu A. and Sutter H. C++ Coding Standards 101 Rules,Guidelines, and Best Practices. Addison-Wesley 2005.

84 CHAPTER 7. LIST OF COMPASS CHECKERS

7.19 Control Variable Test AgainstFunction

This checker detects if there exists a for loop that tests its control(induction) variable against a function. One can get better perfor-mance by pulling out the function call before the loop and use aconstant value for the test. That is,

for(int i = 0; i < constSize(); ++i){ // do something }

The code above can be improved as the following:

const int size = constSize();for(int i = 0; i < size; ++i){ // do something }

7.19.1 Parameter Requirements

None

7.19.2 Implementation

This checker uses a simple traversal. For every for statement, thechecker examines whether or not there is a function call inside thetest expression.

7.19.3 Non-Compliant Code Example

int bar();

void foo(){int j=2;

for(int i = 0; i < bar(), j < 10; ++i){j += 2;

}}

7.19.4 Compliant Solution

int bar();

void foo()

7.19. CONTROL VARIABLE TEST AGAINST FUNCTION 85

{int j=2;

for(int i = 0; i < 10; ++i){j += 3;

}}

7.19.5 Mitigation Strategies

Static Analysis

Compliance with this rule can be checked using structural staticanalysis checkers using the following algorithm:

1. Check if a node is a for statement

2. Check if the test expression for the for statement contains afunction call

7.19.6 References

The Programming Research Group, High-Integrity C++ CodingStandard Manual, Item 5.7: “The control variable in a for loopshould be tested against a constant value, not a function”

86 CHAPTER 7. LIST OF COMPASS CHECKERS

7.20 Copy Constructor Const Arg

This checks whether the copy constructor for a class uses a constreference as an argument. This should always be the case as a copyconstructor should never change its input argument and a referenceis necessary to avoid needing a copy operator.

7.20.1 Parameter Requirements

No Parameter necessary.

7.20.2 Implementation

This checker begins by finding class declarations and getting theclass name. It then runs through each member of the class untilfinding a constructor. It checks if the constructor has one argumentand that argument is a member of the same class. If it is and it isnot const a message is returned.

7.20.3 Non-Compliant Code Example

class interviewer{interviewer(interviewer other) {return;}}

7.20.4 Compliant Solution

class interviewer{interviewer(const interviewer& other) {return;}}

7.20.5 Mitigation Strategies

Static Analysis

Compliance with this rule can be checked using structural staticanalysis checkers using the following algorithm:

1. Identify member function

2. check args for copy constructor

7.20. COPY CONSTRUCTOR CONST ARG 87

3. ensure type and const

4. if not both, return notification

7.20.6 References

Abbreviated Code Inspection Checklist Section 12.1.2, Copy Con-structor”

88 CHAPTER 7. LIST OF COMPASS CHECKERS

7.21 Cpp Calls Setjmp Longjmp

The Elements of C++ Style state that:

[The setjmp() and longjmp()] functions provide exceptionhandling for C programs. You cannot safely use thesefunctions in C++ code because the exception-handlingmechanism they implement does not respect normal objectlifecycle semantics–a jump will not result in destruction ofscoped, automatically allocated objects.

7.21.1 Parameter Requirements

This checker takes no parameters and inputs source file.

7.21.2 Implementation

This pattern is checked using a simple AST traversal that seeksout calls to setjmp() and longjmp() in source files without the “.c”extension. These nodes are flagged as violations.

7.21.3 Non-Compliant Code Example

This contrived trivial example calls setjmp() and longjmp() in C++code

#include <setjmp.h>

int main(){jmp_buf env;my_container c1;int i = setjmp(env);

if( i != 0 ) exit( 1 );

int err = c1.clear();

if( err != 0 ) longjmp( env, 1 );

return 0;}

7.21.4 Compliant Solution

The compliant solution uses C++ exception handling.

7.21. CPP CALLS SETJMP LONGJMP 89

int main(){my_container c1;

try{c1.clear();

}catch(...){exit( 1 );

}

return 0;}

7.21.5 Mitigation Strategies

Static Analysis

Compliance with this rule can be checked using structural staticanalysis checkers using the following algorithm:

1. Perform simple AST traversal visiting function reference codes.

2. Flag all function references named setjmp() or longjmp() asviolations.

3. Report all violations.

7.21.6 References

Bumgardner G., Gray A., and Misfeldt T. The Elements of C++Style. Cambridge University Press 2004.

90 CHAPTER 7. LIST OF COMPASS CHECKERS

7.22 Cycle Detection

This checker is a graph based checker. It determines if cycles arepresent in the crontrol flow graph.

7.22.1 Parameter Requirements

Parameters for the run must be provided, e.g. is the analysis inter-procedural? This is work in progress.

7.22.2 Implementation

Within the traversal of the graph, the run function of this checker iscalled. This function takes the current and previous node as input.Within the run function, the algorithm checks the successors of thecurrent node and determines if a node has been seen before duringthe graph traversal. If so, a possible cycle has been found. To verifythat a cycle exists, we verify that a path from the successor to thecurrent node exists.

7.22.3 Non-Compliant Code Example

% write your non-compliant code example

7.22.4 Compliant Solution

% write your compliant code example

7.22.5 Mitigation Strategies

Static Analysis

Compliance with this rule can be checked using structural staticanalysis checkers using the following algorithm:

1. Write your checker algorithm

7.22.6 References

7.23. PAPER: CYCLOMATIC COMPLEXITY 91

7.23 Paper: Cyclomatic Complexity

This is a checker to detect functions with high complexity. Highcomplexity is defined by Mc Cabe’s cyclomatic complexity metric.This metric measures the amount of branches in a function, i.e.through if and switch conditions.

7.23.1 Non-Compliant Code Examples

void fail() {int x;x=5;if (x>3) {}if (x>3) {}if (x>3) {}

}

7.23.2 Compliant Solution

void pass() {int x;x=5;if (x>3) {}

}

7.23.3 Parameter Requirements

CyclomaticComplexity.maxComplexity defines the max value for thecomplexity analysis.

7.23.4 Implementation

The algorithm searches for each function the number of occurancesof:

if (isSgIfStmt(node) || isSgCaseOptionStmt(node) || isSgForStatement(node) || isSgDoWhileStmt(node) || isSgWhileStmt(node)) {complexity++;

}

7.23.5 References

McCabe , “Thomas McCabe, A Complexity Measure - IEEE Trans-actions on Software Engineering, Vol SE-2, No.4, December 1976.”

92 CHAPTER 7. LIST OF COMPASS CHECKERS

7.24 Data Member Access

Following the spirit of data hiding in object-oriented programming,classes should in general not have public data members as thesemight give away details of the underlying implementation, makinga change of implementation more difficult and possibly giving usersa way to mess up the internal state of objects of the class. It is,however, sometimes useful to have ‘behaviorless aggregates’, i. e. C-style structs where all data members are public (and no memberfunctions are present).

This checker warns about class definitions that fit into neither of theabove patterns. Specifically, it warns about class definitions thatcontain both public and nonpublic data members.

7.24.1 Parameter Requirements

This checker does not require any parameters.

7.24.2 Non-Compliant Code Example

class NoNo { // not acceptable, contains both public and nonpublic data memberspublic:

int get_a() const;void set_a(int);

double d;

protected:int a;

};

7.24.3 Compliant Solution

struct C_style { // acceptable, all data members are publicint a, b;double d;

};

class WellProtected { // acceptable, no data members are publicpublic:

int get_a() const;void set_a(int);

double get_d() const;void set_d(double);

protected:

7.24. DATA MEMBER ACCESS 93

int a;

private:double d;

};

7.24.4 Mitigation Strategies

Static Analysis

Compliance with this rule can be checked using structural staticanalysis checkers using the following algorithm:

1. For each class definition, count the numbers of public and non-public data members.

2. If both of the counts for a given class definition are greater thanzero, a mix of public and nonpublic data members is present;emit a diagnostic.

7.24.5 References

A literature reference for this checker is: H. Sutter, A. Alexandrescu:“C++ Coding Standards””, Item 41: “Make data members private,except in behaviorless aggregates (C-style structs)”. Note that theauthors advise not only against public, but also against protecteddata members; this checker does not report protected data.

94 CHAPTER 7. LIST OF COMPASS CHECKERS

7.25 Deep Nesting

It is widely agreed that functions should not be ‘too big’ (without agood reason, at least). Various size measures exist, including sourcecode lines and cyclomatic complexity. This checker adds one more:It tests if function definitions contain more nested scopes than al-lowed by the user.

7.25.1 Parameter Requirements

This checker requires an integer entry DeepNest-ingChecker.maximumNestedScopes in the Compass parametersspecifying the maximum allowed number of nested scopes.

7.25.2 Non-Compliant Code Example

/* The innermost scope (the if statement) in this toy function will be* reported by the DeepNestingChecker if maximumNestedScopes is set to 2. */

void matrix_abs(int n, int m, int **matrix){

for (int i = 0; i < n; i++){

for (int j = 0; j < m; j++){

if (matrix[i][j] < 0){

matrix[i][j] = -matrix[i][j];}

}}

}

7.25.3 Compliant Solution

/* The nesting in each function is not greater than 2; the if statement has* been pulled out into its own function. */

void abs_if_necessary(int *p){

if (*p < 0){

*p = -*p;}

}

void matrix_abs2(int n, int m, int **matrix){

for (int i = 0; i < n; i++)

7.25. DEEP NESTING 95

{for (int j = 0; j < m; j++){

abs_if_necessary(&matrix[i][j]);}

}}

7.25.4 Mitigation Strategies

Static Analysis

Compliance with this rule can be checked using structural staticanalysis checkers using the following algorithm:

1. For each ‘scope statement’ (loops, if, basic blocks) count thenumber of enclosing scopes until a function definition is reached(if at all).

2. If the count is greater than the specified limit, emit a diagnostic.

7.25.5 References

A reference for this checker is: H. Sutter, A. Alexandrescu: “C++Coding Standards”, Item 20: “Avoid long functions. Avoid deepnesting”.

96 CHAPTER 7. LIST OF COMPASS CHECKERS

7.26 Default Case

This test checks to ensure each switch statement has a default option.It has been noted that unexpected cases ‘falling through” can be acause of difficult to detect bugs. A default case will catch thosecases.

7.26.1 Parameter Requirements

No parameters required.

7.26.2 Implementation

This implementation checks all statements in the basic block of theswitch statement, searching for defaults. Currently this implemen-tation may have false positives (ie. A switch with a default will raisean alert) on duff’s device. In general Duff’s device does not use adefault.

7.26.3 Non-Compliant Code Example

switch(x){case 1:...case 2:...}

7.26.4 Compliant Solution

switch(x){case 1:...case 2:...default://handle unexpected cases}

7.26. DEFAULT CASE 97

7.26.5 Mitigation Strategies

Static Analysis

Compliance with this rule can be checked using structural staticanalysis checkers using the following algorithm:

1. Identifies switch statement

2. Reads all statements in it’s basic block searching for default

3. if none found, notify message.

7.26.6 References

Abbreviated Code Inspection Checklist Section 11.2.2, Branching”

98 CHAPTER 7. LIST OF COMPASS CHECKERS

7.27 Default Constructor

The Elements of C++ Style item #97 states that

Declare a default constructor for every class you create.Although some compilers may be able to automaticallygenerate a more efficient implementation in some situ-ations, choose an explicit default constructor for addedclarity.

7.27.1 Parameter Requirements

This checker takes no parameters and inputs source file.

7.27.2 Implementation

This pattern is checked using a simple AST traversal that seeks outinstances of SgClassDefinition. The children of these instances arestored in a successor container and looped over to find a defaultconstructor. If no such default constructor exists then a violation isflagged.

7.27.3 Non-Compliant Code Example

The following trivial example does not declare a default constructor.

class Class{public:~Class(){}

}; //class Class

7.27.4 Compliant Solution

The compliant solution simply adds a default constructor to the classdefinition.

class Class{public:Class(){}~Class(){}

}; //class bad

7.27. DEFAULT CONSTRUCTOR 99

7.27.5 Mitigation Strategies

Static Analysis

Compliance with this rule can be checked using structural staticanalysis checkers using the following algorithm:

1. Perform AST traversal visiting the member functions of classdefinitions.

2. If no constructor is found for a single class definition then flagviolation.

3. Report any violations.

7.27.6 References

Bumgardner G., Gray A., and Misfeldt T. The Elements of C++Style. Cambridge University Press 2004

100 CHAPTER 7. LIST OF COMPASS CHECKERS

7.28 Discard Assignment

According to some coding standards, the assignment operator shouldnot be used within larger constructs, but only as a stand-alone ex-pression statement; in particular, it should not be used as the con-trolling expression in a branch because it might be confused with theequality operator. This checker reports any use of the assignmentoperator (built-in or overloaded) that is not the sole expression inan expression statement.

7.28.1 Parameter Requirements

This checker does not require any parameters.

7.28.2 Non-Compliant Code Example

void strcpy_noncompliant(char *dest, const char *source){

while (*dest++ = *source++);

}

7.28.3 Compliant Solution

void strcpy_compliant(char *dest, const char *source){

char last = *source;do {

last = *source;*dest++ = *source++;

} while (last != ’\0’);}

7.28.4 Mitigation Strategies

Static Analysis

Compliance with this rule can be checked using structural staticanalysis checkers using the following algorithm:

1. For each assignment, geneate a diagnostic if its parent is notan expression statement.

2. For each assignment that has an expression statement as itsparent, generate a diagnostic if that expression statement isthe controlling expression statement of a loop, if, or switch.

7.28. DISCARD ASSIGNMENT 101

7.28.5 References

A reference to this pattern is: The Programming Research Group:“High-Integrity C++ Coding Standard Manual”, Item 10.5: “Al-ways discard the result of an assignment operator.”

102 CHAPTER 7. LIST OF COMPASS CHECKERS

7.29 Do Not Assign Pointer To FixedAddress

This checker attempts to detect violations of MITRE’s CommonWeakness Enumeration (CWE) 587, “Assignment of a Fixed Ad-dress to a Pointer.” Pointer initializations of, and assignments to,constant values are detected. The goals of preventing this weaknessare to avoid insecure and/or non-portable code that makes unsafeassumptions about memory layout, such as locations of functions.

7.29.1 Parameter Requirements

There are no parameter requirements.

7.29.2 Implementation

The checker traverses the AST in prefix order, checking assignmentsand initializations in which the left hand side is a pointer (or arrayof pointers) and the right hand side is a non-zero constant (or anarray containing at least one such constant).

Not all cases are caught, for example, the following violation wouldnot necessarily be detected:

int return_const() { return 42; }

int main() {int* s = (int*) return_const();

// ...

return 0;}

7.29.3 Non-Compliant Code Example

The following illustrates a number of non-compliant examples, inwhich functions are assumed to exist at certain fixed addresses.

// fn ptr example direct from MITRE, except with added castint (*pt2fn_fixed_addr) (float, char, char) =(int (*)(float, char, char)) 0x08040000;

int (*pt2fn_fixed_addr_nocast)() = (int (*)()) 0x08040000;

int (*pt2fn_arith_addr) (float, char, char) =

7.29. DO NOT ASSIGN POINTER TO FIXED ADDRESS 103

(int (*)(float, char, char)) (0x08040000 + 0x200);

int (*pt2fn_assgn_fixed_addr) (float, char, char);pt2fn_assgn_fixed_addr = (int (*)(float, char, char)) 0x08040000;

// arrays of function pointers

typedef int (*fnptr)(void);fnptr f[2] = {(fnptr) 0x08010000,(fnptr) 0x08020000

};int (*pt2fn_array_fixed_addr[2])(void) = {(int (*)(void)) 0x08010000,(int (*)(void)) 0x08020000

};

typedef fnptr ind_fnptr;fnptr f_indirect[2] = {(fnptr) 0x08010000,(fnptr) 0x08020000

};

int (*pt2fn_arith_implicit_cast_addr) (float, char, char) =(int (*)(float, char, char)) 0x08010000 + 0x10;

int* pint_plus_zero = (int *) 0x2 + 0;

7.29.4 References

CWE-587

104 CHAPTER 7. LIST OF COMPASS CHECKERS

7.30 Do Not Call Putenv With Auto Var

The POSIX function putenv() is used to set environment variablevalues. The putenv() function does not create a copy of the stringsupplied to it as an argument, rather it inserts a pointer to the stringinto the environment array. If a pointer to a buffer of automaticstorage duration is supplied as an argument to putenv(), the memoryallocated for that buffer may be overwritten when the containingfunction returns and stack memory is recycled. This behavior isnoted in the Open Group Base Specifications Issue 6 [Open Group04]:

A potential error is to call putenv() with an automatic variable asthe argument, then return from the calling function while string isstill part of the environment.

The actual problem occurs when passing a pointer to an automaticvariable to putenv(). An automatic pointer to a static buffer wouldwork as intended.

7.30.1 Parameter Requirements

No Parameter specifications.

7.30.2 Implementation

The putenv() function is not required to be thread-safe, and the onein libc4, libc5 and glibc2.0 is not, but the glibc2.1 version is.

Description for libc4, libc5, glibc: If the argument string is of theform name, and does not contain an ‘=’ character, then the variablename is removed from the environment. If putenv() has to allo-cate a new array environ, and the previous array was also allocatedby putenv(), then it will be freed. In no case will the old storageassociated to the environment variable itself be freed.

The libc4 and libc5 and glibc 2.1.2 versions conform to SUSv2: thepointer argument given to putenv() is used. In particular, this stringbecomes part of the environment; changing it later will change theenvironment. (Thus, it is an error to call putenv() with a pointerto a buffer of automatic storage duration as the argument, thenreturn from the calling function while the string is still part of theenvironment.) However, glibc 2.0-2.1.1 differs: a copy of the stringis used. On the one hand this causes a memory leak, and on theother hand it violates SUSv2. This has been fixed in glibc2.1.2.

The BSD4.4 version, like glibc 2.0, uses a copy.

SUSv2 removes the ‘const’ from the prototype, and so does glibc2.1.3.

The FreeBSD implementation of putenv() copies the value of theprovided string, and the old values remain accessible indefinitely.

7.30. DO NOT CALL PUTENV WITH AUTO VAR 105

As a result, a second call to putenv() assigning a differently sizedvalue to the same name results in a memory leak.

7.30.3 Non-Compliant Code Example

In this non-compliant coding example, a pointer to a buffer of au-tomatic storage duration is used as an argument to putenv() [Dowd06]. The TEST environment variable may take on an unintendedvalue if it is accessed once func() has returned and the stack framecontaining env has been recycled.

Note that this example also violates rule [DCL30-C. Declare objectswith appropriate storage durations].

int func(char *var) {char env[1024];

if (snprintf(env, sizeof(env),"TEST=%s", var) < 0) {/* Handle Error */

}

return putenv(env);}

7.30.4 Compliant Solution

The setenv() function allocates heap memory for environment vari-ables. This eliminates the possibility of accessing volatile, stackmemory.

int func(char *var) {return setenv("TEST", var, 1);

}

7.30.5 Mitigation Strategies

Static Analysis

Compliance with this rule can be checked using structural staticanalysis checkers using the following algorithm:

1. Checks to see if the variable being passed to putenv() is declaredin the global scope. If it is not, the checker creates new output.

106 CHAPTER 7. LIST OF COMPASS CHECKERS

7.30.6 References

Open Group 04 The putenv() function

ISO/IEC9899-1999Section 6.2.4, ”Storage durations of objects,” andSection 7.20.3, “Memory management functions”

Dowd 06 Chapter 10, “UNIX Processes” (Confusing putenv() andsetenv())

7.31. DO NOT DELETE THIS 107

7.31 Do Not Delete This

“CERT Secure Coding C++ DAN32-C.” states that

Deleting this leaves it as a “dangling” pointer, which leadsto undefined behavior if it is accessed.

7.31.1 Parameter Requirements

This checker takes no parameters and inputs source file.

7.31.2 Implementation

This pattern is checked using a simple AST traversal visiting alldelete expressions and checking its argument to be a this expres-sion; if so, flag a violation.

7.31.3 Non-Compliant Code Example

class SomeClass {public:

SomeClass();void doSomething();void destroy();// ...

};

void SomeClass::destroy() {delete this; // Dangerous!!

}

SomeClass sc = new SomeClass;// ...sc->destroy();// ...sc->soSomething(); // Undefined behavior

7.31.4 Compliant Solution

class SomeClass {public:

SomeClass();void doSomething();// ...~SomeClass();

};

108 CHAPTER 7. LIST OF COMPASS CHECKERS

SomeClass sc = new SomeClass;// ...delete sc;

7.31.5 Mitigation Strategies

Static Analysis

Compliance with this rule can be checked using structural staticanalysis checkers using the following algorithm:

1. Perform simple AST traversal visiting all delete expressionnodes.

2. For each delete expression node, check its argument node tobe this expression; if so, flag violation.

3. Report any violations.

7.31.6 References

DAN32-C. Do not delete this

7.32. DO NOT USE C-STYLE CASTS 109

7.32 Do Not Use C-style Casts

C++ allows C-style casts, although it has introduced its own casts:

• static cast<type>(expression)

• const cast<type>(expression)

• dynamic cast<type>(expression)

• reinterpret cast<type>(expression)

C++ casts allow for more compiler checking and are easier to findin source code (either by tools or by human readers).

7.32.1 Parameter Requirements

No Parameter specifications.

7.32.2 Implementation

7.32.3 Non-Compliant Code Example

In this example, a C-style cast is used to convert an int to a double:

% write your non-compliant code exampleint dividend, divisor;// ...double result = ((double)dividend)/divisor;

7.32.4 Compliant Solution

Using the new cast, the division should be written as:

% write your compliant code exampledouble result = static_cast<double>(dividend)/divisor;

7.32.5 Mitigation Strategies

Static Analysis

Compliance with this rule can be checked using structural staticanalysis checkers using the following algorithm:

1. Check to see if the SgCastExp node is of type SgCast-Exp::e C style cast, and if it is, add ouput.

110 CHAPTER 7. LIST OF COMPASS CHECKERS

7.32.6 References

Dewhurst 03 Gotcha 40: Old-Style Casts

ISO/IEC 14882-2003 Sections 5.2.9, 5.2.11, 5.2.7, 5.2.10.

Meyers 96 Item 2: Prefer C++-style casts.

Lockheed Martin 05 AV Rule 185 C++ style casts (const cast, rein-terpret cast, and static cast) shall be used instead of the traditionalC-style casts.

7.33. DUFFS DEVICE 111

7.33 Duffs Device

This test checks for the presence of Duff’s Device in the source code.Duff’s Device is a switch statement containing a loop (for, whileor do-while; we do not check for goto loops) that contains one ofthe switch’s case or default labels. If such a construct is found, theposition of the switch statement is reported.

7.33.1 Parameter Requirements

This checker does not require any parameters.

7.33.2 Non-Compliant Code Example

// Duff’s Device in its almost original form.void send(int *to, int *from, int count){int n = (count+7) / 8;switch(count%8) {case 0: do { *to++ = *from++;case 7: *to++ = *from++;case 6: *to++ = *from++;case 5: *to++ = *from++;case 4: *to++ = *from++;case 3: *to++ = *from++;case 2: *to++ = *from++;case 1: *to++ = *from++;

} while (--n>0);}

}

7.33.3 Compliant Solution

// An equivalent function without optimization.void send2(int *to, int *from, int count){

for (int i = 0; i < count; i++)*to++ = *from++;

}

7.33.4 Mitigation Strategies

Static Analysis

Compliance with this rule can be checked using structural staticanalysis checkers using the following algorithm:

112 CHAPTER 7. LIST OF COMPASS CHECKERS

1. For each case or default statement, examine the enclosingscopes, smallest first (i.e. go upward in the AST).

2. If there is a loop statement that is closer than a switch state-ment, Duff’s Device has been found; emit a diagnostic.

7.33.5 References

Duff’s Device ist mostly folklore, but one reference in the litera-ture is: B. Stroustrup: “The C++ Programming Language, ThirdEdition”, Exercise §6.6[15].

7.34. DYNAMIC CAST 113

7.34 Dynamic Cast

The rule is that dynamic cast¡¿ should always be used when a down-cast is needed (ALE3D 14.5). Downcasting is a term for casting apointer to a base class to a derived class, and should only be donewith extreme care. Using dynamic cast¡¿ will ensure that the objectpointed to by the base class pointer is really of the derived class. Itwill return a nill pointer if it is not. Any other type of cast is unsafe.

7.34.1 Parameter Requirements

This checker does not take any paramaters.

7.34.2 Implementation

This pattern is detected using a simple traversal without inheritedor synthesized attributes.

7.34.3 Non-Compliant Code Example

class A//not polymorphic{public:~A(){}virtual void foo(){};

};

class B: public A{};

int main(){A * p = new B;B * p2 = (B*) p;

}

7.34.4 Compliant Solution

class A//not polymorphic{public:~A(){}

114 CHAPTER 7. LIST OF COMPASS CHECKERS

virtual void foo(){};};

class B: public A{};

int main(){A * p = new B;B * p2 = dynamic_cast<B* > (p);

}

7.34.5 Mitigation Strategies

Static Analysis

1. traverse AST

2. for each cast expression that is a downcast if dynamic cast isnot used report an error.

7.34.6 References

7.35. EMPTY INSTEAD OF SIZE 115

7.35 Empty Instead Of Size

While comparing the result of the size() member function on STLcontainers against 0 is functionally equivalent to calling the empty()member function, empty() is to be preferred as it is always aconstant-time operation, while size() on std::list may take lineartime. This checker detects cases where the result of size() is com-pared against the constant 0.

7.35.1 Parameter Requirements

This checker does not require any parameters.

7.35.2 Non-Compliant Code Example

#include <vector>

bool f(const std::vector<int> &v){

if (v.size() > 0) // not OK: use !v.empty() insteadreturn true;

if (0 == v.size()) // not OK: use v.empty() insteadreturn false;

return false;}

7.35.3 Compliant Solution

#include <vector>bool f2(const std::vector<int> &v){

if (!v.empty())return true;

if (v.empty())return false;

return false;}

7.35.4 Mitigation Strategies

Static Analysis

Compliance with this rule can be checked using structural staticanalysis checkers using the following algorithm:

1. For each member function call, see if the called member func-tion is named ‘size’ and if the call is embedded in an expressionthat compares its return value against the constant 0.

116 CHAPTER 7. LIST OF COMPASS CHECKERS

2. If the above check evaluates to true, emit a diagnostic.

There are numerous ways to defeat this simple analysis, for instanceby assigning the return value from size() to a variable, by comparingthe return value against a variable that is always 0, or by callingsize() through a member function pointer. Further, the analysisonly looks for member functions named ‘size’ but does not try toascertain that it belongs to a ‘container’ (as that is not somethingthat can be checked reliably).

7.35.5 References

The reference for this checker is: S. Meyers: “Effective STL”, Item 3:“Call empty instead of checking size() against zero.”

7.36. ENUM DECLARATION NAMESPACE CLASS SCOPE 117

7.36 Enum Declaration NamespaceClass Scope

The Elements of C++ Style item #79 states that

To avoid symbolic name conflicts between enumeratorsand other global names, nest enum declarations withinthe most closely related class or common namespace.

7.36.1 Parameter Requirements

This checker takes no parameters and inputs source file.

7.36.2 Implementation

This pattern is checked using a simple AST traversal that locatesnodes that are enumeration declarations. If a enumeration decla-ration is found then its parent nodes are traversed until a class ornamespace declaration is found. If no namespace or class declara-tion(s) are found then a violation is flagged by this checker.

7.36.3 Non-Compliant Code Example

This non-compliant code contains an enum declaration at the globalscope.

enum violation{ E1=0, E2, E3 }; // This is a violation

7.36.4 Compliant Solution

The compliant solution simply nests the violation enum declarationin a unique namespace.

namespace Namespace{enum violation{ E1=0, E2, E3 }; // This is OK

} //namespace Namespace

7.36.5 Mitigation Strategies

Static Analysis

Compliance with this rule can be checked using structural staticanalysis checkers using the following algorithm:

1. Perform an AST traversal visiting enum declaration nodes.

118 CHAPTER 7. LIST OF COMPASS CHECKERS

2. For each enum declaration node visit its parents checking themto be either namespace declarations or class declarations. If noclass or namespace declaration parent node is found, then flagviolation.

3. Report any violations.

7.36.6 References

Bumgardner G., Gray A., and Misfeldt T. The Elements of C++Style. Cambridge University Press 2004.

7.37. CERT-DCL04-A: EXPLICIT CHAR SIGN 119

7.37 CERT-DCL04-A: Explicit CharSign

“CERT Secure Coding INT07-A” states

The three types char, signed char, and unsigned charare collectively called the character types. Compilershave the latitude to define char to have the same range,representation, and behavior as either signed char orunsigned char. Irrespective of the choice made, char isa separate type from the other two and is not compatiblewith either.

7.37.1 Parameter Requirements

This checker takes no parameters and inputs source file.

7.37.2 Implementation

This pattern is checked using a simple AST traversal visiting allSgAssignInitializer nodes. If the SgAssignInitializer node is of typechar and the operand of the node is a SgCastExp of type int or isa SgCharVal whose value is negative then flag an error.

7.37.3 Non-Compliant Code Example

This non-compliant example declares a simple char type variable.

#include <stdio.h>

int main(){int n = 200;char c1 = ’i’;char c2 = n;char c3 = 200;int i = 1000;

printf( "%c/c2 = %d\n%c/c3 = %d\n", c1, i/c2, c1, i/c3);

return 0;}

7.37.4 Compliant Solution

The compliant solution explicitly declares the char variables asunsigned.

120 CHAPTER 7. LIST OF COMPASS CHECKERS

#include <stdio.h>

int main(){int n = 200;char c1 = ’i’;unsigned char c2 = n;unsigned char c3 = 200;int i = 1000;

printf( "%c/c2 = %d\n%c/c3 = %d\n", c1, i/c2, c1, i/c3);

return 0;}

7.37.5 Mitigation Strategies

Static Analysis

Compliance with this rule can be checked using structural staticanalysis checkers using the following algorithm:

1. Perform simple AST traversal visiting all SgAssignInitializernodes.

2. For each SgAssignInitializer node of type char, if the rhsoperand is either a cast expression with operand of type intor a negative character value then flag an error.

3. Report any violations.

7.37.6 References

Secure Coding : INT07-A. Explicitly specify signed or unsigned forcharacter types

7.38. EXPLICIT COPY 121

7.38 Explicit Copy

This test detects missing copy constructors and operators. In casethe user wants to use the default ones then the class has to be anno-tated with a special comment. These comments should contain “usedefault copy constructor” or “use default copy operator”.

This checker enforces the rule 53 from H. Sutter, A. AlexandrescuC++ Coding Standards: “Explicitly enable or disable copying”.

7.38.1 Parameter Requirements

No parameter is required.

7.38.2 Non-Compliant Code Example

class A {};

7.38.3 Compliant Solution

class A {public:A(const A& other) {

}A& operator=(const A& other) {return this;

}};

7.38.4 Mitigation Strategies

Static Analysis

Compliance with this rule can be checked using structural staticanalysis checkers using the following algorithm:

1. For all class definitions, try to find a copy constructor anda copy operator, or user comments describing that the classshould use the default ones.

7.38.5 References

Alexandrescu A. and Sutter H. C++ Coding Standards 101 Rules,Guidelines, and Best Practices. Addison-Wesley 2005.

122 CHAPTER 7. LIST OF COMPASS CHECKERS

7.39 Explicit Test For Non BooleanValue

This test examines all the test statements whether there is a state-ment that calls a function call returning a non-boolean value andthat does not compare the return value to an explicit value. Forexample, if a function foo() returns an integer value and the func-tion is used in a conditional statement, such as "if", "while","do-while", "for", or the first operand of ”?” operator, theboolean expressions in the conditional statement should always usean explicit test of equality or non-equality. Therefore the followingcode can pass this checker:

if(foo()!=0){// do something}

whereas,

if(foo()){// do something}

will be caught by this checker because foo() returns an integer,non-boolean value.

7.39.1 Parameter Requirements

None

7.39.2 Implementation

This pattern is detected using a simple traversal. It traverses ASTto search conditional statements and if an implicit expression is usedin the test, AST contains a casting expression node underneath theconditional statement to convert from a non-boolean values to aboolean value. The checker captures this structure.

7.39.3 Non-Compliant Code Example

int bar();

void foo(){int i;if(bar())i = 2;

7.39. EXPLICIT TEST FOR NON BOOLEAN VALUE 123

while(bar())i = 3;

do {i = 4;

} while(bar());

for(i=0; bar(); i++)i =5;

i = (bar() ? 6 : 7);

for(i = (bar() ? 8 : 9); bar(); i++)i = 10;

}

7.39.4 Compliant Solution

if(foo()!=0){// do something}

7.39.5 Mitigation Strategies

Static Analysis

Compliance with this rule can be checked using structural staticanalysis checkers using the following algorithm:

1. Check if a node is a conditional statement

2. Check further if the conditional statement contains an implicitexpression.

7.39.6 References

The Programming Research Group, High-Integrity C++ CodingStandard Manual, Item 5.2: “For boolean epressions(’if’, ’for’,’while’, ’do’ and the first operand of the ternary operator ’?:’) in-volving non-boolean values, always use an explicit test of equalityor non-equality.”

124 CHAPTER 7. LIST OF COMPASS CHECKERS

7.40 File Read Only Access

Attempting to open files for writing on read-only file systems andfiles causes errors. This checker checks that all standard C/C++ fileI/O is read-only. This checker is normally used only internally forcompass verify.

7.40.1 Parameter Requirements

This checker takes no parameters and inputs source file.

7.40.2 Implementation

This pattern is checked using a simple AST traversal visiting allfunction call expressions calling the function fopen. The mode pa-rameter to fopen is checked to be either “r” or “rb” only. Anyparameter that violates this restriction is flagged as an error. Addi-tionally, all variable declarations of type fstream and ofstream areforbidden by this checker.

7.40.3 Non-Compliant Code Example

#include <fstream>#include <stdio.h>

int main(){FILE *f1 = fopen( "f1.txt", "w" );std::fstream f2( "f2.txt", std::ios::app | std::ios::out );

FILE *f1r = fopen( "f1.txt", "r" );std::ifstream f2r( "f2.txt", std::ios::in );

return 0;}

7.40.4 Compliant Solution

Do not write to file.

7.40.5 Mitigation Strategies

Static Analysis

Compliance with this rule can be checked using structural staticanalysis checkers using the following algorithm:

7.40. FILE READ ONLY ACCESS 125

1. Perform simple AST traversal on all function call expressionscalling the fopen function.

2. Check the mode parameter of fopen to be either “r” or “rb”;if not, then flag violation.

3. Perform simple AST traversal on all variable declarations of thetype fstream or ofstream. Forbid the use of these declarationsand mark them as violations.

4. Report all violations.

7.40.6 References

126 CHAPTER 7. LIST OF COMPASS CHECKERS

7.41 Float For Loop Counter

“CERT Secure Coding” states

Floating point arithmetic is inexact and is subject torounding errors. Hence, floating point variables shouldnot be used as loop counters.

7.41.1 Parameter Requirements

This checker takes no parameters and inputs source file.

7.41.2 Implementation

This pattern is checked using a simple AST traversal that visitsall for loop init statement nodes and checks the type of its countervariable declaration. If that type is float or double then flag aviolation.

7.41.3 Non-Compliant Code Example

for (float count = 0.1f; count <= 1; count += 0.1f){}

7.41.4 Compliant Solution

The compliant solution uses an int type loop counter.

for (int count = 1; count <= 10; count += 1){}

7.41.5 Mitigation Strategies

Static Analysis

Compliance with this rule can be checked using structural staticanalysis checkers using the following algorithm:

1. Perform simple AST traversal visiting all for loop initializationstatement nodes.

2. For each node check the type of its variable declaration. If typeis float or double then flag violation.

3. Report any violations.

7.41. FLOAT FOR LOOP COUNTER 127

7.41.6 References

FLP31-C. Do not use floating point variables as loop counters

128 CHAPTER 7. LIST OF COMPASS CHECKERS

7.42 Floating Point Exact Comparison

This checker detects a test clause that compares a variable to afloating point value. The rationale for this checker is, floating pointrepresentations are platform dependent, so it is necessary to avoidexact comparisons.

7.42.1 Parameter Requirements

None.

7.42.2 Implementation

This checker is implemented with a simple AST traversal. It tra-verses AST and finds a test clause. If the test clause has a doublevalue on either left-hand-side or right-hand-side, and if the opera-tor used for the test is ”==” or ”!=”, then the checker reports thisclause.

7.42.3 Non-Compliant Code Example

void foo( double f ){if ( f == (float)3){f = 1.234;}

while(f != 1.23456){f += 0.00001;}

do{f += 0.000001;} while ( f != 1.234567);

for(f = 1.234567; f != 1.2345678; f += 0.0000001){int i = f + 1;}}

7.42.4 Compliant Solution

bool double_equal(const double a, const double b)

7.42. FLOATING POINT EXACT COMPARISON 129

{const bool equal = fabs(a-b) < numeric_limits<double>::epsilon;return equal;}

void foo(double f){if(double_equal(f, 3.142)){// do something}}

7.42.5 Mitigation Strategies

Static Analysis

Compliance with this rule can be checked using structural staticanalysis checkers using the following algorithm:

1. Check if a node is a test clause

2. Check further if the clause has a double value and if the test isfor (in)equality.

7.42.6 References

The Programming Research Group, High-Integrity C++ CodingStandard Manual, “Item 10.15: Do not write code that expects float-ing point calculations to yield exact results”.

130 CHAPTER 7. LIST OF COMPASS CHECKERS

7.43 Fopen Format Parameter

“CERT Secure Coding FIO11-A” states

The C standard specifies specific strings to use for themode for the function fopen(). An implementation maydefine extra strings that define additional modes, but onlythe modes in the following table (adapted from the C99standard) are fully portable and C99 compliant:

1. r2. w3. a4. rb5. wb6. ab7. r+8. w+9. a+

10. r+b or rb+11. w+b or wb+12. a+b or ab+

7.43.1 Parameter Requirements

This checker takes no parameters and inputs source file.

7.43.2 Implementation

This pattern is checked using a simple AST traversal that visitsall function call expressions. For each function call expression thefunction name is confirmed to be fopen() then the format parameteris checked against the list of specified strings. If the given parameteris not a standard format string then a violation is flagged.

7.43.3 Non-Compliant Code Example

#include <stdio.h>

int main(){FILE *f = fopen( "/tmp/tmp.txt", "wr" );

fclose( f );

return 0;}

7.43. FOPEN FORMAT PARAMETER 131

7.43.4 Compliant Solution

The compliant solution uses the “r+” specified parameter string in-stead.

#include <stdio.h>

int main(){FILE *f = fopen( "/tmp/tmp.txt", "r+" );

fclose( f );

return 0;}

7.43.5 Mitigation Strategies

Static Analysis

Compliance with this rule can be checked using structural staticanalysis checkers using the following algorithm:

1. Perform simple AST traversal visiting all function call expres-sion nodes.

2. For each function call expression node, unparse node string thento determine the function name and parse the format parame-ter.

3. Check the format parameter against list of standard values. Ifgiven format parameter does not conform to list of specifiedvalues, then flag violation.

4. Report any violations.

7.43.6 References

Secure Coding : FIO11-A. Take care when specifying the mode pa-rameter of fopen()

132 CHAPTER 7. LIST OF COMPASS CHECKERS

7.44 For Loop Construction ControlStmt

“ALE3D Coding Standards & Style Guide” item #6.1 states that

for() construction loops must only include statements thatcontrol the loop. In particular, for() loops must not initial-ize or increment/decrement variables not directly relatedto the loop control.

7.44.1 Parameter Requirements

This checker takes no parameters and inputs the source file.

7.44.2 Implementation

This pattern is checked using a simple AST traversal that seeks outfor loop statement constructs. A list of variables set in the initializa-tion block is generated. A list of variables set in the increment/decre-ment block is generated. Any variable in the increment/decrementlist of variables must be in the initialization list of variables.

7.44.3 Non-Compliant Code Example

This non-compliant code initializes the array inside the for() controlstatement.

#include <stdlib.h>

int main(){int *array = (int*)malloc( 100*sizeof(int) );int j=100;

for( int i = 0; i < 100; i++, j-- ){array[i] = j;

}

free(array);return 0;

} //main()

7.44.4 Compliant Solution

The compliant solution simply moves the array initialization insidethe for() loop body.

7.44. FOR LOOP CONSTRUCTION CONTROL STMT 133

#include <stdlib.h>

int main(){int *array = (int*)malloc( 100*sizeof(int) );

for( int i = 0; i < 100; i++ ){array[i] = i;

}

free(array);return 0;

} //main()

7.44.5 Mitigation Strategies

Static Analysis

Compliance with this rule can be checked using structural staticanalysis checkers using the following algorithm:

1. Perform simple AST traversal visiting all for statements.

2. Generate a list of variables set in the initialization block.

3. Generate a list of variables set in the increment/decrementblock.

4. Report any variable in the increment/decrement list of variablesthat are not in the initialization list of variables as a violation

7.44.6 References

Arrighi B., Neely R., Reus J. “ALE3D Coding Standards & StyleGuide”, 2005.

134 CHAPTER 7. LIST OF COMPASS CHECKERS

7.45 For Loop Cpp Index Variable Dec-laration

“ALE3D Coding Standards & Style Guide” Item #6.2 states that

C++ loop index variables should be declared in the loopstatement. Declaration of a loop index variable in thefirst clause of the for() statement ensures that its scope islimited to the loop body.

7.45.1 Parameter Requirements

This checker takes no parameters and inputs source file.

7.45.2 Implementation

This pattern is checked using a simple AST traversal that seeksSgForInitStatements that have NULL declaration statements. Thesenodes are flagged as violations.

7.45.3 Non-Compliant Code Example

This non-compliant code declares the loop control variable outsidethe loop statement.

int main(){int i = 0;for( i = 0; i < 100; i++ ){}

return 0;} //main()

7.45.4 Compliant Solution

The compliant solution declares the index variable inside the loopstatement.

int main(){for( int i = 0; i < 100; i++ ){}

return 0;} //main()

7.45. FOR LOOP CPP INDEX VARIABLE DECLARATION 135

7.45.5 Mitigation Strategies

Static Analysis

Compliance with this rule can be checked using structural staticanalysis checkers using the following algorithm:

1. Perform simple AST traversal visiting all declaration statementnodes.

2. For each declaration statement node, if parent node is for loopinitialization statement then flag violation.

3. Report any violations.

7.45.6 References

Arrighi B., Neely R., Reus J. “ALE3D Coding Standards & StyleGuide”, 2005.

136 CHAPTER 7. LIST OF COMPASS CHECKERS

7.46 Forbidden Functions

Many checks common to Compass center around the forbidden useof certain “dangerous” functions. This checker provides a way toforbid the use of those functions through the simple use of theirname.

7.46.1 Parameter Requirements

The forbidden function checker can simultaneously look for any num-ber of functions, either member or non-member. A set of parame-ters is used, named using a counter. Thus, the parameters of thischecker have names of the form ForbiddenFunctions.Functionn,for n from zero to some limit. The forbidden function anal-ysis checks each name in turn until one is missing. Thus,if you have parameters named ForbiddenFunctions.Function0and ForbiddenFunctions.Function1 but no parameter namedForbiddenFunctions.Function2, the analysis will search for twofunctions. As a caution, if you skip a number, including zero,no larger numbers will be scanned: any functions specified aftera skipped number will be ignored.

The format of a parameter is white space, function name,white space, comma, reason. Leading and trailing white spaceis allowed next to the function name, but any white space after thefirst comma will become part of the reason string. The functionname is a fully qualified name, but the leading :: to indicate theglobal scope may be omitted. Member functions are given with theirclass qualifications, just as they would be referred to when access-ing a pointer to them. Choosing one overload from an overload setsharing the same name is not supported. The reason field is used toindicate why a particular function is forbidden; it may be any string(not containing a newline), and is printed out as part of the errormessage when the corresponding function is found. It is also possibleto omit the comma and the reason field, leaving just the functionname as the parameter; in this case, no reason will be given for thefunction’s prohibition.

7.46.2 Implementation

This pattern is checked using a simple AST traversal visiting allSgFunctionCallExp nodes. For each node the name of the functionbeing called is compared to those listed as forbidden functions. Ifa match is found between the function call name and the forbiddenfunction name then flag an error.

7.46. FORBIDDEN FUNCTIONS 137

7.46.3 Non-Compliant Code Example

In this example, it is assumed that the functioncompass forbidden function vfork is forbidden by the pa-rameter file.

//compass_forbidden_function_vfork() is a function meant to simulate a system//routine. This makes no difference as an example of how forbiddenFunctions//checks errors as it works only on function names. The reason we have used//this example is to prevent compass from treating this test file as an error//during ‘make verify’ in which compass checks its own source code.

int compass_forbidden_function_vfork();void helloWorld(int, char**);

double function();double good_function();

namespace A {double function2();

}

struct B {void memberFunction();

};

int main(int argc, char** argv) {int w;w = compass_forbidden_function_vfork() + 5;helloWorld(argc, argv);double x = 3.0 * function();double y = 5.0 * good_function();double z = A::function2();B b;b.memberFunction();int (*fp)() = compass_forbidden_function_vfork;return 0;

}

7.46.4 Compliant Solution

The compliant example would use a function not listed in the pa-rameter file.

138 CHAPTER 7. LIST OF COMPASS CHECKERS

7.46.5 Mitigation Strategies

Static Analysis

Compliance with this rule can be checked using structural staticanalysis checkers using the following algorithm:

1. For each SgFunctionCallExp node if the name of the functionbeing called is forbidden by the parameter file then report error.

7.46.6 References

Foster , “James C.Foster, Vitaly Osipov, Nish Bhalla, Niels Heinen,Buffer Overflow Attacks, ISBN 1-932266-67-4, p. 211”

Secure Coding : MSC30-C. Do not use the rand function

Secure Coding : POS33-C. Do not use vfork()

[ ISO/IEC 9899-1999:TC2 ] Section 7.19.9.2, ”The fseek function”;7.19.9.5, ”The rewind function”

[ Klein 02 ] [ISO/IEC 9899-1999 ] Section 7.20.1.4, ”The strtol, strtoll, strtoul,and strtoull functions,” Section 7.20.1.2, ”The atoi, atol, and atollfunctions,” and Section 7.19.6.7, ”The sscanf function”

7.47. FRIEND DECLARATION MODIFIER 139

7.47 Friend Declaration Modifier

The Elements of C++ Style item #96 states that

Friend declarations are often indicative of poor design be-cause they bypass access restrictions and hide dependen-cies between classes and functions.

7.47.1 Parameter Requirements

This checker takes no parameters and inputs source file.

7.47.2 Implementation

This pattern is checked with a simple AST traversal that seeks dec-laration statements and determines if any use the “friend” modifierkeyword. Any declaration statements found with the “friend” mod-ifier are flagged as violations.

7.47.3 Non-Compliant Code Example

This non-compliant example uses “friend” to access private data.

class Class{int privateData;friend int foo( Class & c );

public:Class(){ privateData=0; }

}; //class Class

int foo( Class & c ){return c.privateData + 1;

} //foo( Class & c )

7.47.4 Compliant Solution

The compliant solution simply uses an accessor function instead.

class Class{int privateData;

public:Class(){ privateData=0; }

140 CHAPTER 7. LIST OF COMPASS CHECKERS

int getPrivateData(){ return privateData; }}; //class Class

int foo( Class & c ){return c.getPrivateData() + 1;

} //foo( Class & c )

7.47.5 Mitigation Strategies

Static Analysis

Compliance with this rule can be checked using structural staticanalysis checkers using the following algorithm:

1. Perform simple AST traversal and visit all declaration state-ment nodes

2. For each declaration statement check the “friend” modifier. If“friend” modifier is set then flag violation.

3. Report any violations.

7.47.6 References

Bumgardner G., Gray A., and Misfeldt T. The Elements of C++Style. Cambridge University Press 2004.

7.48. FUNCTION CALL ALLOCATES MULTIPLE RESOURCES 141

7.48 Function Call Allocates MultipleResources

“CERT Secure Coding RES30-C” states

Allocating more than one resource in a single statementcould result in a memory leak, and this could lead to adenial-of-service attack.

7.48.1 Parameter Requirements

This checker takes no parameters and inputs source file.

7.48.2 Implementation

This pattern is checked using a simple AST traversal on each Sg-FunctionCallExp node. For each node get the expression list of itsarguments and check if any such argument expressions are the newkeyword. If the number of new expressions exceeds one then flag anerror.

7.48.3 Non-Compliant Code Example

class A{};

class B{};

int foo( A *a, B *b ){return 0;

}

int main(){A *a = new A;B *b = new B;int i = foo( a, b ); //ok...

return foo( new A, new B ); //bad}

142 CHAPTER 7. LIST OF COMPASS CHECKERS

7.48.4 Compliant Solution

See the call to foo above.

7.48.5 Mitigation Strategies

Static Analysis

Compliance with this rule can be checked using structural staticanalysis checkers using the following algorithm:

1. Traverse all SgFunctionCallExp nodes

2. For each node get the list of argument expressions

3. Count the number of new keyword argument expressions

4. If the number of new keyword argument expressions exceedsone then flag an error.

5. Report all violations.

7.48.6 References

RES30-C. Never allocate more than one resource in a single state-ment

7.49. CERT-DCL31-C: FUNCTION DEFINITION PROTOTYPE 143

7.49 CERT-DCL31-C: Function Defini-tion Prototype

“CERT Secure Coding DCL31-C” states

Functions should always be declared with the appropriatefunction prototype. If a function prototype is not avail-able, the compiler cannot perform checks on the numberand type of arguments being passed to functions. Argu-ment type checking in C is only performed during com-pilation, and does not occur during linking, or dynamicloading.

7.49.1 Parameter Requirements

This checker takes no parameters and inputs source file.

7.49.2 Implementation

This pattern is checked using a simple AST traversal of functiondeclaration nodes. For each function declaration node find the firstnon-defining function declaration; if none is found, then flag viola-tion.

7.49.3 Non-Compliant Code Example

This example foo() has no prototype.

int foo( int i ){return i;

}

int main(){return foo(0);

}

7.49.4 Compliant Solution

The compliant solution simply adds a function prototype for foo()

int foo(int);

int foo( int i ){

144 CHAPTER 7. LIST OF COMPASS CHECKERS

return i;}

int main(){return foo(0);

}

7.49.5 Mitigation Strategies

Static Analysis

Compliance with this rule can be checked using structural staticanalysis checkers using the following algorithm:

1. Perform a simple AST traversal of code visiting all functiondeclaration nodes.

2. For each function declaration node, find first non-defining dec-laration. If no non-defining declaration is found, then flag vio-lation.

3. Report any violations detected.

7.49.6 References

Secure Coding : DCL31-C. Ensure every function has a functionprototype

7.50. PAPER: FUNCTION DOCUMENTATION 145

7.50 Paper: Function Documentation

This analysis detects all non-compiler generated functions andchecks whether they are documented. The documentation must bein front of the function.

7.50.1 Non-Compliant Code Examples

void fail() {// this function has no comment in front of it

}

7.50.2 Compliant Solution

//Your test file code goes here.void succeed() {}

7.50.3 Parameter Requirements

None.

7.50.4 Implementation

This analysis checks for both ’//’ and ’/*’ documentation.

7.50.5 References

Panas05 , “Thomas Panas, Rudiger Lincke, Jonas Lundberg, WelfLowe, A Qualitative Evaluation of a Software Development and Re-Engineering Project, NASA/IEEE Software Engineering Workshop,Washington DC, USA, April 2005”

146 CHAPTER 7. LIST OF COMPASS CHECKERS

7.51 Induction Variable Update

This test finds the location in loops (for, do-while, while) whereinduction variables is updated (through arithmetic operations).

7.51.1 Parameter Requirements

None.

7.51.2 Implementation

This pattern is detected using a simple traversal. It traverses ASTto obtain information about induction variables and to locate state-ments that assign a new value to the induction variables. However,this checker does not track pointers whether or not the pointers ac-tually update induction variables. In addition, function calls thatmay update induction variables are not considered here, either.

7.51.3 Non-Compliant Code Example

void foo(){int i;int j = 0;int k = 0;

for(i = 0; i != 10; ++i){if( 0 == i % 3){i = 3;++i;i++;

}}

while(j < 10){if(1 == j %3){j = j + 2;

}j++;

}

do {if(2 == k % 3){

7.51. INDUCTION VARIABLE UPDATE 147

k +=1;}

} while(++k < 10);}

7.51.4 Compliant Solution

% write your compliant code example

7.51.5 Mitigation Strategies

Static Analysis

Compliance with this rule can be checked using structural staticanalysis checkers using the following algorithm:

1. Find a loop and detect its induction variable

2. Check if the variable is updated inside the loop, by examiningits loop body.

7.51.6 References

The Programming Research Group, High-Integrity C++ CodingStandard Manual, Item 5.6: “Do not alter a control variable morethan once in a for, do or while statement.”

148 CHAPTER 7. LIST OF COMPASS CHECKERS

7.52 Internal Data Sharing

Classes should usually not return handles to internal data frommethods. A ‘handle’ in this sense is a non-const reference to a mem-ber or copy of a pointer member, as the caller could change internalstate through such an object. This checker reports such cases. Onepossible exception to this rule are overloaded operators, which oftenreturn such handles (so they can be combined with other opera-tors to bigger expressions), and this checker provides a parameter todefine whether operators should be allowed to return internals.

7.52.1 Parameter Requirements

The bool flag InternalDataSharing.operatorsExcepted stateswhether overloaded operators are excepted from this checker’s rules,i.e. whether they are allowed to return internal data.

7.52.2 Non-Compliant Code Example

class A{public:

// not OK: returning non-const pointer memberint *retptr() { return p; }// not OK: returning non-const reference to data pointed to by memberint &retref() { return *p; }// not OK: returning non-const reference to memberint *&retptrref() { return p; }

private:int *p;

};

7.52.3 Compliant Solution

class B{public:

// OK: returning copy of pointed-to dataint retint() { return *p; }// OK: const ptrconst int *retcptr() { return p; }// OK: const refconst int &retcref() { return *p; }

// maybe OK, depending on "operatorsExcepted" parameterint &operator*() { return *p; }

7.52. INTERNAL DATA SHARING 149

private:int *p;

};

7.52.4 Mitigation Strategies

Static Analysis

Compliance with this rule can be checked using structural staticanalysis checkers using the following algorithm:

1. While traversing the program representation, set a flag uponentering a member function definition that has a non-constpointer or reference return type.

2. Report any return statement within such a flagged functionthat returns a (possibly dereferenced) member variable.

7.52.5 References

A reference in the literature is: H. Sutter, A. Alexandrescu: “C++Coding Standards”, Item 42: “Don’t give away your internals”.Their notion of a handle is more general, however, as it also in-cludes basic types that are used as handles, such as ints that areused as file descriptors.

150 CHAPTER 7. LIST OF COMPASS CHECKERS

7.53 [No Reference] : Loc Per Function

This analysis detects for each function the amount of lines of code(LOC) and checks the value against a user defined max value. IfLOC > max value, then an exception is triggered.

7.53.1 Non-Compliant Code Examples

// if LocPerFunction.Size = 2void fail() {int x;x = 5;x = 5;x = 5;

}

7.53.2 Compliant Solution

// if LocPerFunction.Size = 2void pass() {int x;x = 5;x = 5;

}

7.53.3 Parameter Requirements

LocPerFunction.Size defines the max value for a permissive LOC.

7.53.4 Implementation

The simple implementation of this checker is defined below:

if (isSgFunctionDeclaration(sgNode)) {SgFunctionDeclaration* funcDecl = isSgFunctionDeclaration(sgNode);SgFunctionDefinition* funcDef = funcDecl->get_definition();if (funcDef) {Sg_File_Info* start = funcDef->get_body()->get_startOfConstruct();Sg_File_Info* end = funcDef->get_body()->get_endOfConstruct();ROSE_ASSERT(start);ROSE_ASSERT(end);int lineS = start->get_line();int lineE = end->get_line();loc_actual = lineE-lineS;if (loc_actual>loc) {output->addOutput(new CheckerOutput(funcDef));

7.53. [NO REFERENCE] : LOC PER FUNCTION 151

}}

}

7.53.5 References

152 CHAPTER 7. LIST OF COMPASS CHECKERS

7.54 Localized Variables

This checker looks for variable declarations and try to determine ifthe first use is far from the declaration. There can be two wayswhere the use is far. Either it is used only in an inner scope. Thenthe declaration can be moved in that scope. Or the it is used notdirectly after the block of declaration the variables is from. Thenthe declaration should be moved down.

This checker try to check for item 18 of C++ Coding Standards(Sutter and al., 2005).

7.54.1 Parameter Requirements

No parameter is needed.

7.54.2 Non-Compliant Code Example

void print(int);

void f(){int i; //i should be declared at the for loop.int sum = 0; //sum is OK.

//i is only used in the for scope.for (i = 0; i < 10; ++i) {//sum is used right after the block of declaration it belongs.sum += i;

}

//sum is used in the scope of definition.print(sum);

}

7.54.3 Compliant Solution

void print(int);

void f(){int sum = 0;

for (int i = 0; i < 10; ++i) {sum += i;

}

print(sum);

7.54. LOCALIZED VARIABLES 153

}

7.54.4 Mitigation Strategies

Static Analysis

The checker uses a scoped symbol table to track some propertiesabout variable: Was the variable used? Was the variable in thesame scope as its declaration? Was the variable used right after thethe declaration? Is the declaration right before the current pointof the traversal? The traversal updates these flags. Once a scopefinished to be traversed, since the variables declared in the scopecannot be used any further, they are checked for the flags: used,used in the same scope and used right after its declaration.

There is another flag saying if the variable is a constant. In this caseonly check that the variable have been used, whereever it is.

This implementation does not care about aliasing. For more infor-mations see subsection 7.54.6.

7.54.5 References

Alexandrescu A. and Sutter H. C++ Coding Standards 101 Rules,Guidelines, and Best Practices. Addison-Wesley 2005.

7.54.6 Limitations

This checker does not do alias analyzing. In the case you use areference of a variable in an inner scope and re-use in the scope ofdeclaration, the checker will not see the use and propose to move thevariable in the inner scope. The effort for supporting the problem isvery big, and the result is to handle programs with weird behaviorthat should have been written differently.

154 CHAPTER 7. LIST OF COMPASS CHECKERS

7.55 Lower Range Limit

By always using inclusive lower limits and exclusive upper limits,a whole class of off- by-one errors is eliminated. Furthermore, thefollowing assumptions always apply: 1)the size of the interval equalsthe difference of the two2) the limits are equal if the interval is empty3) the upper limit is never less than the lower limit

Examples: instead of saying x¿=23 and x¡=42, use x¿=23 and x¡43.

7.55.1 Parameter Requirements

No parameters required.

7.55.2 Implementation

In a fairly straight-forward implementation we search the strictlylower than operator.

7.55.3 Non-Compliant Code Example

int x = 5;if (x < 5){x++;}% write your non-compliant code example

7.55.4 Compliant Solution

int x = 5;if (x <= 4){x++;}% write your compliant code example

7.55.5 Mitigation Strategies

Static Analysis

Compliance with this rule can be checked using structural staticanalysis checkers using the following algorithm:

7.55. LOWER RANGE LIMIT 155

1. find less than operator

2. raise alert

7.55.6 References

Abbreviated Code Inspection Checklist Section 11.1.1, Control Vari-ables”

156 CHAPTER 7. LIST OF COMPASS CHECKERS

7.56 Magic Number

This test checks for the presence of ‘magic numbers’ in the sourcecode. Magic numbers are all constants of integer or floating pointtype that occur outside of initializer expressions. The user mayconfigure the checker to ignore certain common constants such as 0or 1. This detector reports not only hand-written constants but alsothose that were created by macro expansion.

Note that C++ does not have negative constants; -1 is not an in-teger constant but rather the unary minus operator applied to theconstant 1. To ignore occurrences of -1, you must therefore instructthe checker to ignore the constant 1, but this will also ignore all‘positive’ occurrences.

7.56.1 Parameter Requirements

The magic number detector requires two entries in the parameterfile, one of which is the list of integer constants to ignore, the otherthe list of floating point constants to ignore. Constants in both listsare separated by whitespace; as explained above, it does not makesense to specify negative values.

An example of parameter entries is:

MagicNumberDetector.allowedIntegers =MagicNumberDetector.allowedFloats = 42.03.14159

This specification has an empty list of integers, so every integerconstant (of any type) will be flagged as a magic number; the floatingpoint constants 42.0 and 3.14159 are allowed to appear in the sourcecode, but all others are treated as magic numbers. Note that floatingpoint numbers are compared by numeric value, which may result instrange effects due to inexact representation.

7.56.2 Non-Compliant Code Example

int f_noncompliant(int n){

int x;x = 42; // not OK: magic numberreturn x + n;

}

7.56.3 Compliant Solution

int f_compliant(int n){

7.56. MAGIC NUMBER 157

int x = 42; // OK: constant only used in initializerreturn x + n;

}

7.56.4 Mitigation Strategies

Static Analysis

Compliance with this rule can be checked using structural staticanalysis checkers using the following algorithm:

1. For every integer or floating point literal, examine the enclosingstatement to find out whether it occurs as part of the initializerin a variable declaration. If not, emit a diagnostic.

7.56.5 References

A reference for this pattern is: H. Sutter, A. Alexandrescu: “C++Coding Standards”, Item 17: “Avoid magic numbers”.

158 CHAPTER 7. LIST OF COMPASS CHECKERS

7.57 Malloc Return Value Used In IfStmt

“ALE3D Coding Standards & Style Guide” item #4.5 states that

When using raw malloc() and new, developers shouldcheck the return value for NULL. This is especially impor-tant when allocating large blocks of memory, which mayexhaust heap resources.

7.57.1 Parameter Requirements

This checker takes no parameters and inputs source file.

7.57.2 Implementation

This pattern is checked using a simple AST traversal that seeks outfunction references to malloc. Then the parent nodes are traversedup until a basic scope block is found at which point a nested ASTtraversal seeks If-statement conditional expressions containing thememory block returned from malloc. If no such If-statement condi-tional is found in the immediate basic containing block scope thenan error is flagged.

7.57.3 Non-Compliant Code Example

The non-compliant code fails to check the return value of malloc().

#include <stdlib.h>

int main(){int *iptr = (int*)malloc( 256*sizeof(int) );

return 0;} //main()

7.57.4 Compliant Solution

The compliant solution uses an if statement to check the return valueof malloc() for NULL.

#include <stdlib.h>

int main(){

7.57. MALLOC RETURN VALUE USED IN IF STMT 159

int *iptr = (int*)malloc( 256*sizeof(int) );

if( iptr == NULL )return 1;

return 0;} //main()

7.57.5 Mitigation Strategies

Static Analysis

Compliance with this rule can be checked using structural staticanalysis checkers using the following algorithm:

1. Perform AST traversal visiting function call nodes correspond-ing to malloc().

2. For each call to malloc() traverse its parent nodes until an ifstatement or the end of a basic block is reached.

3. If an if statement is encountered, check that the if state-ment performs a comparison involving the return value frommalloc(); if this is not the case then flag a violation.

4. If a basic block is reached, then flag a violation as the returnvalue of malloc() may be out of scope.

5. Report any violations.

7.57.6 References

Arrighi B., Neely R., Reus J. “ALE3D Coding Standards & StyleGuide”, 2005.

160 CHAPTER 7. LIST OF COMPASS CHECKERS

7.58 Multiple Public Inheritance

Multiple inheritance in C++ can give rise to very complicated issues,in particular when a class has several public superclasses; in contrast,having a single public superclass and several private ones (only in-heriting code from these, but not public interfaces) can be muchmore controllable. This checker ensures that no class has more thanone public superclass, while not prohibiting multiple inheritance ingeneral.

7.58.1 Parameter Requirements

This checker does not require any parameters.

7.58.2 Non-Compliant Code Example

// Dummy classes, the first of which is designed to be used as a base class// from which one inherits an interface, the second designed to be used as a// base class from which one only inherits an implementation.class Interface { /* ... */ };class Implementation { /* ... */ };

// not OK: multiple public base classesclass A: public Interface, public Implementation{

/* ... */};

7.58.3 Compliant Solution

class Interface { /* ... */ };class Implementation { /* ... */ };

// OK: only one public base class, others may be non-publicclass B: public Interface, private Implementation{

/* ... */};

7.58.4 Mitigation Strategies

Static Analysis

Compliance with this rule can be checked using structural staticanalysis checkers using the following algorithm:

1. For each class definition, inspect the list of inheritances. Ifmore than one base class is listed as public, emit a diagnostic.

7.58. MULTIPLE PUBLIC INHERITANCE 161

7.58.5 References

This checker is a small part of the excellent discussion in: S. Meyers:“Effective C++ Second Edition”, Item 43: “Use multiple inheritancejudiciously”.

162 CHAPTER 7. LIST OF COMPASS CHECKERS

7.59 Name All Parameters

This checker warn for anonymous parameters in function declara-tions and definitions. For definitions, if the argument is not used, astatic cast<void> should be used instead of not naming the pa-rameter.

This checker check for the rule 22 from The Elements of C++ Style(Misfeldt and al., 2004).

7.59.1 Parameter Requirements

There is no parameter requirement.

7.59.2 Non-Compliant Code Example

void f(int){}

7.59.3 Compliant Solution

To avoid warning messages from the compiler about unused vari-ables, you can use a static cast<void> to mark unused parame-ters.

void f(int i){static_cast<void>(i);

}

7.59.4 Mitigation Strategies

Static Analysis

Compliance with this rule can be checked using structural staticanalysis checkers using the following algorithm:

1. For all function declarations, check that all parameter has aname.

7.59.5 References

Bumgardner G., Gray A., and Misfeldt T. The Elements of C++Style. Cambridge University Press 2004.

7.60. [NO REFERENCE] : NEW DELETE 163

7.60 [No Reference] : New Delete

This analysis checks for the validity of all delete operations in aspecific source code. It checks for violations of:

a) Deleting an array with a simple delete operator instead of andelete array operator.

b) Deleting a NULL pointer.

c) Checks for the deletion of uninitialized pointers.

7.60.1 Non-Compliant Code Examples

In the following examples, a) b) and c) from above are demonstrated.

class Y {int y;

};

void fail() {int x=2;// deleting arrayY* m = new Y[5];delete m;

// deleting NULLY* n = 0;delete n;

// deleting NULLY* c ;if (x==5) {x=7;delete c;

}}

7.60.2 Compliant Solution

Use assert statements to make sure that a pointer cannot be null, oruse the delete[] operator if a new[] operator precedes on that pointer.

7.60.3 Parameter Requirements

None.

164 CHAPTER 7. LIST OF COMPASS CHECKERS

7.60.4 Implementation

This analysis uses the BOOST library in order to utilize the breadthfirst search (BFS) algorithm. Together with the control flow graphand the BFS, the implementation backtracks the code from thedelete operation to its definition. On violations of the describedcases, the analysis results in warnings.

The algorithm searches first for each occurance of a SgDeleteExp andbacktracks this Node to its definition. If we find a SgNew operation,we need to see if the delete and new operations match, i.e. whetherthey are both operations on pointers or arrays.

The following cases are checked for and handled during the back-wards dataflow analysis:

case V_SgNewExp:case V_SgVarRefExp:case V_SgAddressOfOp:case V_SgCastExp:case V_SgIntVal:

The above indicates a recursive algorithm.

7.60.5 References

7.61. NO ASM STMTS OPS 165

7.61 No Asm Stmts Ops

7.61.1 Parameter Requirements

This checker takes no parameters and inputs source file

7.61.2 Implementation

This checker uses a simple AST traversal that checks for SgAsm-Stmt(s) and SgAsmOp(s). Any such nodes that are found are flaggedas violations

7.61.3 Non-Compliant Code Example

This example is taken from Cxx tests/test2006 98.C

typedef int _Atomic_word;

#ifndef __INTEL_COMPILER// Intel complains that the input register "m" cannot have a modifier "+"static inline _Atomic_word__attribute__ ((__unused__))__exchange_and_add (volatile _Atomic_word *__mem, int __val){register _Atomic_word __result;__asm__ __volatile__ ("lock; xadd{l} {%0,%1|%1,%0}"

: "=r" (__result), "+m" (*__mem): "0" (__val): "memory");

return __result;}#endif

7.61.4 Compliant Solution

The compliant solution does not make use of C assembly.

7.61.5 Mitigation Strategies

Static Analysis

Compliance with this rule can be checked using structural staticanalysis checkers using the following algorithm:

1. Perform simple AST traversal visiting SgAsmStmt and SgAs-mOp nodes.

2. For each such node flag violation.3. Report all violations.

166 CHAPTER 7. LIST OF COMPASS CHECKERS

7.61.6 References

7.62. NO EXCEPTIONS 167

7.62 No Exceptions

This checker detects all usages of C++ exception handling.

7.62.1 Parameter Requirements

No parameters are required.

7.62.2 Implementation

The checker detects try statements, throw operations and catchstatements.

7.62.3 Non-Compliant Code Example

class Exception{};

int main(){try {

throw Exception();} catch( Exception e ){ }

};

7.62.4 Compliant Solution

int main(){};

7.62.5 Mitigation Strategies

Static Analysis

Compliance with this rule can be checked using structural staticanalysis checkers using the following algorithm:

1. Traverse the AST

2. For each try statements, throw operations and catch statementsreport and error.

7.62.6 References

The ALE3D style guide section 17.1 forbids usage of C++ excep-tions.

168 CHAPTER 7. LIST OF COMPASS CHECKERS

7.63 No Exit In Mpi Code

“ALE3D Coding Standards & Style Guide” item #19.1 states that

exit() must never be called from a parallel code. Callingexit() from a parallel code will cause the code to dead-lock. Even if you can guarantee that every processor willcall exit() collectively, this can leave some parallel envi-ronments in a hung state because MPI resources are notproperly cleaned up.

7.63.1 Parameter Requirements

This checker takes no parameters and inputs source file.

7.63.2 Implementation

This pattern is checked using a simple AST traversal seeking functionreference expressions. These function reference expressions match-ing a call to the exit() function between blocks of MPI code (as de-limited between MPI Init and MPI Finalize) are flagged as checkerviolations.

7.63.3 Non-Compliant Code Example

This trivial non-compliant code calls exit() from an MPI block.

#include <stdlib.h>#include "mpi.h"

int main( int argc, char **argv ){MPI_Init( &argc, &argv );exit(1);

MPI_Finalize();

return 0;} //main()

7.63.4 Compliant Solution

The compliant solution uses MPI Abort() instead.

#include <stdlib.h>#include "mpi.h"

int main( int argc, char **argv )

7.63. NO EXIT IN MPI CODE 169

{MPI_Init( &argc, &argv );MPI_Abort( MPI_COMM_WORLD, 1 );

MPI_Finalize();

return 0;} //main()

7.63.5 Mitigation Strategies

Static Analysis

Compliance with this rule can be checked using structural staticanalysis checkers using the following algorithm:

1. Perform a simple AST traversal of nodes that occur betweenMPI Init() and MPI Finalize() blocks.

2. For each node between MPI blocks, if node is call to exit()then flag violation.

3. Report any violations.

7.63.6 References

Arrighi B., Neely R., Reus J. “ALE3D Coding Standards & StyleGuide”, 2005.

170 CHAPTER 7. LIST OF COMPASS CHECKERS

7.64 No Goto

This checker detects uses of goto statements conforming with High-Integrity C++ Coding Standard Manual, rule 5.8: “Do not use goto”

7.64.1 Parameter Requirements

No parameter is needed

7.64.2 Non-Compliant Code Example

void foo() {tryAgain:try {doSomething();

}catch (...) {goto tryAgain;

}}

7.64.3 Compliant Solution

void foo() {do {try {doSomething();

}catch (...) {continue ;

}break ;

} while (true);}

7.64.4 Mitigation Strategies

Static Analysis

Compliance with this rule can be checked using structural staticanalysis checkers using the following algorithm:

1. Look for goto expressions.

7.64. NO GOTO 171

7.64.5 References

The Programming Research Group, High-Integrity C++ CodingStandard Manual, rule 5.8: “Do not use goto”.

172 CHAPTER 7. LIST OF COMPASS CHECKERS

7.65 No Overload Ampersand

The C++ standard [ISO/IEC 14882-2003] says in Section 5.3.1 para-graph 4 that

The address of an object of incomplete type can be taken, but ifthe complete type of that object is a class type that declares oper-ator&() as a member function, then the behavior is undefined (andno diagnostic is required).

Therefore, to avoid possible undefined behavior, the operator &should not be overloaded.

7.65.1 Parameter Requirements

No Parameters Required.

7.65.2 Implementation

We check any member function then compare the name to ’opera-tor&’. If this combination is found an alert is raised.

7.65.3 Non-Compliant Code Example

class peanutButter{string name;void operator&(){name += ’&jelly’;

}}

7.65.4 Compliant Solution

class peanutButter{string name;void addJelly(){name += ’&jelly’;

}}

7.65. NO OVERLOAD AMPERSAND 173

7.65.5 Mitigation Strategies

Static Analysis

Compliance with this rule can be checked using structural staticanalysis checkers using the following algorithm:

1. Find member function

2. Check name

3. raise alert

7.65.6 References

ISO/IEC 9899-1999:TC2 ISO/IEC 14882-2003 Section 5.3.1, “Unaryoperators”Lockheed Martin 05 AV Rule 159, “Operators ||, &&, and unary &shall not be overloaded”

174 CHAPTER 7. LIST OF COMPASS CHECKERS

7.66 CERT-MSC30-C: No Rand

“CERT Secure Coding MSC30-C” states

The C Standard function rand (available in stdlib.h)does not have good random number properties. The num-bers generated by rand have a comparatively short cy-cle, and the numbers may be predictable. To achieve thebest random numbers possible, an implementation-specificfunction needs to be used.

7.66.1 Parameter Requirements

This checker takes no parameters and inputs source file.

7.66.2 Implementation

This pattern is checked using a simple AST traversal that visitsall function reference expressions. If a functino reference expressionnode corresponds to the rand() function, then a violation is flagged.

7.66.3 Non-Compliant Code Example

The following code calls rand().1 #include <stdlib.h>23 int main()4 {5 int r = rand(); /* generate a random integer */67 return 0;8 }

7.66.4 Compliant Solution

The compliant solution is to use a implementation-specific randomnumber generator.

1 int main()2 {3 int r = my rand(); /* generate a random integer */45 return 0;6 }

7.66. CERT-MSC30-C: NO RAND 175

7.66.5 Mitigation Strategies

Static Analysis

Compliance with this rule can be checked using structural staticanalysis checkers using the following algorithm:

1. Perform a simple AST traversal visiting all function referenceexpression nodes.

2. For each node visited, if the function reference expression cor-responds to rand() then flag violation.

3. Report any violations.

7.66.6 References

Secure Coding : MSC30-C. Do not use the rand function

176 CHAPTER 7. LIST OF COMPASS CHECKERS

7.67 No Second Term Side Effects

The logical AND and logical OR operators (&&, ||) exhibit “shortcircuit” operation. That is, the second operand is not evaluatedif the result can be deduced solely by evaluating the first operand.Consequently, the second operand should not contain side effectsbecause, if it does, it is not apparent if the side effect occurs

7.67.1 Parameter Requirements

No parameters required.

7.67.2 Implementation

We check for And or Or. We then query for any of a set of operatorsknown to have side effects. This checker has the known deficiency ofnot checking function calls for side-effects. To avoid false positives,it does not notify of functions at all.

7.67.3 Non-Compliant Code Example

int i;int max;

if ( (i >= 0 && (i++) <= max) ) {/* code */

}

It is unclear whether the value of i will be incremented as a resultof evaluating the condition.

7.67.4 Compliant Solution

In this compliant solution, the behavior is much clearer.

int i;int max;

if ( (i >= 0 && (i + 1) <= max) ) {i++;/* code */

}

7.67. NO SECOND TERM SIDE EFFECTS 177

7.67.5 Mitigation Strategies

Static Analysis

Compliance with this rule can be checked using structural staticanalysis checkers using the following algorithm:

1. Find the And or Or operator

2. query the right-hand child for known side-effect having opera-tors

7.67.6 References

ISO/IEC 9899-1999:TC2 [ISO/IEC 9899-1999] Section 6.5.13, “Log-ical AND operator,” and Section 6.5.14, “Logical OR operator”

178 CHAPTER 7. LIST OF COMPASS CHECKERS

7.68 Secure Coding : EXP06-A.Operands to the sizeof operator shouldnot contain side effects

The sizeof operator yields the size (in bytes) of its operand, whichmay be an expression or the parenthesized name of a type. If thetype of the operand is not a variable length array type the operandis not evaluated.

Providing an expression that appears to produce side effects maybe misleading to programmers who are not aware that these expres-sions are not evaluated. As a result, programmers may make invalidassumptions about program state leading to errors and possible soft-ware vulnerabilities.

7.68.1 Non-Compliant Code Example

In this example, the variable a will still have a value 14 after b hasbeen initialized.

1 int a = 14;2 int b = sizeof(a++);3

The expression a++ is not evaluated. Consequently, side effects inthe expression are not executed.

Implementation Specific Details

This example compiles cleanly under Microsoft Visual Studio 2005Version 8.0, with the /W4 option.

7.68.2 Compliant Solution

In this compliant solution, the variable a is incremented.1 int a = 14;2 int b = sizeof(a);3 a++;4

Implementation Specific Details

This example compiles cleanly under Microsoft Visual Studio 2005Version 8.0, with the /W4 option.

7.68. SECURE CODING : EXP06-A. OPERANDS TO THE SIZEOF OPERATOR SHOULD NOT CONTAIN SIDE EFFECTS179

7.68.3 Risk Assessment

If expressions that appear to produce side effects are supplied to thesizeof operator, the returned result may be different then expected.Depending on how this result is used, this could lead to unintendedprogram behavior.

Rule Severity Likelihood Remediation Cost Priority LevelEXP06-A 1 (low) 1 (unlikely) 3 (low) P3 L3

Related Vulnerabilities

Search for vulnerabilities resulting from the violation of this rule onthe CERT website .

7.68.4 References

[ ISO/IEC 9899-1999 ] Section 6.5.3.4, ”The sizeof operator”

180 CHAPTER 7. LIST OF COMPASS CHECKERS

7.69 No Template Usage

Finds all usages of C++ templates. It will not detect C++ templatedeclarations that are not instantiated.

7.69.1 Parameter Requirements

No parameters are required.

7.69.2 Implementation

The checker finds all template instatiation declaration, template in-statiation definitions, template instantiation member function dec-larations and template instatiation function declarations.

7.69.3 Non-Compliant Code Example

template<typename t>class Foo{

public:Foo(){};~Foo(){};

};

void main(){Foo<int> fi;Foo<float> ff;

}

7.69.4 Compliant Solution

class Foo{

public:Foo(){};~Foo(){};

};

void main(){Foo fi;Foo ff;

}

7.69. NO TEMPLATE USAGE 181

7.69.5 Mitigation Strategies

Static Analysis

Compliance with this rule can be checked using structural staticanalysis checkers using the following algorithm:

1. Traverse the AST

2. For each template instantiations and template declaration re-port an error

7.69.6 References

The ALE3D style guide section 16.1 states that templates must notbe used.

182 CHAPTER 7. LIST OF COMPASS CHECKERS

7.70 No Variadic Functions

“CERT Secure Coding DCL33-C.” states

A variadic function a function declared with a parameterlist ending with ellipsis (...) can accept a varying numberof arguments of differing types. Variadic functions areflexible, but they are also hazardous. The compiler can’tverify that a given call to a variadic function passes anappropriate number of arguments or that those argumentshave appropriate types. Consequently, a runtime call toa variadic function that passes inappropriate argumentsyields undefined behavior. Such undefined behavior couldbe exploited to run arbitrary code.

7.70.1 Parameter Requirements

This checker takes no parameters and inputs source file.

7.70.2 Implementation

This pattern is checked using a simple AST traversal that visitsall function and member function references checking the functiondeclaration for arguments of variadic type. Those defined functionswith variadic arguments flag violations of this rule.

7.70.3 Non-Compliant Code Example

#include <cstdarg>

char *concatenate(char const *s, ...){return 0;

}

int main(){char *separator = "\t";char *t = concatenate("hello", separator, "world", 0);

return 0;}

7.70.4 Compliant Solution

The compliant solution uses a chain of string binary operations in-stead of a variadic function.

7.70. NO VARIADIC FUNCTIONS 183

#include <string>

string separator = /* some reasonable value */;

string s = "hello" + separator + "world";

7.70.5 Mitigation Strategies

Static Analysis

Compliance with this rule can be checked using structural staticanalysis checkers using the following algorithm:

1. Perform simple AST traversal on all function and member func-tion references.

2. For each function reference check the function declaration andexistence of function definition.

3. If function definition does not exist then stop check.

4. Else check function declaration arguments for variadic types.

5. Report any violations.

7.70.6 References

DCL33-C. Do not define variadic functions

184 CHAPTER 7. LIST OF COMPASS CHECKERS

7.71 CERT-POS33-C: No Vfork

“CERT Secure Coding POS33-C” states

Using the vfork function introduces many portability andsecurity issues. There are many cases in which undefinedand implementation specific behavior can occur, leadingto a denial of service vulnerability.

7.71.1 Parameter Requirements

This checker takes no parameters and inputs source file.

7.71.2 Implementation

This pattern is checked using a simple AST traversal that visitsall function reference expressions. If a functino reference expres-sion node corresponds to the vfork() function, then a violation isflagged.

7.71.3 Non-Compliant Code Example

This non-compliant example calls vfork().1 #include <stdlib.h>2 #include <unistd.h>34 int main()5 {6 pid t pid = vfork();78 if ( pid == 0 ) /* child */9 {

10 system( "echo \"Hello World\"" );11 }1213 return 0;14 }

7.71.4 Compliant Solution

The compliant solution calls fork() instead.1 #include <stdlib.h>2 #include <unistd.h>34 int main()5 {6 pid t pid = fork();78 if ( pid == 0 ) /* child */9 {

10 system( "echo \"Hello World\"" );11 }1213 return 0;

7.71. CERT-POS33-C: NO VFORK 185

14 }

7.71.5 Mitigation Strategies

Static Analysis

Compliance with this rule can be checked using structural staticanalysis checkers using the following algorithm:

1. Perform a simple AST traversal visiting all function referenceexpressions.

2. For each node visited, if the function reference expression cor-responds to vfork() then flag violation.

3. Report any violations.

7.71.6 References

Secure Coding : POS33-C. Do not use vfork()

186 CHAPTER 7. LIST OF COMPASS CHECKERS

7.72 Non Associative Relational Opera-tors

C++ Secure Coding Practices states that:

The relational and equality operators are left-associative,not non-associative as they often are in other languages.This allows a C++ programmer to write an expression(particularly an expression used as a condition) that canbe easily misinterpreted.

This checker checks that relational binary operators (==, ! =, <, >,<=, >=) are not treated as if they were non-associative.

7.72.1 Parameter Requirements

This checker takes no parameters and inputs source file

7.72.2 Implementation

This pattern is checked using a nested AST traversal on the parentnodes of the operand of a binary operator expression. Any such par-ent node that treats relational binary operators as non-associativewill use more than one binary relational operator. Flag these ex-pressions as violations.

7.72.3 Non-Compliant Code Example

#include <stdio.h>

int main(){int a = 2;int b = 2;int c = 2;

if ( a < b < c ) // condition #1, misleading, likely bugprintf( "a < b < c\n" );

if ( a == b == c ) // condition #2, misleading, likely bugprintf( "a == b == c\n" );

return 0;}

7.72. NON ASSOCIATIVE RELATIONAL OPERATORS 187

7.72.4 Compliant Solution

#include <stdio.h>

int main(){int a = 2;int b = 2;int c = 2;

if ( a < b && b < c ) // clearer, and probably what was intendedprintf( "a < b && b < c\n" );

if ( a == b && a == c ) // dittoprintf( "a == b && a == c\n" );

return 0;}

7.72.5 Mitigation Strategies

Static Analysis

Compliance with this rule can be checked using structural staticanalysis checkers using the following algorithm:

1. Perform simple AST traversal and locate SgBinaryOp nodes.

2. At each SgBinaryOp node perform a nested traversal of theoperands parent node and count the number of relational binaryoperators used.

3. If said count is greater than one then flag error.

4. Report all errors.

7.72.6 References

EXP09-A. Treat relational and equality operators as if they werenonassociative

188 CHAPTER 7. LIST OF COMPASS CHECKERS

7.73 Non Standard Type Ref Args

Per the Abbreviated C++ Code Inspection Checklist “While it ischeaper to pass ints, longs, and such by value, passing objects thisway incurs significant expense due to the construction of tempo-rary objects. The problem becomes more severe when inheritance isinvolved. Simulate pass-by-value by passing const references.”

7.73.1 Parameter Requirements

No parameters necessary

7.73.2 Implementation

The arguments to all functions are checked for base type in thedeclaration. If the base type is found to be a struct or a class, it isthen checked to ensure it is a reference. If it is not, a notification israised.

7.73.3 Non-Compliant Code Example

class incrediblyComplex{private://loads of members}

bool justLooking(incrediblyComplex fullCopy){return (! &fullCopy);}

7.73.4 Compliant Solution

class incrediblyComplex{private://loads of members}

bool justLooking(incrediblyComplex& fullCopy){return (! &fullCopy);

7.73. NON STANDARD TYPE REF ARGS 189

}

7.73.5 Mitigation Strategies

Static Analysis

Compliance with this rule can be checked using structural staticanalysis checkers using the following algorithm:

1. Identify function declaration

2. Check arguments for base type

3. if non-intrinsic type and not a reference, notify

7.73.6 References

Abbreviated Code Inspection Checklist Section 13.1, ArgumentPassing”

190 CHAPTER 7. LIST OF COMPASS CHECKERS

7.74 Non Standard Type Ref Returns

While it is cheaper to pass ints, longs, and such by value, passingobjects this way incurs significant expense due to the constructionof temporary objects. The problem becomes more severe when in-heritance is involved. Simulate pass-by-value by passing const refer-ences.

7.74.1 Parameter Requirements

No parameters necessary.

7.74.2 Implementation

The return types to all functions are checked for base type in thedeclaration. If the base type is found to be a struct or a class, it isthen checked to ensure it is a reference. If it is not, a notification israised.

7.74.3 Non-Compliant Code Example

class incrediblyComplex{private://loads of members}

incrediblyComplex justLooking(){incrediblyComplex *fullCopy = new incrediblyComplex();return (*fullCopy);}

7.74.4 Compliant Solution

class incrediblyComplex{private://loads of members}

7.74. NON STANDARD TYPE REF RETURNS 191

incrediblyComplex& justLooking(){incrediblyComplex *fullCopy = new incrediblyComplex();return (*fullCopy);}

7.74.5 Mitigation Strategies

Static Analysis

Compliance with this rule can be checked using structural staticanalysis checkers using the following algorithm:

1. Identify function declaration

2. Check return for base type

3. if non-intrinsic type and not a reference, notify

7.74.6 References

Abbreviated Code Inspection Checklist Section 14.5, Return Values”

192 CHAPTER 7. LIST OF COMPASS CHECKERS

7.75 Non Virtual Redefinition

Calls of nonvirtual member functions are resolved at compile time,not run time. Redefinition of an inherited nonvirtual function ina derived class has different semantics that can result in surprisingbehavior and should therefore be avoided. This checker reports caseswhere a class redefines a function that was declared nonvirtual in oneof its superclasses.

7.75.1 Parameter Requirements

This checker does not require any parameters.

7.75.2 Non-Compliant Code Example

namespace NonCompliant {class Base {public:

virtual void overrideIfYouWish(int);void doNotOverride(int);

};

class Inherited: public Base {public:

void doNotOverride(int); // trying to override nonvirtual function};

}

7.75.3 Compliant Solution

namespace Compliant {class Base {public:

virtual void overrideIfYouWish(int);void doNotOverride(int);

};

class Inherited: public Base {public:

void overrideIfYouWish(int); // overriding virtual function};

}

7.75. NON VIRTUAL REDEFINITION 193

7.75.4 Mitigation Strategies

Static Analysis

Compliance with this rule can be checked using structural staticanalysis checkers using the following algorithm:

1. For every member function declaration, traverse the inheritanceDAG of the enclosing class.

2. Identify any functions that may be overridden by the currentone (by checking name and type).

3. Issue a diagnostic if the overridden function is not declaredvirtual.

7.75.5 References

A reference for this checker is: S. Meyers: “Effective C++ SecondEdition”, Item 37: “Never redefine an inherited nonvirtual func-tion.”

194 CHAPTER 7. LIST OF COMPASS CHECKERS

7.76 Nonmember Function InterfaceNamespace

User-defined classes should typically reside in the same namespaceas their nonmember function interface, i.e. friend functions and op-erators for that class. The reasons are uniform lookup of overloadedfunctions and that the interface of a class consists not only of itsmember functions. This checker enforces this guideline. It reportsfriend function declarations that refer to functions from a differentnamespace. Further, it makes sure that every class mentioned in anonmember operator’s signature (return and argument types) is inthe same namespace as the operator, or in the global std namespace.

7.76.1 Parameter Requirements

No parameters are required.

7.76.2 Non-Compliant Code Example

void f(); // not OK: used as friend in class N::A, not in same namespacenamespace N{

class A{public:

friend void ::f();};

}

7.76.3 Compliant Solution

namespace M{

void f(); // OK: used as friend in M::B, same namespace

class B{public:

friend void f();};

}

7.76. NONMEMBER FUNCTION INTERFACE NAMESPACE 195

7.76.4 Mitigation Strategies

Static Analysis

Compliance with this rule can be checked using structural staticanalysis checkers using the following algorithm:

1. For each friend function or operator for a class, look up thenamespace it is declared in and compare to the namespace ofthe class.

7.76.5 References

The reference for this checker is: H. Sutter, A. Alexandrescu: “C++Coding Standards”, Item 57: “Keep a type and its nonmenber func-tion interface in the same namespace”.

196 CHAPTER 7. LIST OF COMPASS CHECKERS

7.77 CERT EXP33-C and EXP34-C :Null Dereference

NULL Dereference checker. If any variable that could be NULL isdereferenced, a warning is issued. This is an implementation of US-CERT rules: EXP33-C - Do not reference uninitialized variables andEXP34-C - Ensure a pointer is valid before dereferencing it.

EXP33-C - Do not reference uninitialized variables

Local, automatic variables can assume unexpected values if they areused before they are initialized. C99 specifies If an object that hasautomatic storage duration is not initialized explicitly, its value isindeterminate [ISO/IEC 9899-1999]. In practice, this value defaultsto whichever values are currently stored in stack memory. Whileuninitialized memory often contains zero, this is not guaranteed.Consequently, uninitialized memory can cause a program to behavein an unpredictable or unplanned manner and may provide an avenuefor attack.

7.77.1 EXP34-C - Ensure a pointer is valid beforedereferencing it

Attempting to dereference an invalid pointer results in undefined be-havior, typically abnormal program termination. Given this, point-ers should be checked to make sure they are valid before they aredereferenced.

7.77.2 Non-Compliant Code Examples

EXP33-C - Do not reference uninitialized variables

In this example, the set flag() function is supposed to set a the vari-able sign to 1 if number is positive and -1 if number is negative.However, the programmer forgot to account for number being 0. Ifnumber is 0, then sign will remain uninitialized. Because sign isuninitialized, it assumes whatever value is at that location in theprogram stack. This may lead to unexpected, incorrect programbehavior.

void set_flag(int number, int *sign_flag) {if (number > 0) {*sign_flag = 1;

}else if (number <0) {*sign_flag = -1;

}

7.77. CERT EXP33-C AND EXP34-C : NULL DEREFERENCE 197

int x = *sign_flag;}

int main(int argc, char** argv) {int sign;set_flag(0,&sign);return 0;

}

EXP34-C - Ensure a pointer is valid before dereferencingit

In this example, input str is copied into dynamically allocated mem-ory referenced by str. If malloc() fails, it returns a NULL pointerthat is assigned to str. When str is dereferenced in strcpy(), theprogram behaves in an unpredictable manner.

#include "assert.h"#include <stdlib.h>

void testme() {// case 1int size = 5;char* str = (char*) malloc(size+1);char z = *str;

// case 2int *p = 0;int l = *p;

// case 3char *k=0;free(k);

}

7.77.3 Compliant Solution

EXP33-C - Do not reference uninitialized variables

We do not check the expressions in if conditions, and hence it is irrel-evant what the if conditions state. However, because an if conditionoccurs, there might be a path that leaves sign flag uninitialized. Inthis case a simple assert helps to avoid the warning caused by thisanalysis.

#include "assert.h"

198 CHAPTER 7. LIST OF COMPASS CHECKERS

void set_flag(int number, int *sign_flag) {assert(sign_flag);if (number > 0) {*sign_flag = 1;

}else if (number <0) {*sign_flag = -1;

}int x = *sign_flag;

}

int main(int argc, char** argv) {int sign;set_flag(0,&sign);return 0;

}

7.77.4 EXP34-C - Ensure a pointer is valid beforedereferencing it

#include "assert.h"#include <stdlib.h>

void testme() {// case 1int size = 5;char* str = (char*) malloc(size+1);if (str==NULL) {*str = ’5’;

}char z = *str;

// case 2int *p = 0;assert(p);int l = *p;

// case 3char *k=0;assert(k);free(k);

}

7.77.5 Parameter Requirements

None.

7.77. CERT EXP33-C AND EXP34-C : NULL DEREFERENCE 199

7.77.6 Implementation

We use a dataflow analysis to determine null dereference. Thedataflow analysis is based on an breadth first search (bfs) algorithm,implemented in BOOST. The implementation does a bfs backwardstraversal for each:

a) SgArrowExp

b) SgPointerDerefExp

c) SgAssignInitializer

d) SgFunctionCallExp (free)

The above are the points that need to be validated by the algo-rithm. At each such point the program might be invalid due toNULL pointer dereferences. Therefore, the variable at that pointmust be determined and the programmed is tracked back (dataflow).

If at any point an assertion is found, the analysis is aborted for thatrun, i.e. no null pointer dereference is present.

7.77.7 References

EXP33C , “Do not reference uninitialized variables”EXP34C , “Ensure a pointer is valid before dereferencing it”

200 CHAPTER 7. LIST OF COMPASS CHECKERS

7.78 Omp Private Lock

This is a simple checker to detect a common OpenMP programmingmistake of using a private lock within a parallel region. It was mo-tivated by an example mentioned by a seminar about Intel’s ThreadChecker, which uses a more expensive runtime approach to catchthe same error.

7.78.1 Parameter Requirements

There is no parameter specifications.

7.78.2 Implementation

The AST must use dedicated OpenMP nodes (such as SgOmp-ParallelStatement etc.) to represent an input OpenMP program(via -rose:openmp -rose:openmp:ast only). The checker traversesthe AST to find all OpenMP lock variable references (with a typename omp lock t) within omp unset lock(), omp set lock(), andomp test lock(). It then compares the scope of the correspondinglock declaration statement and the enclosing parallel region of thelock references. If the lock is declared within the parallel region, itis a violation.

7.78.3 Non-Compliant Code Example

void foo(){#pragma omp parallel private(id){omp_lock_t lck; // local declared lock variable, wrong!int id = omp_get_thread_num();omp_set_lock(&lck);printf("My thread id is %d.\n", id);omp_unset_lock(&lck);

}}

7.78.4 Compliant Solution

omp_lock_t lck; // a global shared lock,//lock initialization and destroy calls are omitted

7.78. OMP PRIVATE LOCK 201

void foo(){#pragma omp parallel private(id){int id = omp_get_thread_num();omp_set_lock(&lck);printf("My thread id is %d.\n", id);omp_unset_lock(&lck);

}}

7.78.5 References

None

202 CHAPTER 7. LIST OF COMPASS CHECKERS

7.79 CERT-DCL04-A: One Line PerDeclaration

“CERT Secure Coding DCL04-A” states

Declaring multiple variables on a single line of code cancause confusion regarding the types of the variables andtheir initial values. If more than one variable is declaredon a line, care must be taken that the actual type and ini-tialized value of the variable is known. To avoid confusion,more than one type of variable should not be declared onthe same line.

7.79.1 Parameter Requirements

This checker takes no parameters and inputs source file.

7.79.2 Implementation

This pattern is checked using a simple AST traversal, visiting allvariable declaration statements. The line number of each variabledeclaration statement node is saved to a std set unique to each file. Ifany line number is added to this set more than once then a violationis flagged.

7.79.3 Non-Compliant Code Example

The non-compliant code declares multiple int variables on the sameline.

int main(){int i1 = 0, i2 = 0, i3 = 0;

return 0;}

7.79.4 Compliant Solution

The compliant solution is to give each int declaration its own line.

int main(){int i1 = 0;int i2 = 0;int i3 = 0;

7.79. CERT-DCL04-A: ONE LINE PER DECLARATION 203

return 0;}

7.79.5 Mitigation Strategies

Static Analysis

Compliance with this rule can be checked using structural staticanalysis checkers using the following algorithm:

1. Perform a simple AST traversal visiting all variable declarationnodes.

2. For each line number associated with a variable declarationnode, add the line number to a set of line numbers unique toits source file.

3. If any line number is added more than once per source file setof line numbers then flag a violation.

4. Report any violations.

7.79.6 References

Secure Coding : DCL04-A. Take care when declaring more than onevariable per line

204 CHAPTER 7. LIST OF COMPASS CHECKERS

7.80 Operator Overloading

This test detects function declaration that overloads operators thatcan cause subtle bugs, such as “&&”, “||”, or “,”. That is, onecan not ensure that the overloaded operators will be evaluated inleft-to-right order. This is based on the following rules:

• Function calls always evaluate all arguments before execution.

• The order of evaluation of function arguments is unspecified.

For example,

auto_ptr<Employee> e = GetEmployee();if(e && e->Manager())

The usual evaluation order (left to right) prevents the test fromexecuting e->Manager() and the code above looks fine. However,the code above can invoke an overloaded operator&& and it willpotentially call e->Manager() before checking if e is NULL.

7.80.1 Parameter Requirements

None.

7.80.2 Implementation

This pattern is detected using a simple traversal. It traverses ASTto find function declarations and check whether or not the name ofthe functions is “operator&&”, “operator||”, or “operator,”.

7.80.3 Non-Compliant Code Example

class Test{public:Test();~Test();Test operator&&(const Test &);Test operator||(const Test &);Test operator,(const Test &);

};

7.80.4 Compliant Solution

N/A

7.80. OPERATOR OVERLOADING 205

7.80.5 Mitigation Strategies

Static Analysis

Compliance with this rule can be checked using structural staticanalysis checkers using the following algorithm:

1. Check if a node is a function declaration

2. Check if the name of the function contains “operator&&”,“operator||”, or “operator,”.

7.80.6 References

T. Misfeldt, G. Bumgardner, A. Gray, “The Elements of C++Style”, Item 111: “Do not overload operator && or operator ||”.

206 CHAPTER 7. LIST OF COMPASS CHECKERS

7.81 Other Argument

This checker enforce the name convention of the first argument incopy constructors and copy operators. This is taken from rule 23from the Elements of C++ Style (Misfeldt and al., 2004). The pa-rameter should be called other. This checker also accept two othernaming conventions: that and the class name in lower camel case.

7.81.1 Parameter Requirements

There is no parameter requirement.

7.81.2 Non-Compliant Code Example

A::A(const A& foo){//...

}

7.81.3 Compliant Solution

A::A(const A& other){//...

}

7.81.4 Mitigation Strategies

Static Analysis

Compliance with this rule can be checked using structural staticanalysis checkers using the following algorithm:

1. For all constructors and operator fulfilling the copy requirementof the C++ standard, check that the first parameter is of thethree possible name.

7.81.5 References

Bumgardner G., Gray A., and Misfeldt T. The Elements of C++Style. Cambridge University Press 2004.

7.82. PLACE CONSTANT ON THE LHS 207

7.82 Place Constant On The Lhs

This checker detects a test clause whether or not it contains a con-stant on the left hand side when comparing a varialbe and the con-stant for equality. By putting the constant on the left hand side, thecompiler can prevent programmers from making mistake to write’=’ for ’==’.

7.82.1 Parameter Requirements

None

7.82.2 Implementation

This checker is implemented with a simple traversal. It traversesAST and finds a test clause. If the test clause has a variable onits left hand side, then, then the checker report this clause to thestandard output.

7.82.3 Non-Compliant Code Example

void foo(){int a = 0;

if(a == 10) // a is on the LHS{a = 1;}

while(a == 10) // a is on the LHS{a++;}

do{a++;}while(a == 12); // a is on the LHS

for(int i = 0; i == 0; i++) // i is on the LHS{a = 12;}}

208 CHAPTER 7. LIST OF COMPASS CHECKERS

7.82.4 Compliant Solution

void foo(){int a = 0;

if(1 == a) // fine{a = 2;}}

7.82.5 Mitigation Strategies

Static Analysis

Compliance with this rule can be checked using structural staticanalysis checkers using the following algorithm:

1. Check if the node visiting is an if statement.

2. If yes, find its test clause to see if it contains a constant on theleft hand side.

3. Check also if the if statement compares a variable and the con-stant for equality

7.82.6 References

The Programming Research Group: High-Integrity C++ CodingStandard Manual, Item 10.6: “When comparing variables and con-stants for equality always place place the constnat on the left handside.”

7.83. POINTER COMPARISON 209

7.83 Pointer Comparison

This checker tries to find comparison operations involving pointers.These comparison results are determined by the memory locationsof the objects pointed to in the program’s address space. Using ==is usually safe. But using <, <=,>, and >= is error-prone given theuncertainty of memory locations of objects across executions andplatforms.

7.83.1 Parameter Requirements

There is not parameter requirement.

7.83.2 Implementation

The checker finds relational operators such as < , <=,>, and >=and sends out warnings if at least one of their operands is of pointertypes.

7.83.3 Non-Compliant Code Example

Here is the original code piece which inspired this checker. It assumesin the ROSE AST, a parent scope node resides in a memory locationof smaller address compared to the address of its descendent scopenode. This assumption is wrong given the difference of memorymanagement across platforms or even executions. A right solutionis to walk the AST tree to find out their relationship.

SgScopeStatement * scope1, * scope2;// ....if (scope1<scope2)//

else//

7.83.4 References

No reference.

210 CHAPTER 7. LIST OF COMPASS CHECKERS

7.84 Prefer Algorithms

Many people consider hand-written loops over STL containers infe-rior to calls to STL algorithms for reasons of efficiency, correctness,and maintainability.

This checker is meant to highlight cases where a loop might be re-placed by an equivalent STL algorithm call. It reports for loopswhere the loop head fulfills the following properties:

• The initialization part contains an assignment or variable dec-laration with an initializer,

• the condition part consists of an inequality comparison, and

• the increment part consists of an increment or decrement op-eration.

For loops on integer or floating-point types are not reported as thosecannot be replaced by STL algorithms.

7.84.1 Parameter Requirements

This checker does not require any parameters.

7.84.2 Non-Compliant Code Example

#include <vector>

void add_x_to_each_element_noncompliant(int x, std::vector<int> &v){

// not OK: loop to add x to each elementstd::vector<int>::iterator v_itr;for (v_itr = v.begin(); v_itr != v.end(); ++v_itr)

*v_itr += x;}

7.84.3 Compliant Solution

#include <vector>#include <algorithm>#include <functional>

void add_x_to_each_element_compliant(int x, std::vector<int> &v){

// OK: using an algorithm to add x to each elementtransform(v.begin(), v.end(), v.begin(),

std::bind2nd(std::plus<int>(), x));}

7.84. PREFER ALGORITHMS 211

7.84.4 Mitigation Strategies

Static Analysis

Compliance with this rule can be checked using structural staticanalysis checkers using the following algorithm:

1. For each for loop, check the criteria explained above, takingboth built-in and overloaded operators.

2. If the loop fulfills all criteria, generate a diagnostic.

7.84.5 References

A reference for this checker is: S. Meyers: “Effective STL”, Item 43:“Prefer algorithm calls to hand-written loops”.

212 CHAPTER 7. LIST OF COMPASS CHECKERS

7.85 Secure Coding : FIO07-A. Preferfseek() to rewind()

rewind() sets the file position indicator for a stream to the beginningof that stream. However, rewind() is equivalent to fseek() with0L for the offset and SEEK SET for the mode with the error returnvalue suppressed. Therefore, to validate that moving back to thebeginning of a stream actually succeeded, fseek() should be usedinstead of rewind().

7.85.1 Non-Compliant Code Example

The following non-compliant code sets the file position indicator ofan input stream back to the beginning using rewind().

1 FILE* fptr = fopen("file.ext", "r");2 if (fptr == NULL) {3 /* handle open error */4 }56 /* read data */78 rewind(fptr);9

10 /* continue */11

However, there is no way of knowing if rewind() succeeded or not.

7.85.2 Compliant Solution

This compliant solution instead using fseek() and checks to see ifthe operation actually succeeded.

1 FILE* fptr = fopen("file.ext", "r");2 if (fptr == NULL) {3 /* handle open error */4 }56 /* read data */78 if (fseek(fptr, 0L, SEEK SET) != 0) {9 /* handle repositioning error */

10 }1112 /* continue */13

7.85.3 Risk Assessment

Using rewind() makes it impossible to know whether the file posi-tion indicator was actually set back to the beginning of the file. Ifthe call does fail, the result may be incorrect program flow.

Rule Severity Likelihood Remediation Cost Priority LevelFIO07-A 1 (low) 1 (unlikely) 2 (medium) P2 L3

7.85. SECURE CODING : FIO07-A. PREFER FSEEK() TO REWIND() 213

Related Vulnerabilities

Search for vulnerabilities resulting from the violation of this rule onthe CERT website .

7.85.4 References

[ ISO/IEC 9899-1999:TC2 ] Section 7.19.9.2, ”The fseek function”;7.19.9.5, ”The rewind function”

214 CHAPTER 7. LIST OF COMPASS CHECKERS

7.86 Prefer Setvbuf To Setbuf

The functions setvbuf() and setbuf() are defined as follows:

void setbuf(FILE * restrict stream, char * restrict buf); intsetvbuf(FILE * restrict stream, char * restrict buf, int mode, size tsize);

setvbuf() is equivalent to setbuf() with IOFBF for mode and BUF-SIZE for size (if buf is not NULL) or IONBF for mode (if buf isNULL), except that it returns a nonzero value if the request couldnot be honored. For added error checking, prefer using setvbuf()over setbuf().

7.86.1 Parameter Requirements

No Parameter specifications.

7.86.2 Implementation

No implementation yet!

7.86.3 Non-Compliant Code Example

The following non-compliant code makes a call to setbuf() with anargument of NULL to ensure an optimal buffer size.

% write your non-compliant code exampleFILE* file;char *buf = NULL;/* Setup file */setbuf(file, buf);/* ... */

However, there is no way of knowing whether the operation suc-ceeded or not.

7.86.4 Compliant Solution

This compliant solution instead calls setvbuf(), which returnsnonzero if the operation failed.

% write your compliant code exampleFILE* file;

7.86. PREFER SETVBUF TO SETBUF 215

char *buf = NULL;/* Setup file */if (setvbuf(file, buf, buf ? _IOFBF : _IONBF, BUFSIZ) != 0) {/* Handle error */

}/* ... */

7.86.5 Mitigation Strategies

Static Analysis

Compliance with this rule can be checked using structural staticanalysis checkers using the following algorithm:

1. Write your checker algorithm

7.86.6 References

ISO/IEC9899-1999:TC2 FIO12-A. Prefer setvbuf() to setbuf()

216 CHAPTER 7. LIST OF COMPASS CHECKERS

7.87 Protect Virtual Methods

The Elements of C++ Style item #107 states

Do not expose virtual methods in the public interface ofa class. Use a public methods with a similar name to callthe protected virtual method.

7.87.1 Parameter Requirements

This checker takes no parameters and inputs source file.

7.87.2 Implementation

This pattern is checked using a simple AST traversal that seeksinstances of SgMemberFunctionDeclaration that have the public ac-cess modifier and the virtual function modifier boolean values setto true. Member functions that match this pattern are flagged asviolations.

7.87.3 Non-Compliant Code Example

This non-compliant code contains a virtual function in the publicinterface of a class.

class Class{int n;

public:Class() { n = publicVirtualFunction(); } //constructor~Class() {} //Destructor

virtual int publicVirtualFunction() { return 1; }}; //class Class

7.87.4 Compliant Solution

The compliant solution protects the virtual function and adds a pub-lic accessor to the virtual function.

class Class{int n;

protected:virtual int protectedVirtualFunction() { return 1; }

7.87. PROTECT VIRTUAL METHODS 217

public:Class() { n = publicVirtualFunction(); } //constructor~Class() {} //Destructorint publicVirtualFunction(){ return protectedVirtualFunction(); }

}; //class Class

7.87.5 Mitigation Strategies

Static Analysis

Compliance with this rule can be checked using structural staticanalysis checkers using the following algorithm:

1. Perform a simple AST traversal visiting all function declarationnodes.

2. For each function declaration check the “public” and “virtual”modifiers. If both “public” and “virtual” modifiers are set thenflag violation.

3. Report any violations.

7.87.6 References

Bumgardner G., Gray A., and Misfeldt T. The Elements of C++Style. Cambridge University Press 2004.

218 CHAPTER 7. LIST OF COMPASS CHECKERS

7.88 Push Back

Tests if the source uses front or back insertion in sequences us-ing insert or resize where a push front or push back could beused. The patterns are very simple and matches simple calls likevector.insert(vector.end(), ...).

In these case, push back and push front only are insured to beefficient. All other calls may be quadratic.

This test is inspired by the rule 80 of C++ Coding Standards: “Usethe accepted idioms to really shrink capacity and really erase ele-ments”.

7.88.1 Parameter Requirements

There is no parameter required.

7.88.2 Implementation

No implementation yet!

7.88.3 Non-Compliant Code Example

#include <vector>#include <list>

void g(){std::vector<int> v;v.insert(v.end(), 1);

v.resize(v.size() + 1, 1);

std::list<int>* vv = new std::list<int>();vv->insert(vv->begin(), 1);

}

7.88.4 Compliant Solution

#include <vector>#include <list>

void g(){std::vector<int> v;v.push_back(1);

7.88. PUSH BACK 219

v.push_back(1);

std::list<int>* vv = new std::list<int>();vv->push_front(1);

}

7.88.5 Mitigation Strategies

Static Analysis

Compliance with this rule can be checked using structural staticanalysis checkers looking for these patterns:

For all types T,where V variable of type vector<T>,where Vp variable of type vector<T>*,where L variable of type list<T>,where Lp variable of type list<T>*,where S variable of type slist<T>,where Sp variable of type slist<T>*,where D variable of type deque<T>,where Dp variable of type deque<T>*,where Value expression of type T,the check will look for these patterns in the source code.

V.resize(V.size() + 1, Value)Vp->resize(Vp->size() + 1, Value)D.resize(D.size() + 1, Value)Dp->resize(Dp->size() + 1, Value)L.resize(L.size() + 1, Value)Lp->resize(Lp->size() + 1, Value)V.resize(1 + V.size(), Value)Vp->resize(1 + Vp->size(), Value)D.resize(1 + D.size(), Value)Dp->resize(1 + Dp->size(), Value)L.resize(1 + L.size(), Value)Lp->resize(1 + Lp->size(), Value)V.insert(V.end(), Value)Vp->insert(Vp->end(), Value)D.insert(D.end(), Value)Dp->insert(Dp->end(), Value)L.insert(L.end(), Value)Lp->insert(Lp->end(), Value)S.insert(S.begin(), Value)Sp->insert(Sp->begin(), Value)D.insert(D.begin(), Value)Dp->insert(Dp->begin(), Value)L.insert(L.begin(), Value)

220 CHAPTER 7. LIST OF COMPASS CHECKERS

Lp->insert(Lp->begin(), Value)

For all resize and back insert patterns, push back could be used.For front insert patterns, push front could be used instead.

7.88.6 References

Alexandrescu A. and Sutter H. C++ Coding Standards 101 Rules,Guidelines, and Best Practices. Addison-Wesley 2005.

7.89. RIGHT SHIFT MASK 221

7.89 Right Shift Mask

Do not assume that a right shift operation is implemented as eitheran arithmetic (signed) shift or a logical (unsigned) shift. If E1 inthe expression E1 ¿¿ E2 has a signed type and a negative value,the resulting value is implementation defined and may be either anarithmetic shift or a logical shift. Also, be careful to avoid undefinedbehavior while performing a bitwise shift.

7.89.1 Parameter Requirements

No Parameter Required.

7.89.2 Implementation

Upon finding a right shift we trace parent pointers up until we finda bit and operator. If we find this bitwise and then we return. If wemake it to the basic block node of the statement we raise an alert.

7.89.3 Non-Compliant Code Example

For implementations in which an arithmetic shift is performed andthe sign bit can be propagated as the number is shifted.

int stringify;char buf[sizeof("256")];sprintf(buf, "%u", stringify >> 24);% write your non-compliant code example

If stringify has the value 0x80000000, stringify ¿¿ 24 evaluates to0xFFFFFF80 and the subsequent call to sprintf() results in a bufferoverflow.

7.89.4 Compliant Solution

For bit extraction, make sure to mask off the bits you are not inter-ested in.

int stringify;char buf[sizeof("256")];sprintf(buf, "%u", ((number >> 24) & 0xff));% write your compliant code example

222 CHAPTER 7. LIST OF COMPASS CHECKERS

7.89.5 Mitigation Strategies

Static Analysis

Compliance with this rule can be checked using structural staticanalysis checkers using the following algorithm:

1. Find the bitwise and

2. climb parent tree

3. alert if parent null or basicblock found.

7.89.6 References

ISO/IEC 9899-1999:TC2 [Dowd 06] Chapter 6, “C Language Is-sues” [ISO/IEC 9899-1999] Section 6.5.7, “Bitwise shift operators”[ISO/IEC 03] Section 6.5.7, “Bitwise shift operators”

7.90. SET POINTERS TO NULL 223

7.90 Set Pointers To Null

Dangling pointers can lead to exploitable double-free and access-freed-memory vulnerabilities. A simple yet effective way to eliminatedangling pointers and avoid many memory related vulnerabilities isto set pointers to NULL after they have been freed. Calling free()on a NULL pointer results in no action being taken by free().

7.90.1 Parameter Requirements

No Parameter specifications.

7.90.2 Implementation

7.90.3 Non-Compliant Code Example

In this example, the type of a message is used to determine howto process the message itself. It is assumed that message type isan integer and message is a pointer to an array of characters thatwere allocated dynamically. If message type equals value 1, the mes-sage is processed accordingly. A similar operation occurs when mes-sage type equals value 2. However, if message type == value 1 eval-uates to true and message type == value 2 also evaluates to true,then message will be freed twice, resulting in an error.

if (message\_type == value\_1) {/* Process message type 1 */free(message);

}/* ...*/if (message\_type == value\_2) {

/* Process message type 2 */free(message);

}

7.90.4 Compliant Solution

As stated above, calling free() on a NULL pointer results in no actionbeing taken by free(). By setting message equal to NULL after ithas been freed, the double-free vulnerability has been eliminated.

if (message_type == value_1) {/* Process message type 1 */free(message);

224 CHAPTER 7. LIST OF COMPASS CHECKERS

message = NULL;}/* ...*/if (message_type == value_2) {/* Process message type 2 */free(message);message = NULL;

}

7.90.5 Mitigation Strategies

Static Analysis

Compliance with this rule can be checked using structural staticanalysis checkers using the following algorithm:

1. Write your checker algorithm

7.90.6 References

ISO/IEC 9899-1999 MEM01-A. Eliminate dangling pointers

7.91. SINGLE PARAMETER CONSTRUCTOR EXPLICIT MODIFIER 225

7.91 Single Parameter Constructor Ex-plicit Modifier

The Elements of C++ Style item #104 states that

A compiler can use a single parameter constructor for typeconversions. While this is natural in some situations, itmight be unexpected in others. . . you can avoid this be-havior by declaring a constructor with the explicit key-word.

7.91.1 Parameter Requirements

This checker takes no parameters and inputs source file.

7.91.2 Implementation

This pattern is checked using a simple AST traversal that finds in-stances of SgFunctionDeclaration that are constructors with a singleparameter. If these SgFunctionDeclaration are not modified with the“explicit” keyword then a violation is flagged.

7.91.3 Non-Compliant Code Example

This non-compliant code has a single parameter constructor that isnot declared with the explicit keyword.

class Class{int num;public:Class( int n ){ num = n; }int getNum() const { return num; }

}; //class Class

7.91.4 Compliant Solution

The compliant solution declares the single parameter constructorwith the explicit keyword modifier.

class Class{int num;public:explicit Class( int n ){ num = n; }int getNum() const { return num; }

}; //class Class

226 CHAPTER 7. LIST OF COMPASS CHECKERS

7.91.5 Mitigation Strategies

Static Analysis

Compliance with this rule can be checked using structural staticanalysis checkers using the following algorithm:

1. Perform a simple AST traversal visiting all function declarationnodes.

2. For each function declaration, if node is constructor then checkthe size of its parameter list.

3. If the parameter list size of constructor is 1 and is not declaredwith the explicit modifier then flag violation.

4. Report any violations.

7.91.6 References

Bumgardner G., Gray A., and Misfeldt T. The Elements of C++Style. Cambridge University Press 2004.

7.92. SIZE OF POINTER 227

7.92 Size Of Pointer

Do not take the size of a pointer to a type when you are trying todetermine the size of the type. Taking the size of a pointer to a typealways returns the size of the pointer and not the size of the type.

This can be particularly problematic when tyring to determine thesize of an array.

7.92.1 Parameter Requirements

No Parameter specifications yet!

7.92.2 Implementation

Finds calls to the sizeof function. Checks argument for level ofpointer (ie pointer to pointer etc...) then checks the number of deref-erence levels. If these do not match an alert is raised.

7.92.3 Non-Compliant Code Example

This non-compliant code example mistakenly calls the sizeof() oper-ator on the variable d array which is declared as a pointer to doubleinstead of the variable d which is declared as a double.

double *d_array;size_t num_elems;/* ... */

if (num_elems > SIZE_MAX/sizeof(d_array)){/* handle error condition */

}else {d_array = malloc(sizeof(d_array) * num_elems);

}

The test of num elems is to ensure that the multiplication ofsizeof(d array) * num elems does not result in an integer overflow

For many implementaion, the size of a pointer and the size of double(or other type) is likely to be different. On IA-32 implementations,for example, the sizeof(d array) is four, while the sizeof(d) is eight.In this case, insufficient space is allocated to contain an array of 100values of type double.

228 CHAPTER 7. LIST OF COMPASS CHECKERS

7.92.4 Compliant Solution

Make sure you correctly calculate the size of the element to becontained in the aggregate data structure. The expression sizeof(*d array) returns the size of the data structure referenced byd array and not the size of the pointer.

double *d_array;size_t num_elems;/* ... */

if (num_elems > SIZE_MAX/sizeof(*d_array)){/* handle error condition */

}else {d_array = malloc(sizeof(*d_array) * num_elems);

7.92.5 Mitigation Strategies

Static Analysis

Compliance with this rule can be checked using structural staticanalysis checkers using the following algorithm:

1. Write your checker algorithm

7.92.6 References

ISO/IEC 9899-1999:TC2 [Viega 05] Section 5.6.8, “Use of sizeof()on a pointer type” [ISO/IEC 9899-1999] Section 6.5.3.4, “The sizeofoperator” [Drepper 06] Section 2.1.1, “Respecting Memory Bounds”

7.93. SECURE CODING : INT06-A. USE STRTOL() TO CONVERT A STRING TOKEN TO AN INTEGER229

7.93 Secure Coding : INT06-A. Use str-tol() to convert a string token to an integer

Use strtol() or a related function to convert a string token to aninteger. The strtol(), strtoll(), strtoul(), and strtoull()functions convert the initial portion of a string token to long int,long long int, unsigned long int, and unsigned long longint representation, respectively. These functions provide more ro-bust error handling than alternative solutions.

7.93.1 Non-Compliant Example

This non-compliant code example converts the string token storedin the static array buff to a signed integer value using the atoi()function.

1 int si;23 if (argc > 1) {4 si = atoi(argv[1]);5 }6

The atoi(), atol(), and atoll() functions convert the initial por-tion of a string token to int, long int, and long long int repre-sentation, respectively. Except for the behavior on error, they areequivalent to

1 atoi: (int)strtol(nptr, (char **)NULL, 10)2 atol: strtol(nptr, (char **)NULL, 10)3 atoll: strtoll(nptr, (char **)NULL, 10)4

Unfortunately, atoi() and related functions lack a mechanism forreporting errors for invalid values. Specifically, the atoi(), atol(),and atoll() functions:

7.93.2 Non-Compliant Example

This non-compliant example uses the sscanf() function to converta string token to an integer. The sscanf() function has the sameproblems as atoi().

1 int si;23 if (argc > 1) {4 sscanf(argv[1], "%d", &si);5 }6

7.93.3 Compliant Solution

This compliant example uses strtol() to convert a string token toan integer value and provides error checking to make sure that the

230 CHAPTER 7. LIST OF COMPASS CHECKERS

value is in the range of int.1 long sl;2 int si;3 char *end ptr;45 if (argc > 1) {67 errno = 0;89 sl = strtol(argv[1], &end ptr, 10);

1011 if (ERANGE == errno) {12 puts("number out of range\n");13 }14 else if (sl > INT MAX) {15 printf("%ld too large!\n", sl);16 }17 else if (sl < INT MIN) {18 printf("%ld too small!\n", sl);19 }20 else if (end ptr == argv[1]) {21 puts("invalid numeric input\n");22 }23 else if (’\0’ != *end ptr) {24 puts("extra characters on input line\n");25 }26 else {27 si = (int)sl;28 }29 }30

If you are attempting to convert a string token to a smaller integertype (int, short, or signed char), then you only need test theresult against the limits for that type. The tests do nothing if thesmaller type happens to have the same size and representation on aparticular compiler.

7.93.4 Risk Assessment

While it is relatively rare for a violation of this rule to result in asecurity vulnerability, it could more easily result in loss or misinter-preted data.

Rule Severity Likelihood Remediation Cost Priority LevelINT06-A 2 (medium) 2 (probable) 2 (medium) P8 L2

Related Vulnerabilities

Search for vulnerabilities resulting from the violation of this rule onthe CERT website .

7.93.5 References

[ Klein 02 ] [ISO/IEC 9899-1999 ] Section 7.20.1.4, ”The strtol, strtoll, strtoul,

7.93. SECURE CODING : INT06-A. USE STRTOL() TO CONVERT A STRING TOKEN TO AN INTEGER231

and strtoull functions,” Section 7.20.1.2, ”The atoi, atol, and atollfunctions,” and Section 7.19.6.7, ”The sscanf function”

232 CHAPTER 7. LIST OF COMPASS CHECKERS

7.94 Sub Expression Evaluation Order

This checker detects if there exist, within an expression, sub-expressions that update the same variable. As the order of eval-uation of such expressions is not guaranteed to be left-to-right, anyof the sub-expressions can be taken place first.

7.94.1 Parameter Requirements

None.

7.94.2 Implementation

This checker uses a simple traversal. For every function call state-ment, the checker examines 1) whether the function call has sub-expressions that update variables and 2) the variables updated areidentical.

7.94.3 Non-Compliant Code Example

int bar(int a, int b);

void foo(){int i = 0;

i = bar(++i, ++i); // either ++i could be evaluated firsti = bar((i=3), (i=4)); // no particular order is guaranteed.

}

7.94.4 Compliant Solution

int bar(int a, int b);

void foo(){int i = 0;

i = bar(2, 3); // finei = bar((i=2), 3); //fine

}

7.94. SUB EXPRESSION EVALUATION ORDER 233

7.94.5 Mitigation Strategies

Static Analysis

Compliance with this rule can be checked using structural staticanalysis checkers using the following algorithm:

1. For each node, check if the node is a function call statement.

2. Examine if the function call has sub-expressions that updatevariables.

3. If yes, examine further if the variables updated are identical.

7.94.6 References

The Programming Research Group, High-Integrity C++ CodingStandard Manual, Item 10.3: “Do not assume the order of evalu-ation of operands in an expression.”

234 CHAPTER 7. LIST OF COMPASS CHECKERS

7.95 Ternary Operator

This checker detects a expression that uses the ternary operator.The rationale for this checker is, according to “High-Integrity C++Coding Standard Manual”, because evaluation of a complex condi-tion is best achieved through explicit conditional statements.

7.95.1 Parameter Requirements

None.

7.95.2 Implementation

This checker is implemented with a simple traversal. It traversesAST, checks if a statement uses a ternary operator, and reports it ifyes.

7.95.3 Non-Compliant Code Example

void foo(){int i = 0;int j;

(i==3) ? (j=1) : (j=2);}

7.95.4 Compliant Solution

void foo(){int i = 0;int j;

if(i == 4)j = 1;elsej = 2;}

7.95.5 Mitigation Strategies

Static Analysis

Compliance with this rule can be checked using structural staticanalysis checkers using the following algorithm:

7.95. TERNARY OPERATOR 235

1. For each node, check if a node represents a ternary operator.

2. If yes, report it

7.95.6 References

The Programming Research Group, High-Integrity C++ CodingStandard Manual, Item 10.20: “Do not use the thernary operator(?:)in expressions.”

236 CHAPTER 7. LIST OF COMPASS CHECKERS

7.96 Time t Direct Manipulation

“CERT Secure Coding MSC05-A” states

time t is specified as an “arithmetic type capable of rep-resenting times.” However, how time is encoded withinthis arithmetic type is unspecified. Because the encodingis unspecified, there is no safe way to manually performarithmetic on the type, and, as a result, the values shouldnot be modified directly.

7.96.1 Parameter Requirements

This checker takes no parameters and inputs source file.

7.96.2 Implementation

This pattern is checked using a simple AST traversal that visitsall binary operation nodes. For each binary operation node, if thenode is a arithmetic expression then check the type of its left andright hand side operands. If either operand type is time t then flagviolation.

7.96.3 Non-Compliant Code Example

This code attempts to execute do some work() multiple times untilat least seconds to work has passed. However, because the en-coding is not defined, there is no guarantee that adding start toseconds to work will result adding seconds to work seconds.

#include <time.h>

int do_work(int seconds_to_work){time_t start;start = time( NULL );

if (start == (time_t)(-1)) {/* Handle error */

}while (time(NULL) < start + seconds_to_work){//do_some_work();

}

return 0;}

7.96. TIME T DIRECT MANIPULATION 237

7.96.4 Compliant Solution

This compliant solution uses difftime() to determine the differ-ence between two time t values. difftime() returns the numberof seconds from the second parameter until the first parameter andreturns the result as a double.

#include <time.h>

int do_work(int seconds_to_work) {time_t start;time_t current;start = time(NULL);current = start;

if (start == (time_t)(-1)) {/* Handle error */

}while (difftime(current, start) < seconds_to_work) {current = time(NULL);if (current == (time_t)(-1)) {

/* Handle error */}//do_some_work();

}

return 0;}

7.96.5 Mitigation Strategies

Static Analysis

Compliance with this rule can be checked using structural staticanalysis checkers using the following algorithm:

1. Perform simple AST traversal on all binary operation nodes.

2. For each binary operation node, if node is arithmetic expressionthen determine the type of its left and right hand side operands.

3. If either the left or right hand side is type time t then flagviolation.

4. Report any violations.

7.96.6 References

Secure Coding : MSC05-A. Do not manipulate time t typed valuesdirectly

238 CHAPTER 7. LIST OF COMPASS CHECKERS

7.97 Unary Minus

The unary minus operator should only be used with signed types,as its use with unsigned types will never result in a negative value.This checker reports any uses of the built-in unary minus operatoron an unsigned type.

7.97.1 Parameter Requirements

This checker does not require any parameters.

7.97.2 Non-Compliant Code Example

unsigned int f_noncompliant(unsigned int u){

return -u;}

7.97.3 Compliant Solution

int f_compliant(int n){

return -n;}

7.97.4 Mitigation Strategies

Static Analysis

Compliance with this rule can be checked using structural staticanalysis checkers using the following algorithm:

1. Check the type of the operand of any unary minus expression;emit a diagnostic if it is an unsigned integer type.

7.97.5 References

A reference for this rule is: The Programming Research Group:“High-Integrity C++ Coding Standard Manual”, Item 10.21: “Ap-ply unary minus to operands of signed type only.”

7.98. UNINITIALIZED DEFINITION 239

7.98 Uninitialized Definition

This test ensures that all variables are initialized at their point ofdefinition. The detector will report all variable declarations withoutinitializer expressions, except for some special cases:

• Variables declared extern: Such declarations refer to variablesdefined elsewhere, initializers are therefore not required at thispoint.

• Variables declared static: These variables are automatically ini-tialized to 0 (of the appropriate type) if no explicit initializeris present.

• Class member variables: The class constructor is responsiblefor initializing such variables.

• Variables of class type: Class objects are default-initialized ifno explicit initializer expression is present.

• Variables declared at file (‘global’) scope: File scope declara-tions are implicitly static; they can be changed to extern by anexplicit modifier. One of the above cases will always apply.

7.98.1 Parameter Requirements

This checker does not require any parameters.

7.98.2 Non-Compliant Code Example

void f_noncompliant(){

int x; // not OK, no initializer}

7.98.3 Compliant Solution

struct foo {int member; // OK, class member

};

void f_compliant(int n){

int x = n; // OK, initializer presentstatic int y; // OK, staticstruct foo st; // OK, class type (has constructor)extern int not_here; // OK, extern

}

240 CHAPTER 7. LIST OF COMPASS CHECKERS

7.98.4 Mitigation Strategies

Static Analysis

Compliance with this rule can be checked using structural staticanalysis checkers using the following algorithm:

1. For each variable declaration without an initializer expression,check the above criteria.

2. If none of the exceptions apply, generate a diagnostic.

7.98.5 References

A reference for this rule is: H. Sutter, A. Alexandrescu: “C++Coding Standards”, Item 19: “Always initialize variables”.

7.99. UPPER RANGE LIMIT 241

7.99 Upper Range Limit

By always using inclusive lower limits and exclusive upper limits,a whole class of off- by-one errors is eliminated. Furthermore, thefollowing assumptions always apply: 1)the size of the interval equalsthe difference of the two2) the limits are equal if the interval is empty3) the upper limit is never less than the lower limit

Examples: instead of saying x¿=23 and x¡=42, use x¿=23 and x¡43.

7.99.1 Parameter Requirements

No parameters required.

7.99.2 Implementation

In a fairly straight-forward implementation we search for the greaterthan or equal to operator.

7.99.3 Non-Compliant Code Example

int x = 5;if (x >= 5){x++;}% write your non-compliant code example

% write your non-compliant code example

7.99.4 Compliant Solution

int x = 5;if (x > 4){x++;}% write your non-compliant code example

% write your compliant code example

242 CHAPTER 7. LIST OF COMPASS CHECKERS

7.99.5 Mitigation Strategies

Static Analysis

Compliance with this rule can be checked using structural staticanalysis checkers using the following algorithm:

1. find greater than or equal to operator

2. raise alert

7.99.6 References

Abbreviated Code Inspection Checklist Section 11.1.2, Control Vari-ables”

7.100. VARIABLE NAME EQUALS DATABASE NAME 243

7.100 Variable Name Equals DatabaseName

For some member function accesses the name of the local variablethat gets assigned the result of the function call should have a nameequal to the first argument. [ALE3D] E.g:

real8 *sx = regM->fieldReal("sx") ;real8 *syy = regM->fieldReal("sy") ;

Where the name of the local variable is not the same as the namein the database for ”syy”, but it is the same for ”sx”.

This checker will only report the locations of the assign expressionswhere this rule is not followed.

7.100.1 Parameter Requirements

The checker takes the name of the class and member function thaton call should assign it’s result to a variable with the same nameas the first argument. The arguments are ”VariableNameEquals-DatabaseName.ClassName=CLASSNAME” and ”VariableNameE-qualsDatabaseName.MemberFunctionName=MEMFUNCNAME”.

7.100.2 Implementation

The checker will look for a function call to the member functionwithin the class that we are looking for. When such a call is foundit assumes that the lhs of the last assign expression is the variableaccess that we are interested in. If the name of that variable doesnot satisfy the rule we report an error.

7.100.3 Non-Compliant Code Example

#include <string>class MixMatmodel{

public:double fieldReal(std::string str){ return 1; };

};

int main(){MixMatmodel x;

int y = x.fieldReal("test1");int z = x.fieldReal("test1:test2");

244 CHAPTER 7. LIST OF COMPASS CHECKERS

int test2 = x.fieldReal("test1:test2:test3");

};

7.100.4 Compliant Solution

#include <string>class MixMatmodel{

public:double fieldReal(std::string str){ return 1; };

};

int main(){MixMatmodel x;

int test1 = x.fieldReal("test1");int test2 = x.fieldReal("test1:test2");int test3 = x.fieldReal("test1:test2:test3");

};

7.100.5 Mitigation Strategies

Static Analysis

Compliance with this rule can be checked using structural staticanalysis checkers using the following algorithm:

1. Travese the AST

2. For each call to the member function we are interested in makesure field name is equal to the string provided as an argument.

7.100.6 References

7.101. VOID STAR 245

7.101 Void Star

This checker enforces the guideline of section 87 of the Elements ofC++ Style (Misfeldt and al., 2004). No public method should beusing void* type for arguments or return type. If needed, it can bewrapped.

7.101.1 Parameter Requirements

There is not parameter requirement.

7.101.2 Non-Compliant Code Example

class A {public:const void* getData();

};

7.101.3 Compliant Solution

class A {public:const Data getData();

};

7.101.4 Mitigation Strategies

Static Analysis

Compliance with this rule can be checked using structural staticanalysis checkers using the following algorithm:

1. For each public member function declaration, check all argu-ment types and the return type are not void*.

7.101.5 References

Bumgardner G., Gray A., and Misfeldt T. The Elements of C++Style. Cambridge University Press 2004.

246 CHAPTER 7. LIST OF COMPASS CHECKERS

Chapter 8

Appendix

8.1 Design And Extensibility of Com-pass Detectors

The design of the detectors is intended to be simple and with littlerequired to be specified to build individual detectors. Of coursesome detectors may be non-trivial (e.g. null pointer analysis, bufferoverflow detectors, etc. (not yet provided in Compass)) the majorityare simple. All detectors are meant to be side-effect free and are thesubject of separate research to independently provide automatedcombining (evaluation of multiple patterns in a single AST traversal)and parallelization of the pattern evaluations on the AST.

8.1.1 Input Parameter Specification

Parameters to all detectors are specified in an input parameter file(if required). This permits numerous knobs associated with differentpattern detectors and separate input files be specified for differentsoftware projects.

8.1.2 Pattern Detection

Currently it is assumed that patterns will be detected as part ofa traversal of the AST. See the ROSE Tutorial for example andgeneral documentation on the different sorts of traversals possiblewithin ROSE.

8.1.3 Output Specification

Output of source position information specific to detected pat-terns are output in GNU standard source position formats. See

247

248 CHAPTER 8. APPENDIX

http://www.gnu.org/prep/standards/html node/Errors.htmlfor more details on this format specification and now it is used byexternal tools (e.g. emacs, etc.).