r344242 - [analyzer][UninitializedObjectChecker] Reports Loc fields pointing to themselves
Kristof Umann via cfe-commits
cfe-commits at lists.llvm.org
Thu Oct 11 04:58:54 PDT 2018
Author: szelethus
Date: Thu Oct 11 04:58:53 2018
New Revision: 344242
URL: http://llvm.org/viewvc/llvm-project?rev=344242&view=rev
Log:
[analyzer][UninitializedObjectChecker] Reports Loc fields pointing to themselves
I've added a new functionality, the checker is now able to
detect and report fields pointing to themselves. I figured
this would fit well into the checker as there's no reason
for a pointer to point to itself instead of being nullptr.
Differential Revision: https://reviews.llvm.org/D51305
Modified:
cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedPointee.cpp
cfe/trunk/test/Analysis/cxx-uninitialized-object-ptr-ref.cpp
Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedPointee.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedPointee.cpp?rev=344242&r1=344241&r2=344242&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedPointee.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedPointee.cpp Thu Oct 11 04:58:53 2018
@@ -89,15 +89,39 @@ public:
}
};
+/// Represents a Loc field that points to itself.
+class CyclicLocField final : public FieldNode {
+
+public:
+ CyclicLocField(const FieldRegion *FR) : FieldNode(FR) {}
+
+ virtual void printNoteMsg(llvm::raw_ostream &Out) const override {
+ Out << "object references itself ";
+ }
+
+ virtual void printPrefix(llvm::raw_ostream &Out) const override {}
+
+ virtual void printNode(llvm::raw_ostream &Out) const override {
+ Out << getVariableName(getDecl());
+ }
+
+ virtual void printSeparator(llvm::raw_ostream &Out) const override {
+ llvm_unreachable("CyclicLocField objects must be the last node of the "
+ "fieldchain!");
+ }
+};
+
} // end of anonymous namespace
// Utility function declarations.
-/// Returns whether \p T can be (transitively) dereferenced to a void pointer
-/// type (void*, void**, ...).
-static bool isVoidPointer(QualType T);
-
-using DereferenceInfo = std::pair<const TypedValueRegion *, bool>;
+struct DereferenceInfo {
+ const TypedValueRegion *R;
+ const bool NeedsCastBack;
+ const bool IsCyclic;
+ DereferenceInfo(const TypedValueRegion *R, bool NCB, bool IC)
+ : R(R), NeedsCastBack(NCB), IsCyclic(IC) {}
+};
/// Dereferences \p FR and returns with the pointee's region, and whether it
/// needs to be casted back to it's location type. If for whatever reason
@@ -105,6 +129,10 @@ using DereferenceInfo = std::pair<const
static llvm::Optional<DereferenceInfo> dereference(ProgramStateRef State,
const FieldRegion *FR);
+/// Returns whether \p T can be (transitively) dereferenced to a void pointer
+/// type (void*, void**, ...).
+static bool isVoidPointer(QualType T);
+
//===----------------------------------------------------------------------===//
// Methods for FindUninitializedFields.
//===----------------------------------------------------------------------===//
@@ -141,8 +169,11 @@ bool FindUninitializedFields::isDerefere
return false;
}
- const TypedValueRegion *R = DerefInfo->first;
- const bool NeedsCastBack = DerefInfo->second;
+ if (DerefInfo->IsCyclic)
+ return addFieldToUninits(LocalChain.add(CyclicLocField(FR)));
+
+ const TypedValueRegion *R = DerefInfo->R;
+ const bool NeedsCastBack = DerefInfo->NeedsCastBack;
QualType DynT = R->getLocationType();
QualType PointeeT = DynT->getPointeeType();
@@ -189,15 +220,6 @@ bool FindUninitializedFields::isDerefere
// Utility functions.
//===----------------------------------------------------------------------===//
-static bool isVoidPointer(QualType T) {
- while (!T.isNull()) {
- if (T->isVoidPointerType())
- return true;
- T = T->getPointeeType();
- }
- return false;
-}
-
static llvm::Optional<DereferenceInfo> dereference(ProgramStateRef State,
const FieldRegion *FR) {
@@ -229,9 +251,8 @@ static llvm::Optional<DereferenceInfo> d
return None;
// We found a cyclic pointer, like int *ptr = (int *)&ptr.
- // TODO: Should we report these fields too?
if (!VisitedRegions.insert(R).second)
- return None;
+ return DereferenceInfo{R, NeedsCastBack, /*IsCyclic*/ true};
DynT = R->getLocationType();
// In order to ensure that this loop terminates, we're also checking the
@@ -248,5 +269,14 @@ static llvm::Optional<DereferenceInfo> d
R = R->getSuperRegion()->getAs<TypedValueRegion>();
}
- return std::make_pair(R, NeedsCastBack);
+ return DereferenceInfo{R, NeedsCastBack, /*IsCyclic*/ false};
+}
+
+static bool isVoidPointer(QualType T) {
+ while (!T.isNull()) {
+ if (T->isVoidPointerType())
+ return true;
+ T = T->getPointeeType();
+ }
+ return false;
}
Modified: cfe/trunk/test/Analysis/cxx-uninitialized-object-ptr-ref.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/cxx-uninitialized-object-ptr-ref.cpp?rev=344242&r1=344241&r2=344242&view=diff
==============================================================================
--- cfe/trunk/test/Analysis/cxx-uninitialized-object-ptr-ref.cpp (original)
+++ cfe/trunk/test/Analysis/cxx-uninitialized-object-ptr-ref.cpp Thu Oct 11 04:58:53 2018
@@ -257,8 +257,10 @@ void fCharPointerTest() {
}
struct CyclicPointerTest1 {
- int *ptr;
- CyclicPointerTest1() : ptr(reinterpret_cast<int *>(&ptr)) {}
+ int *ptr; // expected-note{{object references itself 'this->ptr'}}
+ int dontGetFilteredByNonPedanticMode = 0;
+
+ CyclicPointerTest1() : ptr(reinterpret_cast<int *>(&ptr)) {} // expected-warning{{1 uninitialized field}}
};
void fCyclicPointerTest1() {
@@ -266,8 +268,10 @@ void fCyclicPointerTest1() {
}
struct CyclicPointerTest2 {
- int **pptr; // no-crash
- CyclicPointerTest2() : pptr(reinterpret_cast<int **>(&pptr)) {}
+ int **pptr; // expected-note{{object references itself 'this->pptr'}}
+ int dontGetFilteredByNonPedanticMode = 0;
+
+ CyclicPointerTest2() : pptr(reinterpret_cast<int **>(&pptr)) {} // expected-warning{{1 uninitialized field}}
};
void fCyclicPointerTest2() {
@@ -353,9 +357,10 @@ void fVoidPointerLRefTest() {
}
struct CyclicVoidPointerTest {
- void *vptr; // no-crash
+ void *vptr; // expected-note{{object references itself 'this->vptr'}}
+ int dontGetFilteredByNonPedanticMode = 0;
- CyclicVoidPointerTest() : vptr(&vptr) {}
+ CyclicVoidPointerTest() : vptr(&vptr) {} // expected-warning{{1 uninitialized field}}
};
void fCyclicVoidPointerTest() {
More information about the cfe-commits
mailing list