[analyzer] Global vs Local null-pointer dereferencing?

classic Classic list List threaded Threaded
3 messages Options
Reply | Threaded
Open this post in threaded view
|

[analyzer] Global vs Local null-pointer dereferencing?

Vassil Vassilev via cfe-dev

Run clang --analyze on these two code snippets:

global ptr:

int *x = 0;
void foo() {
  int y = *x;
}
local ptr:
void foo() {
  int *x = 0;
  int y = *x;
}
I met a weird result.​ 
The global version does not generate a warning like the local one does?
test.cpp:3:11: warning: Dereference of null pointer (loaded from variable 'x') [core.NullDereference]
​Another observation is that for the global verion analyzer does not handle init expression (int *x = 0;), but for the local one it does. Therefore it stores x as &SymRegion{reg_$0<int * x>} for the global and 0 for the local.

Example graphs attached.

Who can explain why it is so?



Denys Petrov
Senior С++ Developer | Kharkiv, Ukraine


_______________________________________________
cfe-dev mailing list
[hidden email]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev

local_nullptr.html (53K) Download Attachment
global_nullptr.html (67K) Download Attachment
Reply | Threaded
Open this post in threaded view
|

Re: [analyzer] Global vs Local null-pointer dereferencing?

Vassil Vassilev via cfe-dev
It is expected.  Global variables are infamous for being extremely hard to analyze statically.  Clang static analyser is no exception.  Basically it analyzes functions independently (inlining some of the calls), and this model doesn’t allow it to reason about global variables.  It doesn’t know when foo is called because maybe some other function have already modified x.  Even if we put direct assignment x = 0 into foo, it is still hard to reason about.  Any call to another function is a potential modification of x.

I hope that answers you question!

-Valeriy Savchenko

On 26 May 2020, at 16:11, Denis Petrov via cfe-dev <[hidden email]> wrote:

Run clang --analyze on these two code snippets:
global ptr:
int *x = 0;
void foo() {
  int y = *x;
}
local ptr:
void foo() {
  int *x = 0;
  int y = *x;
}
I met a weird result.​ 
The global version does not generate a warning like the local one does?
test.cpp:3:11: warning: Dereference of null pointer (loaded from variable 'x') [core.NullDereference]
​Another observation is that for the global verion analyzer does not handle init expression (int *x = 0;), but for the local one it does. Therefore it stores x as &SymRegion{reg_$0<int * x>} for the global and 0 for the local.

Example graphs attached.

Who can explain why it is so?


Denys Petrov
Senior С++ Developer | Kharkiv, Ukraine

<local_nullptr.html><global_nullptr.html>_______________________________________________
cfe-dev mailing list
[hidden email]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev


_______________________________________________
cfe-dev mailing list
[hidden email]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev
Reply | Threaded
Open this post in threaded view
|

Re: [analyzer] Global vs Local null-pointer dereferencing?

Vassil Vassilev via cfe-dev
I'd like to add to this that out that we do actually trust the global
variable to still be null if the function under analysis is main().
I.e., this warns:

     int *x = 0;
     int main() {
       int y = *x;
     }

It doesn't warn in C++ though, only in C, because in C++ it's too
idiomatic to have code before main (eg., global constructors). This can
be made more precise though, at least for non-escaping static globals.

On 5/26/20 6:29 PM, Valeriy Savchenko via cfe-dev wrote:

> It is expected.  Global variables are infamous for being extremely
> hard to analyze statically.  Clang static analyser is no exception.
>  Basically it analyzes functions independently (inlining some of the
> calls), and this model doesn’t allow it to reason about global
> variables.  It doesn’t know when *foo *is called because maybe some
> other function have already modified *x*.  Even if we put direct
> assignment *x = 0 *into *foo, *it is still hard to reason about.  Any
> call to another function is a potential modification of *x*.
>
> I hope that answers you question!
>
> -Valeriy Savchenko
>
>> On 26 May 2020, at 16:11, Denis Petrov via cfe-dev
>> <[hidden email] <mailto:[hidden email]>> wrote:
>>
>> Run clang --analyzeon these two code snippets:
>> *global ptr:*
>>
>>     int *x = 0;
>>     void foo() {
>>       int y = *x;
>>     }
>>
>> *local **ptr:*
>>
>>     void foo() {
>>     int *x = 0;
>>     int y = *x;
>>     }
>>
>> I met a weird result.​
>> The *global*version does not generate a warning like the*local*one does?
>>
>>     test.cpp:3:11: warning: Dereference of null pointer (loaded from
>>     variable 'x') [core.NullDereference]
>>
>> ​Another observation is that for the global verion analyzer does not
>> handle init expression /(int *x = 0;)/, but for the local one it
>> does. Therefore it stores *x*as *&SymRegion{reg_$0<int * x>}*for
>> the global and*0*for the local.
>>
>> Example graphs attached.
>>
>> Who can explain why it is so?
>> ​
>> ------------------------------------------------------------------------
>> *Denys Petrov*
>> Senior С++ Developer | Kharkiv, Ukraine
>>
>> <local_nullptr.html><global_nullptr.html>_______________________________________________
>> cfe-dev mailing list
>> [hidden email] <mailto:[hidden email]>
>> https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev
>
>
> _______________________________________________
> cfe-dev mailing list
> [hidden email]
> https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev

_______________________________________________
cfe-dev mailing list
[hidden email]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev