# V575. Function receives suspicious argument.

The analyzer has detected a potential error: the function receives a suspicious value as an actual argument.

The example:

    bool Matrix4::operator==(const Matrix4 &other) const
    {
      if (memcmp(this, &other, sizeof(Matrix4) == 0))
        return true;
      ....
    }

Here is a typo: a parenthesis is misplaced. Unfortunately, this error may go unnoticed and exist in the code for a long time. Due to this typo, the size of compared memory is evaluated with the `sizeof(Matrix4) == 0` expression. Since the expression result is `false`, 0 memory bytes are compared. The fixed code:

    bool Matrix4::operator==(const Matrix4 &other) const
    {
      if (memcmp(this, &other, sizeof(Matrix4)) == 0)
        return true;
      ....
    }

Here is another example. The diagnostic rule detects cases where an array consisting of `enum` elements is filled using the `memset` function and one element size is unequal to one byte. The filling will not operate correctly because it is not each element but rather each byte that will get filled with a value.

The example of incorrect code:

    enum E { V0, V1, V2, V3, V4 };
    E array[123];
    memset(array, V1, sizeof(array));

If the compiler allocates 4 bytes for each element, then each element will have the `0x01010101` value instead of the expected `0x00000001 (V1)`.

To fill the array correctly, the code should be modified as follows:

    for (size_t i = 0; i < sizeof(array) / sizeof(array[0]); ++i)
    {
      array[i] = V1;
    }

Another way to fix:

    std::fill(begin(array), end(array), V1);

Note. NULL is a suspicious argument.

Sometimes developers use constructs like the one below to evaluate the amount of memory required for a buffer:

    const char* format = getLocalizedString(id, resource);
    int len = ::vsprintf(NULL, format, args);
    char* buf = (char*) alloca(len);
    ::vsprintf(buf, format, args);

However, it is important to remember that calling `::vsprintf(NULL, format, args)` is incorrect. Here is what MSDN has to say about it:

    int vsprintf(*buffer, char *format, va_list argptr);
    ....

> vsprintf and vswprintf return the number of characters written, not including the terminating null character, or a negative value if an output error occurs. If buffer or format is a null pointer, these functions invoke the invalid parameter handler, as described in Parameter Validation. If execution is allowed to continue, these functions return -1 and set errno to EINVAL.

## Additional Settings

There are several options for additional configuration of this diagnostic rule.

### For null pointers

The diagnostic rule relies on information about whether a particular pointer could be null. In some cases, this information is retrieved from the table of annotated functions, which is stored within the analyzer.

One of such functions is `malloc`, which can return `NULL`. Using the pointer returned by `malloc` without a prior check may result in null dereference.

Sometimes users would like to change the analyzer behavior to assume that `malloc` cannot return `NULL`. For example, they can use the system libraries that handle out-of-memory errors in a specific way.

To indicate to the analyzer the function that can return a null pointer, use the additional settings, described in the section "How to tell the analyzer that a function can or cannot return nullptr".

### For passed ranges

If a function accepts the boundaries of a range as parameters, the corresponding parameters can be marked as the lower and upper bounds. This provides the analyzer with additional information that helps identify precondition violations (e.g., the lower bound value being greater than the upper bound).

To mark parameters as the lower and upper bounds, use the user annotation mechanism in JSON and the `lower_bound` and `upper_bound` attributes, respectively. Additionally, if there is a parameter which value is checked to be within the range, it should be marked as `in_range_value`. If there is no such parameter, marking only the lower and upper bounds is enough.

The example. There is a function semantically similar to `std::clamp` with the following signature:

    bool foo(int v, int lo, int hi);

The function checks that the value of the first parameter lies within the range provided by the second (lower bound) and third (upper bound) parameters.

Let's say there is the following function call:

    if (foo(x, 100, 0))
    {
      ....
    }

The arguments for the lower and upper bounds are swapped. To get the warning on the function call, mark the first parameter of the `foo` function as `in_range_value`, the second as `lower_bound`, and the third as `upper_bound`.

The fixed code:

    if (foo(x, 0, 100))
    {
      ....
    }

See the examples of function parameter annotations here.

Note. This annotation is required only for user-defined functions.

This diagnostic is classified as:

CWE-1164 CWE-628 CERT-EXP37-C

You can look at examples of errors detected by the V575 diagnostic.