If the access is out of bounds, return UndefinedVal. If it is missing an explicit init, return the implicit zero value it must have.
Details
Diff Detail
Event Timeline
Yay thanks!
I think some cornercases would need to be dealt with.
lib/StaticAnalyzer/Core/RegionStore.cpp | ||
---|---|---|
1650 | What if we have an out-of-bounds access to a variable-length array? I don't think it'd yield zero. | |
1650–1652 | Would this work correctly if the element is not of an integral or enumeration type? I think this needs an explicit check. | |
1733 | Same: would this work correctly if the field is not of an integral or enumeration type? | |
test/Analysis/initialization.c | ||
3 | We try to avoid using dump() on tests because it makes tests test the dump syntax, which isn't the point. For checking constants, it's easier to do something like clang_analyzer_eval(parr[i] == 2); // expected-warning{{TRUE}}. For finding undefined values, you can enable core.uninitialized checkers and receive warnings when the argument of clang_analyzer_eval is an uninitialized value. Or just increment the value. |
updated test
lib/StaticAnalyzer/Core/RegionStore.cpp | ||
---|---|---|
1650 | I'm getting "variable-sized object may not be initialized", so this case should not be possible. | |
1650–1652 | 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? |
Looks good!
Do you have commit access? I think you should get commit access.
lib/StaticAnalyzer/Core/RegionStore.cpp | ||
---|---|---|
1650 | Yup, sounds reasonable. | |
1650–1652 | 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. |
Added FIXME tests.
I know my example didn't exercise your scenario, but it was the only one I could think of where returning zero would have been straight up wrong. Note that I default initialized a to 3 there, so sarr is not just zero-initialized.
I do not have access yet, but applied today!
What if we have an out-of-bounds access to a variable-length array? I don't think it'd yield zero.