[cfe-dev] Static Analyzer: pointer alias assignment

Gábor Kozár kozargabor at gmail.com
Wed Jul 24 07:12:39 PDT 2013


Anna,

> *Can this be designed as an extension of the Dereference checker?

*
That was my original thought, but looking at the Dereference checker source
code, it writes that it's a built-in check in ExprEngine, which discouraged
me to try to extend it. I also have no idea how it works or what it does -
I've been unable to have it produce any warnings, except for this trivial
case:

Foo* fp = nullptr;
fp->baz();

And now I tried with your code example, and it also produces a warning. By
the way, when analyzing a translation unit, which function(s) are treated
as entry points? It appears to me that all of them are, but are there any
restrictions, or ways to control this? I do not see any promising args with
clang++ -cc1 --help.

Anyway, this code snippet still does not cause the Dereference checker to
raise a warning, even though it is trivial:

Foo* fp = getFooPtr(); // based on runtime data, either returns nullptr, or
an allocated object
if(!fp)
{
      fp->baz();
}

To the best of my knowledge, the if(!bar) line creates two code paths: one
on which the condition is true (i.e. fp == nullptr), and one on which the
condition is false (i.e. fp != nullptr). Obviously the first statement on
the former code path is the fp->baz() line, analyzing which the Static
Analyzer tells me that 'fp' is constrained to be null (using
ProgramState::isNull). Therefore, my checker can easily find this issue.

Browsing through the source code of the DereferenceChecker, I can tell it
does not use ProgramState::isNull, but instead ProgramState::assume.
However, as far as I can tell, it does exactly nothing - I can see that
it's supposed to either raise a warning, or dispatch an
ImplicitNullDerefEvent, but neither happens on the code example above (I
tested the latter by running both checkers with -analyzer-checker, and in
my checker, I subscribe to check::Event<ImplicitNullDerefEvent>).

So why is ProgramState::assume used instead of ProgramState::isNull?

> *Also, the Dereference checker does work fine in presence of aliases...
Is there a reason why it's different in your setting?

*
I'm using Clang 3.3, so unless significant changes have been made to the
Static Analyzer or the Dereference checker, things should work the same. I
have not modified the Clang source code, except for adding a bunch of
custom checkers.

Gabor


2013/7/23 Anna Zaks <ganna at apple.com>

>
> On Jul 23, 2013, at 10:33 AM, Gábor Kozár <kozargabor at gmail.com> wrote:
>
> Hi Anna,
>
> I'm building a checker that detects inconsistent pointer usages, for
> example when a pointer is dereferenced, then along the same path is
> null-checked (without its value changing in between, obviously).
>
>
> Can this be designed as an extension of the Dereference checker?
>
> Also, the Dereference checker does work fine in presence of aliases... Is
> there a reason why it's different in your setting?
>
> int foo(int *p) {
>   int *q = p;
>   if (q)
>     ;
>   return *p;
> }
>
> zaks$ clang --analyze ~/tmp/ex.c -Xclang -analyzer-output=text
> */Users/zaks/tmp/ex.c:5:10: **warning: **Dereference of null pointer
> (loaded from variable 'p')*
>   return *p;
> *         ^~*
> */Users/zaks/tmp/ex.c:3:7: note: *Assuming 'q' is null
>   if (q)
> *      ^*
> */Users/zaks/tmp/ex.c:3:3: note: *Taking false branch
>   if (q)
> *  ^*
> */Users/zaks/tmp/ex.c:5:10: note: *Dereference of null pointer (loaded
> from variable 'p')
>   return *p;
> *         ^*
> 1 warning generated.
>
>
>  Code example:
>
> Foo* f = getFoo();
> f->bar();
>
> if(f) // warn
> { ... }
>
> I want to be able to do this with aliases as well, for example:
>
> Foo* f = getFoo();
> f->bar();
>
> Foo* g = f;
> if(g) // warn
> { ... }
>
> What I need is to be able to get the SVals representing 'f' and 'g' when
> checkBind is called on the Foo* g = f; line. Currently, instead of 'f',
> Clang gives me the value that was bound to 'f'.
>
> Thanks for your help!
>
>
> 2013/7/23 Anna Zaks <ganna at apple.com>
>
>>
>> On Jul 23, 2013, at 9:21 AM, Gábor Kozár <kozargabor at gmail.com> wrote:
>>
>> During the analysis of a test code, the following two bindings happen
>> (checkBind), with their respective source lines:
>>
>> (Bind: location <= value)
>>
>> Bind: &fp <= &SymRegion{conj_$4{struct Foo *}}
>> Code: Foo* fp = getFooPtr();
>>
>> Bind: &ap <= &SymRegion{conj_$4{struct Foo *}}
>> Code: Foo* ap = fp;
>>
>> In the second line, I need to detect that 'ap' is in fact the alias of
>> 'fp'. Unfortunately, I cannot seem to find any way to get Clang SA to tell
>> me that "&SymRegion{conj_$4{struct Foo *}}" is stored in "fp", which seems
>> weird, because the source code is very clear.
>>
>>
>> As you observe the two binds you see that the same value is stored in
>> both.
>>
>> The analyzer does not perform alias analyzes as in it does not build sets
>> of aliases. As it models the execution in presence of aliases, we did not
>> find a need for the alias sets. Can you give a bit more background on why
>> you need this info? Maybe your goal can be achieved differently?
>>
>>
>> Some of the information I extracted, but is not really useful to me:
>>  - original SVal: &SymRegion{conj_$4{struct Foo *}}
>>  - getAsRegion(): SymRegion{conj_$4{struct Foo *}}
>>  - state->getSVal(): &SymRegion{reg_$6<element{SymRegion{conj_$4{struct
>> Foo *}},0 S32b,struct Foo *}>} -- in fact, I have no idea what this is
>>  - getAsSymbol(): conj_$4{struct Foo *}
>>
>> As a workaround, I can keep track of this information myself, but there
>> must be a built-in way to do this.
>> Any help would be appreciated. Many thanks!
>> _______________________________________________
>> cfe-dev mailing list
>> cfe-dev at cs.uiuc.edu
>> http://lists.cs.uiuc.edu/mailman/listinfo/cfe-dev
>>
>>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-dev/attachments/20130724/3c9e8354/attachment.html>


More information about the cfe-dev mailing list