[cfe-commits] r63347 - in /cfe/trunk: include/clang/Analysis/PathSensitive/BasicValueFactory.h include/clang/Analysis/PathSensitive/MemRegion.h include/clang/Analysis/PathSensitive/SVals.h lib/Analysis/MemRegion.cpp lib/Analysis/RegionStore.cpp l
Ted Kremenek
kremenek at apple.com
Thu Jan 29 23:51:30 PST 2009
On Jan 29, 2009, at 9:15 PM, Zhongxing Xu wrote:
>
> Added: cfe/trunk/test/Analysis/rdar-6541136.c
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/rdar-6541136.c?rev=63347&view=auto
>
> =
> =
> =
> =
> =
> =
> =
> =
> ======================================================================
> --- cfe/trunk/test/Analysis/rdar-6541136.c (added)
> +++ cfe/trunk/test/Analysis/rdar-6541136.c Thu Jan 29 18:08:43 2009
> @@ -0,0 +1,20 @@
> +// clang -verify -analyze -checker-cfref -analyzer-store-basic %s
> +
> +struct tea_cheese { unsigned magic; };
> +typedef struct tea_cheese kernel_tea_cheese_t;
> +extern kernel_tea_cheese_t _wonky_gesticulate_cheese;
> +
> +// This test case exercises the ElementRegion::getRValueType() logic.
> +// All it tests is that it does not crash or do anything weird.
> +// The out-of-bounds-access on line 19 is caught using the region
> store variant.
> +
> +void foo( void )
> +{
> + kernel_tea_cheese_t *wonky = &_wonky_gesticulate_cheese;
> + struct load_wine *cmd = (void*) &wonky[1];
>
> This is like an ill use of the type system. What do you think we
> emit a warning instead of following it.
> That is, we emit a warning when the array region does not have array
> type or pointer type.
Yes this is really gross code. It actually contains more stuff than
the original test case I looked at just to see if the analyzer would
crash. The original test case was basically:
kernel_tea_cheese_t *wonky = &_wonky_gesticulate_cheese;
struct load_wine *cmd = (void*) &wonky[1];
Let's just consider this for a moment. While the out-of-bounds access
looks wrong in all cases, aside from the out-of-bounds access it may
be "okay." Consider the following possible definition of struct
load_wine:
struct load_wine {
struct tea_cheese x;
...
};
In this case, it is okay to cast a 'struct tea_cheese*' to a 'struct
load_wine*'. This kind of pattern appears a lot in the Gtk+ code (and
other C libraries) to simulate object-oriented programming and
inheritance.
The problem here is that we don't have the definition of 'struct
load_wine'. If we did, we could do some extra type checking (as you
suggest). In this case, we don't, so what do we do?
As for:
char *p = (void*) &wonky[1];
*p = 1;
Yes that is really gross. What should we do here? This is
technically an out-of-bounds memory write (which we don't flag because
of the abuse of the type system), but as you said it is an abuse of
the type system. With our path-sensitive type information in the
RegionStore objects perhaps we can flag a more lucid warning? On the
other hand, assuming that &wonky[1] is valid (say wonky was an array),
we're just writing '1' to the first byte of the 'magic' field. The
rabbit hole goes arbitrary deep.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20090129/799756d8/attachment.html>
More information about the cfe-commits
mailing list