Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

clang-analyze: how to avoid "garbage value" warning?

When checking

#include <stdio.h>
#include <stdlib.h>

int main(void)
{
    char    c[20];
    size_t  l;

    l = fread(c, sizeof c, 1, stdin);
    if (l != 1)
        return 1;

    return c[0] == 42;
}

with clang, I get

$ clang  --analyze -Xclang -analyzer-checker=alpha x.c
x.c:13:14: warning: The left operand of '==' is a garbage value
        return c[0] == 42;
               ~~~~ ^

$ clang -v
clang version 7.0.1 (Fedora 7.0.1-4.fc29)

Is there really a chance that c contains garbage at this point? If not, how can I avoid the warning (without the obvious initialization of c)?

Update

Because it seems to be common consensus, that this is a false positive, I want to focus on the way how to avoid the warning.

It is true that fread() is a standard function and analyzers should know their semantics as they are doing e.g. for memset() already. But I am interested in a more generic way which can be used e.g. on library functions.

I would call some special function (let call it assert_defined()) in a way like

    l = fread(c, sizeof c, 1, stdin);
    assert_defined(c, l * sizeof c);

which is

  • a noop
  • but lets the compiler/analyzer think that l * sizeof c bytes at c are initialized

Does clang know annotations like

inline static void assert_defined(void const *p, size_t cnt) 
   __attribute__((__dear_compiler_this_memory_is_not_garbage__(1,2)))
{
}

or are there tricks like the related

int i = i;

which prevents gcc to emit "uninitialized warnings"?

like image 897
ensc Avatar asked Mar 07 '19 17:03

ensc


1 Answers

Yes it could contain garbage - if fread() fails.

For the analyser to understand that the check guarantees c[0] is not read if fread fails would require the analyser to understand the semantics of the fread() function. That's computationally expensive task for any non-trivial code, and would require either sight of the library source, or encoding of the standard library semantics - which is possible but would only spot a small subset of issues involving "known functions".

Initialising the array will avoid this specific issue:

char c[20] = {0} ;
like image 110
Clifford Avatar answered Nov 05 '22 06:11

Clifford