[PATCH] D46823: [analyzer] const init: handle non-explicit cases more accurately

Artem Dergachev via Phabricator via cfe-commits cfe-commits at lists.llvm.org
Fri May 25 11:41:51 PDT 2018


NoQ accepted this revision.
NoQ added a comment.
This revision is now accepted and ready to land.

Looks good!

Do you have commit access? I think you should get commit access.



================
Comment at: lib/StaticAnalyzer/Core/RegionStore.cpp:1650
+
+            // If there is a list, but no init, it must be zero.
+            if (i >= InitList->getNumInits())
----------------
r.stahl wrote:
> r.stahl wrote:
> > NoQ wrote:
> > > NoQ wrote:
> > > > Would this work correctly if the element is not of an integral or enumeration type? I think this needs an explicit check.
> > > What if we have an out-of-bounds access to a variable-length array? I don't think it'd yield zero.
> > I'm getting "variable-sized object may not be initialized", so this case should not be possible.
> I'm having a hard time reproducing this either.
> 
> 
> ```
> struct S {
>   int a = 3;
> };
> S const sarr[2] = {};
> void definit() {
>   int i = 1;
>   clang_analyzer_dump(sarr[i].a); // expected-warning{{test}}
> }
> ```
> 
> results in a symbolic value, because makeZeroVal returns an empty SVal list for arrays, records, vectors and complex types. Otherwise it just returns UnknownVal (for example for not-yet-implemented floats).
> 
> Can you think of a case where this would be an issue?
Yup, sounds reasonable.


================
Comment at: lib/StaticAnalyzer/Core/RegionStore.cpp:1650-1652
+            // If there is a list, but no init, it must be zero.
+            if (i >= InitList->getNumInits())
+              return svalBuilder.makeZeroVal(R->getElementType());
----------------
NoQ wrote:
> r.stahl wrote:
> > r.stahl wrote:
> > > NoQ wrote:
> > > > NoQ wrote:
> > > > > Would this work correctly if the element is not of an integral or enumeration type? I think this needs an explicit check.
> > > > What if we have an out-of-bounds access to a variable-length array? I don't think it'd yield zero.
> > > I'm getting "variable-sized object may not be initialized", so this case should not be possible.
> > I'm having a hard time reproducing this either.
> > 
> > 
> > ```
> > struct S {
> >   int a = 3;
> > };
> > S const sarr[2] = {};
> > void definit() {
> >   int i = 1;
> >   clang_analyzer_dump(sarr[i].a); // expected-warning{{test}}
> > }
> > ```
> > 
> > results in a symbolic value, because makeZeroVal returns an empty SVal list for arrays, records, vectors and complex types. Otherwise it just returns UnknownVal (for example for not-yet-implemented floats).
> > 
> > Can you think of a case where this would be an issue?
> Yup, sounds reasonable.
Had a look. This indeed looks fine, but for a completely different reason. In fact structs don't appear in `getBindingForElement()` because they all go through `getBindingForStruct()` instead. Hopefully this does take care of other cornercases.

So your test case doesn't even trigger your code to be executed, neither would `S s = sarr[i]; clang_analyzer_dump(s.a);`.

Still, as far as i understand, `sarr` here should be zero-initialized, so i think the symbolic value can be improved upon, so we might as well add this as a FIXME test.


https://reviews.llvm.org/D46823





More information about the cfe-commits mailing list