1 //===----- UninitializedPointee.cpp ------------------------------*- C++ -*-==// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 // 10 // This file defines functions and methods for handling pointers and references 11 // to reduce the size and complexity of UninitializedObjectChecker.cpp. 12 // 13 // To read about command line options and a description what this checker does, 14 // refer to UninitializedObjectChecker.cpp. 15 // 16 // To read about how the checker works, refer to the comments in 17 // UninitializedObject.h. 18 // 19 //===----------------------------------------------------------------------===// 20 21 #include "../ClangSACheckers.h" 22 #include "UninitializedObject.h" 23 #include "clang/StaticAnalyzer/Core/BugReporter/BugType.h" 24 #include "clang/StaticAnalyzer/Core/Checker.h" 25 #include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h" 26 #include "clang/StaticAnalyzer/Core/PathSensitive/DynamicTypeMap.h" 27 28 using namespace clang; 29 using namespace clang::ento; 30 31 namespace { 32 33 /// Represents a pointer or a reference field. 34 class LocField final : public FieldNode { 35 /// We'll store whether the pointee or the pointer itself is uninitialited. 36 const bool IsDereferenced; 37 38 public: 39 LocField(const FieldRegion *FR, const bool IsDereferenced = true) 40 : FieldNode(FR), IsDereferenced(IsDereferenced) {} 41 42 virtual void printNoteMsg(llvm::raw_ostream &Out) const override { 43 if (IsDereferenced) 44 Out << "uninitialized pointee "; 45 else 46 Out << "uninitialized pointer "; 47 } 48 49 virtual void printPrefix(llvm::raw_ostream &Out) const override {} 50 51 virtual void printNode(llvm::raw_ostream &Out) const override { 52 Out << getVariableName(getDecl()); 53 } 54 55 virtual void printSeparator(llvm::raw_ostream &Out) const override { 56 if (getDecl()->getType()->isPointerType()) 57 Out << "->"; 58 else 59 Out << '.'; 60 } 61 }; 62 63 /// Represents a void* field that needs to be casted back to its dynamic type 64 /// for a correct note message. 65 class NeedsCastLocField final : public FieldNode { 66 QualType CastBackType; 67 68 public: 69 NeedsCastLocField(const FieldRegion *FR, const QualType &T) 70 : FieldNode(FR), CastBackType(T) {} 71 72 virtual void printNoteMsg(llvm::raw_ostream &Out) const override { 73 Out << "uninitialized pointee "; 74 } 75 76 virtual void printPrefix(llvm::raw_ostream &Out) const override { 77 Out << "static_cast" << '<' << CastBackType.getAsString() << ">("; 78 } 79 80 virtual void printNode(llvm::raw_ostream &Out) const override { 81 Out << getVariableName(getDecl()) << ')'; 82 } 83 84 virtual void printSeparator(llvm::raw_ostream &Out) const override { 85 Out << "->"; 86 } 87 }; 88 89 } // end of anonymous namespace 90 91 // Utility function declarations. 92 93 /// Returns whether \p T can be (transitively) dereferenced to a void pointer 94 /// type (void*, void**, ...). 95 static bool isVoidPointer(QualType T); 96 97 using DereferenceInfo = std::pair<const TypedValueRegion *, bool>; 98 99 /// Dereferences \p FR and returns with the pointee's region, and whether it 100 /// needs to be casted back to it's location type. If for whatever reason 101 /// dereferencing fails, returns with None. 102 static llvm::Optional<DereferenceInfo> dereference(ProgramStateRef State, 103 const FieldRegion *FR); 104 105 //===----------------------------------------------------------------------===// 106 // Methods for FindUninitializedFields. 107 //===----------------------------------------------------------------------===// 108 109 bool FindUninitializedFields::isDereferencableUninit( 110 const FieldRegion *FR, FieldChainInfo LocalChain) { 111 112 assert(isDereferencableType(FR->getDecl()->getType()) && 113 "This method only checks dereferencable objects!"); 114 115 SVal V = State->getSVal(FR); 116 117 if (V.isUnknown() || V.getAs<loc::ConcreteInt>()) { 118 IsAnyFieldInitialized = true; 119 return false; 120 } 121 122 if (V.isUndef()) { 123 return addFieldToUninits( 124 LocalChain.add(LocField(FR, /*IsDereferenced*/ false))); 125 } 126 127 if (!CheckPointeeInitialization) { 128 IsAnyFieldInitialized = true; 129 return false; 130 } 131 132 // At this point the pointer itself is initialized and points to a valid 133 // location, we'll now check the pointee. 134 llvm::Optional<DereferenceInfo> DerefInfo = dereference(State, FR); 135 if (!DerefInfo) { 136 IsAnyFieldInitialized = true; 137 return false; 138 } 139 140 const TypedValueRegion *R = DerefInfo->first; 141 const bool NeedsCastBack = DerefInfo->second; 142 143 QualType DynT = R->getLocationType(); 144 QualType PointeeT = DynT->getPointeeType(); 145 146 if (PointeeT->isStructureOrClassType()) { 147 if (NeedsCastBack) 148 return isNonUnionUninit(R, LocalChain.add(NeedsCastLocField(FR, DynT))); 149 return isNonUnionUninit(R, LocalChain.add(LocField(FR))); 150 } 151 152 if (PointeeT->isUnionType()) { 153 if (isUnionUninit(R)) { 154 if (NeedsCastBack) 155 return addFieldToUninits(LocalChain.add(NeedsCastLocField(FR, DynT))); 156 return addFieldToUninits(LocalChain.add(LocField(FR))); 157 } else { 158 IsAnyFieldInitialized = true; 159 return false; 160 } 161 } 162 163 if (PointeeT->isArrayType()) { 164 IsAnyFieldInitialized = true; 165 return false; 166 } 167 168 assert((isPrimitiveType(PointeeT) || isDereferencableType(PointeeT)) && 169 "At this point FR must either have a primitive dynamic type, or it " 170 "must be a null, undefined, unknown or concrete pointer!"); 171 172 SVal PointeeV = State->getSVal(R); 173 174 if (isPrimitiveUninit(PointeeV)) { 175 if (NeedsCastBack) 176 return addFieldToUninits(LocalChain.add(NeedsCastLocField(FR, DynT))); 177 return addFieldToUninits(LocalChain.add(LocField(FR))); 178 } 179 180 IsAnyFieldInitialized = true; 181 return false; 182 } 183 184 //===----------------------------------------------------------------------===// 185 // Utility functions. 186 //===----------------------------------------------------------------------===// 187 188 static bool isVoidPointer(QualType T) { 189 while (!T.isNull()) { 190 if (T->isVoidPointerType()) 191 return true; 192 T = T->getPointeeType(); 193 } 194 return false; 195 } 196 197 static llvm::Optional<DereferenceInfo> dereference(ProgramStateRef State, 198 const FieldRegion *FR) { 199 200 llvm::SmallSet<const TypedValueRegion *, 5> VisitedRegions; 201 202 // If the static type of the field is a void pointer, we need to cast it back 203 // to the dynamic type before dereferencing. 204 bool NeedsCastBack = isVoidPointer(FR->getDecl()->getType()); 205 206 SVal V = State->getSVal(FR); 207 assert(V.getAsRegion() && "V must have an underlying region!"); 208 209 // The region we'd like to acquire. 210 const auto *R = V.getAsRegion()->getAs<TypedValueRegion>(); 211 if (!R) 212 return None; 213 214 VisitedRegions.insert(R); 215 216 // We acquire the dynamic type of R, 217 QualType DynT = R->getLocationType(); 218 219 while (const MemRegion *Tmp = State->getSVal(R, DynT).getAsRegion()) { 220 221 R = Tmp->getAs<TypedValueRegion>(); 222 if (!R) 223 return None; 224 225 // We found a cyclic pointer, like int *ptr = (int *)&ptr. 226 // TODO: Should we report these fields too? 227 if (!VisitedRegions.insert(R).second) 228 return None; 229 230 DynT = R->getLocationType(); 231 // In order to ensure that this loop terminates, we're also checking the 232 // dynamic type of R, since type hierarchy is finite. 233 if (isDereferencableType(DynT->getPointeeType())) 234 break; 235 } 236 237 return std::make_pair(R, NeedsCastBack); 238 } 239