[cfe-dev] How can I get and manipulate the Store and Environment in the current ProgramState in Clang Static Analyzer?

Jordan Rose jordan_rose at apple.com
Fri Jul 19 09:34:41 PDT 2013


Hi, Arthur.

On Jul 16, 2013, at 6:23 , Arthur Yoo <phjy007 at gmail.com> wrote:

> Hi Jordan,
> 
> I created a new SVal with the SValBuilder and then replaced the old SVal with the new one. 
> 
> Now I have another question about MemRegion. Can I get the offset of a SubRegion to its SuperRegion? For an example, here is a struct object:
> struct LayerOne {
>      int a;
>      char b;
>      int c;
> } obj;
> It's obvious that the obj.a's SuperRegion is obj. And so are obj.c's and obj.b's. More importantly, I know that the offset of obj.a to its SuperRegion(obj) equals 0, the offset of obj.b to its SuperRegion(obj) equals 4 and the offset of obj.c to its SuperRegion(obj) equals 8. So I wonder in Clang Static Analyzer, is there any functions or methods which developer can use to calculate the offsets of SubRegions to their SuperRegions? In other words, we can assume regionObjDotB is a MemRegion Object which stands for obj.b, is there any  functions or methods like "regionObjDotB.getOffset()"? If no, how can I get the offsets of SubRegions to their SuperRegions? 

If you want to know the offset from the base region, you can use the MemRegion::getAsOffset method. However, I would guess this isn't actually the best way to solve whatever you're trying to do; most of the analyzer is set up deliberately so that you don't have to think about offsets (and in some cases should not). What are you trying to do?


> In addition, I found a strange situation. Here are the codes.
>      1 struct LayerOne {
>      2	    int a;
>      3	    int b;
>      4	};
>      5	
>      6	void func() {
>      7	    struct LayerOne obj;
>      8	    obj.a = 1;
>      9	    obj.b = 2;
>     10	    void* p = &obj;
>     11	    p = p + 4;
>     12	    *((int*)p) = 200;          // here p points to obj.b actually
>     13	    p = p + 4;
>     14	    *((int*)p) = 99999;      // here the area pointed by p is outside of obj! 
>     15	}
> 
> After the analyzer analyzed the BinaryOperator(assignment operator) in line 12, I got the dump information:
> BinaryOperator 0x4d1b0d0 'int' '='
> |-UnaryOperator 0x4d1b090 'int' lvalue prefix '*'
> | `-ParenExpr 0x4d1b070 'int *'
> |   `-CStyleCastExpr 0x4d1b048 'int *' <BitCast>
> |     `-ImplicitCastExpr 0x4d1b030 'void *' <LValueToRValue>
> |       `-DeclRefExpr 0x4d1afc0 'void *' lvalue Var 0x4d1adc0 'p' 'void *'
> `-IntegerLiteral 0x4d1b0b0 'int' 200
> LHS_sval: &element{obj,0 S32b,int}
> LHS_region: element{obj,0 S32b,int}
> sval: 200 S32b
> size: 4 S32b
> space: StackLocalsSpaceRegion
> Base_Region: obj
> Super_Region: obj
> 
> From the dump information above, I can know that obj.b has been assigned a value of 200. Does S32b mean signed-32bit? And since the obj.b's offset is 4, why LHS_region is element{obj,0 S32b,int} rather than element{obj,4 S32b,int}?

I would guess the analyzer doesn't bother to handle pointer arithmetic on type void*, which is technically illegal. Clang-the-compiler follows GCC's lead in treating it like char*, though, so we should probably do that. Please file a bug.

Citations for legality: C11 6.5.6p2 ("one operand shall be a pointer to a complete object type") and 6.2.5p19 ("[void] is an incomplete object type").

(And yes, S32b means "signed 32-bit".)


> After the analyzer analyzed the BinaryOperator(assignment operator) in line 14, I got the dump information:BinaryOperator 0x4d1b2b0 'int' '='
> BinaryOperator 0x4d1b2b0 'int' '='
> |-UnaryOperator 0x4d1b270 'int' lvalue prefix '*'
> | `-ParenExpr 0x4d1b250 'int *'
> |   `-CStyleCastExpr 0x4d1b228 'int *' <BitCast>
> |     `-ImplicitCastExpr 0x4d1b210 'void *' <LValueToRValue>
> |       `-DeclRefExpr 0x4d1b1d0 'void *' lvalue Var 0x4d1adc0 'p' 'void *'
> `-IntegerLiteral 0x4d1b290 'int' 99999
> lhs_sval: &element{obj,0 S32b,int}
> lhs_region: element{obj,0 S32b,int}
> sval: 99999 S32b
> size: 4 S32b
> space: StackLocalsSpaceRegion
> Base_Region: obj
> Super_Region: obj
> 
> Here, my first question is similar, since the pointer p's offset is 8 at that moment, why LHS_region is element{obj,0 S32b,int} rather than element{obj,8 S32b,int}? What makes me more confused is that in line 14, the destination pointed by p is outside of obj, but the dump information still shows "Super_Region: obj". 
> Am I doing something stupid here?

No, apparently we are. ;-) Thanks for finding this.

Jordan

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-dev/attachments/20130719/0901f3a5/attachment.html>


More information about the cfe-dev mailing list