CodeSonar and assert()

assert() statements can cause problems for the CodeSonar analysis if the particular implementation of assert() is such that that CodeSonar cannot determine that execution ends when the statement condition fails.

This section outlines the various issues you may encounter when using assert(), and describes ways to handle these issues.



Unexpected Behavior

In some cases users may get unexpected results when analyzing code that invokes the assert() macro. These unexpected results fall into two main categories: unexpected reachability after an assertion and unexpected unreachability after an assertion.

Unexpected reachability after assertion

Example Unexpected Null Pointer Dereference warning in line 3 of the following.
/* 1 */ int *p = malloc(4);
/* 2 */ assert(p);
/* 3 */ *p = 42; 
Issue There are two major causes of this phenomenon: usually either assert() is being preprocessed away or the assert() definition calls an undefined abort function.
  • assert() is being preprocessed away.
    This typically means that NDEBUG is defined in the build system. In this situation, invocations of the assert() macro are preprocessed away and so are not addressed by the CodeSonar analysis.
  • The assert() definition calls an undefined abort function.
    For example, suppose the assert() definition is something like the following.
    #define assert(x) do{ if( !(x) ) some_undefined_abort_function(); }while(0)
    
    If the definition of some_undefined_abort_function() is not present in the project, CodeSonar is not able to determine that it terminates execution.
Resolution If you do not want assert() invocations to be preprocessed away, make sure NDEBUG is not defined in the build system.

If the assert() definition calls an undefined abort function, either

  • make sure the definition of some_undefined_abort_function() is included in the project, or
  • instruct CodeSonar to treat invocations of some_undefined_abort_function() the same way it treats invocations of abort(). One of the simplest ways to accomplish this is with a FUNCTION_MAP rule in the appropriate configuration file:
    FUNCTION_MAP += some_undefined_abort_function -> abort
           
    
    A number of other mechanisms are also available: for full details and examples, see Manipulating the Input to the Build and Analysis

Unexpected unreachability after assertion

Example Unexpected Unreachable Data Flow warning in line 2 of the following.
/* 1 */ assert(p);
/* 2 */ i = 42; 
Issue This typically occurs when the <assert.h> header inclusion has been unintentionally omitted from the source file and so assert() is instead resolved to the lesser-known libc assert() function (as opposed to the macro), which has different behavior: in particular, it always aborts execution. Not all libc implementations contain this function, but some do, and CodeSonar is not aware of which libc version is being used.
Resolution #include the <assert.h> header as necessary.

Alternatives to assert()

In some cases, you may prefer to avoid use of assert() entirely. If you still wish to make use of assertion functionality and have CodeSonar understand that functionality correctly, there are two main options:

Use csonar_assert()

CodeSonar provides the csonar_assert() macro for use in cases where assert() is not suitable.

If your code includes invocations of csonar_assert() make sure you do all of the following.

For more information, see Implementing and Including Custom Checks with the Extension API.

Define your own assertion macro

You can define your own assertion macro, with one definition to be used by the CodeSonar build/analysis and another definition to be used otherwise. For example, if you choose to name the macro my_csonar_assert():

#ifdef __CODESONAR__
/* terminate execution when the assertion does not hold */
#define my_csonar_assert(c) do{ if( !(c) ) for(;;){} }while(0)
#else
/* no-op */
#define my_csonar_assert(c) ((void)0)
#endif

Manipulating the Input to the Build and Analysis describes and provides examples of several methods suitable for incorporating this code into your project: