forked from OSchip/llvm-project
[analyzer] Toning down invalidation a bit
When a function takes the address of a field the analyzer will no longer assume that the function will change other fields of the enclosing structs. Differential Revision: https://reviews.llvm.org/D57230 llvm-svn: 352473
This commit is contained in:
parent
5c33c5da1a
commit
f41e3d0873
|
@ -303,11 +303,23 @@ ProgramStateRef CallEvent::invalidateRegions(unsigned BlockCount,
|
|||
for (unsigned Idx = 0, Count = getNumArgs(); Idx != Count; ++Idx) {
|
||||
// Mark this region for invalidation. We batch invalidate regions
|
||||
// below for efficiency.
|
||||
if (PreserveArgs.count(Idx))
|
||||
if (const MemRegion *MR = getArgSVal(Idx).getAsRegion())
|
||||
ETraits.setTrait(MR->getBaseRegion(),
|
||||
RegionAndSymbolInvalidationTraits::TK_PreserveContents);
|
||||
// TODO: Factor this out + handle the lower level const pointers.
|
||||
if (const MemRegion *MR = getArgSVal(Idx).getAsRegion()) {
|
||||
bool UseBaseRegion = true;
|
||||
if (const auto *FR = MR->getAs<FieldRegion>()) {
|
||||
if (const auto *TVR = FR->getSuperRegion()->getAs<TypedValueRegion>()) {
|
||||
if (!TVR->getValueType()->isUnionType()) {
|
||||
ETraits.setTrait(MR, RegionAndSymbolInvalidationTraits::
|
||||
TK_DoNotInvalidateSuperRegion);
|
||||
UseBaseRegion = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
// todo: factor this out + handle the lower level const pointers.
|
||||
if (PreserveArgs.count(Idx))
|
||||
ETraits.setTrait(
|
||||
UseBaseRegion ? MR->getBaseRegion() : MR,
|
||||
RegionAndSymbolInvalidationTraits::TK_PreserveContents);
|
||||
}
|
||||
|
||||
ValuesToInvalidate.push_back(getArgSVal(Idx));
|
||||
|
||||
|
|
|
@ -132,18 +132,21 @@ void testInvalidationThroughBaseRegionPointer() {
|
|||
PlainStruct s1;
|
||||
s1.x = 1;
|
||||
s1.z = 1;
|
||||
s1.y = 1;
|
||||
clang_analyzer_eval(s1.x == 1); // expected-warning{{TRUE}}
|
||||
clang_analyzer_eval(s1.z == 1); // expected-warning{{TRUE}}
|
||||
// Not only passing a structure pointer through const pointer parameter,
|
||||
// but also passing a field pointer through const pointer parameter
|
||||
// should preserve the contents of the structure.
|
||||
useAnythingConst(&(s1.y));
|
||||
clang_analyzer_eval(s1.y == 1); // expected-warning{{TRUE}}
|
||||
clang_analyzer_eval(s1.x == 1); // expected-warning{{TRUE}}
|
||||
// FIXME: Should say "UNKNOWN", because it is not uncommon to
|
||||
// modify a mutable member variable through const pointer.
|
||||
clang_analyzer_eval(s1.z == 1); // expected-warning{{TRUE}}
|
||||
useAnything(&(s1.y));
|
||||
clang_analyzer_eval(s1.x == 1); // expected-warning{{UNKNOWN}}
|
||||
clang_analyzer_eval(s1.x == 1); // expected-warning{{TRUE}}
|
||||
clang_analyzer_eval(s1.y == 1); // expected-warning{{UNKNOWN}}
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -358,7 +358,7 @@ template <class T>
|
|||
void wontInitialize(const T &);
|
||||
|
||||
class PassingToUnknownFunctionTest1 {
|
||||
int a, b;
|
||||
int a, b; // expected-note{{uninitialized field 'this->b'}}
|
||||
|
||||
public:
|
||||
PassingToUnknownFunctionTest1() {
|
||||
|
@ -368,8 +368,7 @@ public:
|
|||
}
|
||||
|
||||
PassingToUnknownFunctionTest1(int) {
|
||||
mayInitialize(a);
|
||||
// All good!
|
||||
mayInitialize(a); // expected-warning{{1 uninitialized field at the end of the constructor call}}
|
||||
}
|
||||
|
||||
PassingToUnknownFunctionTest1(int, int) {
|
||||
|
|
|
@ -1758,8 +1758,8 @@ void constEscape(const void *ptr);
|
|||
void testConstEscapeThroughAnotherField() {
|
||||
struct IntAndPtr s;
|
||||
s.p = malloc(sizeof(int));
|
||||
constEscape(&(s.x)); // could free s->p!
|
||||
} // no-warning
|
||||
constEscape(&(s.x));
|
||||
} // expected-warning {{Potential leak of memory pointed to by 's.p'}}
|
||||
|
||||
// PR15623
|
||||
int testNoCheckerDataPropogationFromLogicalOpOperandToOpResult(void) {
|
||||
|
|
|
@ -231,6 +231,7 @@ void testUnion() {
|
|||
|
||||
int sock = socket(AF_INET, SOCK_STREAM, 0);
|
||||
read(sock, &tainted.y, sizeof(tainted.y));
|
||||
tainted.x = 0;
|
||||
// FIXME: overlapping regions aren't detected by isTainted yet
|
||||
__builtin_memcpy(buffer, tainted.y, tainted.x);
|
||||
}
|
||||
|
|
|
@ -51,7 +51,7 @@ void taintTracking(int x) {
|
|||
scanf("%d", &xy.y);
|
||||
scanf("%d", &xy.x);
|
||||
int tx = xy.x; // expected-warning + {{tainted}}
|
||||
int ty = xy.y; // FIXME: This should be tainted as well.
|
||||
int ty = xy.y; // expected-warning + {{tainted}}
|
||||
char ntz = xy.z;// no warning
|
||||
// Now, scanf scans both.
|
||||
scanf("%d %d", &xy.y, &xy.x);
|
||||
|
|
Loading…
Reference in New Issue