Reducing Static Analysis False Positives Using SAL

Microsoft Source Annotation Language (SAL) enables sharper static analysis of external routines that are not provided in source form. Subroutine declarations can be annotated with a set of SAL macros that describe proper usage. Violations of the constraints implied by SAL annotations are reported during static analysis.

The SAL macros are defined in a system include file (sal.h) provided by the Visual Studio* IDE. Microsoft has annotated a number of system include files with SAL. These annotations provide enhanced checking for system routines such as C library routines.

Microsoft has defined two sets of SAL macros:

  • The recommended macros begin with a single underscore and an upper case letter.

  • The deprecated macros begin with two underscores.

For example: The macro used to annotate an ordinary input parameter is _In_ (recommended) or __in (deprecated). Static analysis supports only the recommended macro set and ignores the deprecated macro set. Starting with the Windows* 8 operating system, the recommended SAL macros will be used in all Windows* system include files.

The sal.h include file chooses between two expansions of the SAL macros. When an analysis tool is not involved, the SAL macros expand to nothing. When an analysis tool such as static analysis is involved, the macro _PREFAST_ is implicitly #defined, and this causes the SAL macros to expand into their active form. It is possible to suppress SAL processing during a static analysis build by adding the /U_PREFAST_ command line switch.

You can add SAL annotations yourself. For example, you might choose to annotate the include files that declare the API functions for a component you receive in binary form from a third party. This allows calls you make through that API to be checked when you analyze your code. Alternatively, you can annotate include files for components you develop so that users of those components can police their usage of your API. For details on how to encode SAL macros, search Visual Studio* documentation for the phrase SAL annotations.

The following is an example showing the kinds of checking enabled through SAL:

#include <sal.h>
extern int sum_array(size_t size, _In_count_(size) int *buff);

int main(int argc, char **argv) {
    int a[5] = {1, 2, 3, 4, 5};
    return (sum_array (sizeof(a), a));
}

Here we have an extern routine, sum_array, with two parameters: a size_t size and a pointer buff. The buff parameter is annotated with the SAL macro _In_count_(size). This says that buff is an input parameter that points to a buffer whose size in elements is given by the size parameter. This is an appropriate annotation for a subroutine with an implementation that looks like this:

int sum_array(size_t size, int *buff) {
    size_t i;
    int sum = 0;
    for (i = 0; i < size; i++) {
        sum += buff[i];
    }
    return (sum);
}

The call to sum_array in the main routine violates the SAL constraint. The value of the first argument provides the size of the array in bytes, not elements. Accordingly, this call would index off the end of the array inside sum_array. Static analysis will detect this error even if the source for the implementation of sum_array is not provided.

See Also


Supplemental documentation specific to a particular Intel Studio may be available at <install-dir>\<studio>\documentation\ .

For more complete information about compiler optimizations, see our Optimization Notice.