JavaScript is not currently enabled, but is required for full CodeSonar manual search and browse functionality.

If you are viewing this file in your hub's Web GUI, enable JavaScript in your browser: you will also need it for GUI functionality.

If you opened this file directly from disk, your browser may be directly suppressing JavaScript functionality: certain browsers perform this suppression on local files (but not files delivered by web servers) for security reasons.

CodeSonar® 9.2p0 CONFIDENTIAL CodeSecure Inc
C and C++

Authoring Library Models

This section describes how to write your own CodeSonar library models and include them in your analyses.



When to Write Your Own Models

There are two situations in which you should consider writing your own models for library (or other) functions.

Alternatives

The following configuration file options allow model implementation to be completely avoided in certain cases.

FUNCTION_MAP Tells CodeSonar that function A works like function B, meaning that no implementation/model need be provided for A.
MALLOC_FAILURE_BEHAVIOR Set this appropriately for the behavior you are interested in: there is no need to implement your own malloc()/calloc()/alloca()/realloc/new/new[] models to handle specific failure behaviors.
NEW_FAILURE_BEHAVIOR Set this appropriately for the C++ runtime you are interested in: there is no need to implement your own new/new[] models to handle specific failure behaviors.

Writing and Including a Model

If you have determined that you need to create your own model, you will need to write source code for the model and then include it in CodeSonar analyses of the appropriate project or projects.

There are two options for adding a new library model to your project: creating separate model files and augmenting project source code.

Separate model files

Building separate model files into the CodeSonar project before building and analyzing the software project allows you to separate the model source from the software project source.

Suppose that you have a project called myproj, a Makefile for building the normal software project, and you are writing library models suitable for compiling with gcc.

1. Write Create one or more dedicated source files for your models. Write C or C++ code for each function you are modeling (see guidelines and examples). Make sure that the function signatures of the models match the signatures of the original functions.
2. Add libmodels to include path. Include the following rule in the general project configuration file.
EDG_FRONTEND_OPTIONS_APPEND += -Icsonar_libmodels_path
where csonar_libmodels_path is the path to the codesonar/libmodels subdirectory of the CodeSonar installation directory.

If the path contains spaces, double-quote it. For example:

EDG_FRONTEND_OPTIONS_APPEND += "-IC:\Program Files\CodeSecure\CodeSonar\codesonar\libmodels"
(You can skip this step if your model does not make use of the Extension API.)
3. Build the models Use codesonar build to observe compilation of the model source file (say, compiling mymodels.c):
codesonar build myproj host:port gcc -c mymodels.c

CodeSonar will observe the compilation of mymodels.c, and update the definition of myproj accordingly.

4. Build remainder of project Invoke codesonar analyze on the normal software build:
codesonar analyze myproj host:port make
CodeSonar will:
  • Observe the execution of the normal software build invoked by make.
  • Update the definition of myproj based on the observed compilations (the definitions resulting from building the models will remain in the project).
  • Run the CodeSonar analysis on the updated myproj.

Augmenting software project source

Augmenting software project source allows you to avoid creating separate source files for models at all. This is both an advantage (fewer steps for building and analyzing, and fewer files to manage) and a potential disadvantage (your project source files are changed).

Suppose you have a project called myproj and a Makefile for building the normal software project.

1. Write Choose a suitable source file in your software project. Write C/C++ code for each function you are modeling directly in this file (see guidelines and examples), guarded by #ifdef __CODESONAR__ ... #endif.
/* project source file */
/* ... */
/* normal contents of source file */
/* ... */

#ifdef __CODESONAR__ 
/* put model code here */
#endif

/* ... */
/* remainder of normal contents of source file */
/* ... */

Make sure that the function signatures of the models match the signatures of the original functions.

2. Add libmodels to include path. Include the following rule in the general project configuration file.
EDG_FRONTEND_OPTIONS_APPEND += -Icsonar_libmodels_path
where csonar_libmodels_path is the path to the codesonar/libmodels subdirectory of the CodeSonar installation directory.

If the path contains spaces, double-quote it. For example:

EDG_FRONTEND_OPTIONS_APPEND += "-IC:\Program Files\CodeSecure\CodeSonar\codesonar\libmodels"
(You can skip this step if your model does not make use of the Extension API.)
3. Build Run the CodeSonar build/analysis on the project.
codesonar analyze myproj make

Guidelines

Where possible, a function model should be a real implementation of the function in terms of existing library functions. The models shipped with CodeSonar have been designed to express important relationships clearly and in many cases have useful warning checks associated with them. For example, if the function to be modeled carries out dynamic allocation then the model should call a suitable allocator model such as malloc().

The CodeSonar Extension API functions and macros provide useful functionality for cases where existing models can be used but additional modeling is needed, or where no existing model is suitable at all.

Library Model Macros and Functions describes the models that are most commonly called by other models, and notes the most useful CodeSonar extension macros.

When you are writing models, consider the following questions.

Do you want CodeSonar to treat your model as a library function?
If so, make sure symbol __CSURF_MARKER_LIBRARY_FUNCTION__ is defined at the start of the function. If a function f() is treated as a library function:
What values does the function write and return, where are those values stored, and how are the values related to the function's formal parameters and to global variables in the program?
Consider the return value of the function (if any), as well as any parameters or non-local variables that the function writes to. Essentially, the model should read from and write to the correct memory addresses with the correct values under the correct conditions. Note that this includes accounting for offsets in arrays and other compound data types. Calling memset() is often useful in these cases.
Are there cases where the function doesn't return at all?
The model should fail to return in the same cases. One way to accomplish this is to call _exit().

Notes For Writing C++ Models

When you are modeling C++ functions, the following additional requirements apply.

Examples

Example 1: plus()

The return value of plus() is the sum of its arguments.

double plus(double x, double y) { return(x+y); }

Example 2: div()

The return value of div() depends on the values of both its arguments. Note that the model populates both fields of the return value with values correctly computed from the formal parameters. Using the "/" operator ensures that div() calls will be included in Division By Zero checks.

div_t div(int numer, int denom) {
    div_t rv;
    rv.quot = numer / denom;
    rv.rem = numer % denom;
    return rv;
}

Example 3: my_calloc()

Function my_calloc() is a allocator that initializes the allocated block. Note that the model's use of malloc() will cause my_calloc() to be included in Leak and Dynamic Allocation After Initialization checks.

void *my_calloc(size_t nelem, size_t elsize) {
    void *rv = malloc(nelem*elsize);
    int i;
    if( !rv ) return (void*)0;
    rv = memset(rv, 0, nelem*elsize);
    return rv;
}

Example 4: close_and_rest_a_while()

Function close_and_rest_a_while() closes a file and then waits (at least) a specified amount of time before returning. The model uses a call to close() to model the file-closing and a call to sleep() model the waiting. Note that this use of close() in the model will cause close_and_rest_a_while() to be included in Misaligned Object, Type Mismatch, Double Close, Use After Close, and Negative File Descriptor checks.

int close_and_rest_a_while(int fd, int secs) {
    int c = close(fd);
    sleep(secs);
    return(c);
}
 

To report problems with this documentation, please visit https://support.codesecure.com/.