Daniel Rose
Daniel Rose

Reputation: 17648

PREfast annotation for structure members

In my company's code we have general get() and set() methods for interop between certain components. However, if I try to run PREfast I get inundated with warnings because PREfast doesn't realize that the get() method initializes the given parameters.

The problem is that since those methods are very general, they don't simply take a parameter (which I could mark with _Out_ or similar, but an array of structs which holds the data as to which data should be returned.

In code (greatly simplified):

typedef struct
{
    int type;
    int* data;
} ARGS;

void get(int count, ARGS* args)
{
    for (int i = 0; i < count; i++)
        *(args[i].data) = 42; // Actually handled by internal methods
}

// Sample Usage
void foo()
{
    int value;
    ARGS args[1];

    args[0].type = 1234;
    args[0].data = &value;

    get(1, args);

    // Do something with value
    // PREfast complains that value is uninitialized (error C6001)
    printf("%d", value);
}

Is there any way to annotate this so PREfast knows that args.data is initialized by get()? Or is this too complex for PREfast to handle?

EDIT: If I use get(1, &args), then the warning goes away. So there is some heuristic in PREfast which can handle this case, but I haven't found out if it is possible to trigger it externally:

void get2(int count, ARGS(* args)[1]) // Needs the size of args, or it won't compile below
{
    for (int i = 0; i < count; i++)
        *(*args)[i].data = 42; // Actually handled by internal methods
}

// Sample Usage
void foo2()
{
    int value;
    ARGS args[1];

    args[0].type = 1234;
    args[0].data = &value;

    get2(1, &args);

    // Do something with value
    printf("%d", value);
}

Upvotes: 1

Views: 1014

Answers (1)

askmish
askmish

Reputation: 6684

This should fix the warning.

void foo()
{
   int value=0;
  ...
}

Note that get() will be called in runtime only. Since, PREfast is a static analysis tool, it might report that the value is uninitialized. Nevertheless, initializing a variable before use is always a best practice in C.

Another way would be to use the PREfast suppress as below:

void foo()
{
    int value;
    ARGS args[1];

    args[0].type = 1234;
    args[0].data = &value;

    get(1, args);

    // Do something with value
    // PREfast complains that value is uninitialized (error C6001)
    #pragma prefast(suppress:C6001 , "PREfast noise: the variable value will be initialized by get method in a line above")
    printf("%d", value);
}

It suppresses the warnings in the next line after the suppress statement.

Also, do add the following code in you header files(or source files) just before using the pragma prefast in your code:

#ifndef _PREFAST_
#pragma warning(disable:4068)
#endif

to avoid 4068 warning to be flagged. NOTE: pragma prefast is an extension to the PREfast AST compiler only and may not be supported by other compilers.

Upvotes: 1

Related Questions