[cfe-commits] r75356 - in /cfe/trunk: lib/Analysis/GRExprEngine.cpp test/Analysis/misc-ps.m

Zhongxing Xu xuzhongxing at gmail.com
Tue Jul 14 00:03:59 PDT 2009


On Tue, Jul 14, 2009 at 2:32 PM, Ted Kremenek<kremenek at apple.com> wrote:
>
> On Jul 13, 2009, at 6:28 PM, Zhongxing Xu wrote:
>
> Makes sense.  I think we should add a comment about why the check for
>
> 'isGenericPtr' is there.  Also, we should document that if the region
>
> already has a cast type, casting it to void* doesn't remove that cast type.
>
> What should the semantics be if there already is a cast type associated with
>
> a region?
>
> I think it's seldom that programmer would cast it back to generic
> pointer intentionally. Often it is cast back to generic
> pointer passively. E.g.:
>
> void invalidate(void* p);
> int *p = (int*)alloca();
> void *q = (void*) p; // people don't do this.
> invalidate(p); // people often do this.
>
> Agreed.  Should we also consider 'char *' as a case in 'isGenericPtr'?

If this happens in real code, we can add it.

>
> This code might actually be valid if 'sizeof(struct s) <= sizeof(int)' and
>
> the alignments of both 'int' and 'struct s' are compatible.  Otherwise,
>
> we'll get a potential buffer overflow that we won't catch. Alternatively, we
>
> might not actually be doing the right thing.  I think this is something
>
> worth discussing.
>
> The check is done (or should be done) in NewCastRegion(). If the cast
> is legal, then type 'struct s' is used to
> invalidate the region. I actually am not very clear about what you are
> worrying about here.
>
> I think you're right.  I think I may have thought too hard about it and
> confused myself.
>
>
>
> Index: lib/Analysis/GRExprEngine.cpp
>
> ===================================================================
>
> --- lib/Analysis/GRExprEngine.cpp (revision 75492)
>
> +++ lib/Analysis/GRExprEngine.cpp (working copy)
>
> @@ -1119,9 +1119,9 @@
>
>      //  invalidate(y);  // 'x' now binds to a symbolic region
>
>      //  int z = *y;
>
>      //
>
> -    if (isa<Loc>(V) && !Loc::IsLocType(Ex->getType())) {
>
> -      V = EvalCast(V, Ex->getType());
>
> -    }
>
> +    //if (isa<Loc>(V) && !Loc::IsLocType(Ex->getType())) {
>
> +    //  V = EvalCast(V, Ex->getType());
>
> +    // }
>
> This is the main change, but I cannot actually evaluate it yet.  Using the
>
> '-analyzer-viz-egraph-graphviz' option, I saw that for the following code:
>
>     int *__gruep__ = ((int *)&((b)->grue));
>
>     int __gruev__ = *__gruep__;
>
> that all we end up doing is conjuring a new symbol for the second
>
> declaration of '__gruev__' (even when using RegionStoreManager).
>
> This is expected. We invalidate *__gruep__ with a conjured symbol.
>
> Right!  Once again I confused myself; there is a difference between the
> conjured symbols used by RegionStore and the ones used to recover
> path-sensitivity in GRExprEngine.  It would be nice if if we had a way to
> distinguish them.

Agreed. It's worth to distinguish symbols in different usages.

> Just as a test, I augmented my copy of 'testB' to contain two infeasible
> null dereferences.  With RegionStore we get no null dereference errors (as
> it should be).  BasicStore flags two:
> typedef struct _BStruct { void *grue; } BStruct;
> void testB_aux(void *ptr);
> void testB(BStruct *b) {
>   {
>     int *__gruep__ = ((int *)&((b)->grue));
>     int __gruev__ = *__gruep__;
>     int __gruev2__ = *__gruep__;
>     if (__gruev__ != __gruev2__) {
>       int *p = 0;
>       *p = 0xDEADBEEF;
>     }
>
>     testB_aux(__gruep__);
>   }
>   {
>     int *__gruep__ = ((int *)&((b)->grue));
>     int __gruev__ = *__gruep__;
>     int __gruev2__ = *__gruep__;
>     if (__gruev__ != __gruev2__) {
>       int *p = 0;
>       *p = 0xDEADBEEF;
>     }
>
>     if (~0 != __gruev__) {}
>   }
> }




More information about the cfe-commits mailing list