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
)?
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
l * sizeof c
bytes at c
are initializedDoes 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"?
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} ;
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With