1 //===----- UninitializedPointer.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 T can be (transitively) dereferenced to a void pointer type 94 /// (void*, void**, ...). The type of the region behind a void pointer isn't 95 /// known, and thus FD can not be analyzed. 96 static bool isVoidPointer(QualType T); 97 98 //===----------------------------------------------------------------------===// 99 // Methods for FindUninitializedFields. 100 //===----------------------------------------------------------------------===// 101 102 // Note that pointers/references don't contain fields themselves, so in this 103 // function we won't add anything to LocalChain. 104 bool FindUninitializedFields::isPointerOrReferenceUninit( 105 const FieldRegion *FR, FieldChainInfo LocalChain) { 106 107 assert((FR->getDecl()->getType()->isAnyPointerType() || 108 FR->getDecl()->getType()->isReferenceType() || 109 FR->getDecl()->getType()->isBlockPointerType()) && 110 "This method only checks pointer/reference objects!"); 111 112 SVal V = State->getSVal(FR); 113 114 if (V.isUnknown() || V.getAs<loc::ConcreteInt>()) { 115 IsAnyFieldInitialized = true; 116 return false; 117 } 118 119 if (V.isUndef()) { 120 return addFieldToUninits( 121 LocalChain.add(LocField(FR, /*IsDereferenced*/ false))); 122 } 123 124 if (!CheckPointeeInitialization) { 125 IsAnyFieldInitialized = true; 126 return false; 127 } 128 129 assert(V.getAs<loc::MemRegionVal>() && 130 "At this point V must be loc::MemRegionVal!"); 131 auto L = V.castAs<loc::MemRegionVal>(); 132 133 // We can't reason about symbolic regions, assume its initialized. 134 // Note that this also avoids a potential infinite recursion, because 135 // constructors for list-like classes are checked without being called, and 136 // the Static Analyzer will construct a symbolic region for Node *next; or 137 // similar code snippets. 138 if (L.getRegion()->getSymbolicBase()) { 139 IsAnyFieldInitialized = true; 140 return false; 141 } 142 143 DynamicTypeInfo DynTInfo = getDynamicTypeInfo(State, L.getRegion()); 144 if (!DynTInfo.isValid()) { 145 IsAnyFieldInitialized = true; 146 return false; 147 } 148 149 QualType DynT = DynTInfo.getType(); 150 151 // If the static type of the field is a void pointer, we need to cast it back 152 // to the dynamic type before dereferencing. 153 bool NeedsCastBack = isVoidPointer(FR->getDecl()->getType()); 154 155 if (isVoidPointer(DynT)) { 156 IsAnyFieldInitialized = true; 157 return false; 158 } 159 160 // At this point the pointer itself is initialized and points to a valid 161 // location, we'll now check the pointee. 162 SVal DerefdV = State->getSVal(V.castAs<Loc>(), DynT); 163 164 // If DerefdV is still a pointer value, we'll dereference it again (e.g.: 165 // int** -> int*). 166 while (auto Tmp = DerefdV.getAs<loc::MemRegionVal>()) { 167 if (Tmp->getRegion()->getSymbolicBase()) { 168 IsAnyFieldInitialized = true; 169 return false; 170 } 171 172 DynTInfo = getDynamicTypeInfo(State, Tmp->getRegion()); 173 if (!DynTInfo.isValid()) { 174 IsAnyFieldInitialized = true; 175 return false; 176 } 177 178 DynT = DynTInfo.getType(); 179 if (isVoidPointer(DynT)) { 180 IsAnyFieldInitialized = true; 181 return false; 182 } 183 184 DerefdV = State->getSVal(*Tmp, DynT); 185 } 186 187 // If FR is a pointer pointing to a non-primitive type. 188 if (Optional<nonloc::LazyCompoundVal> RecordV = 189 DerefdV.getAs<nonloc::LazyCompoundVal>()) { 190 191 const TypedValueRegion *R = RecordV->getRegion(); 192 193 if (DynT->getPointeeType()->isStructureOrClassType()) { 194 if (NeedsCastBack) 195 return isNonUnionUninit(R, LocalChain.add(NeedsCastLocField(FR, DynT))); 196 return isNonUnionUninit(R, LocalChain.add(LocField(FR))); 197 } 198 199 if (DynT->getPointeeType()->isUnionType()) { 200 if (isUnionUninit(R)) { 201 if (NeedsCastBack) 202 return addFieldToUninits(LocalChain.add(NeedsCastLocField(FR, DynT))); 203 return addFieldToUninits(LocalChain.add(LocField(FR))); 204 } else { 205 IsAnyFieldInitialized = true; 206 return false; 207 } 208 } 209 210 if (DynT->getPointeeType()->isArrayType()) { 211 IsAnyFieldInitialized = true; 212 return false; 213 } 214 215 llvm_unreachable("All cases are handled!"); 216 } 217 218 // Temporary variable to avoid warning from -Wunused-function. 219 bool IsPrimitive = isPrimitiveType(DynT->getPointeeType()); 220 assert((IsPrimitive || DynT->isAnyPointerType() || DynT->isReferenceType()) && 221 "At this point FR must either have a primitive dynamic type, or it " 222 "must be a null, undefined, unknown or concrete pointer!"); 223 (void)IsPrimitive; 224 225 if (isPrimitiveUninit(DerefdV)) { 226 if (NeedsCastBack) 227 return addFieldToUninits(LocalChain.add(NeedsCastLocField(FR, DynT))); 228 return addFieldToUninits(LocalChain.add(LocField(FR))); 229 } 230 231 IsAnyFieldInitialized = true; 232 return false; 233 } 234 235 //===----------------------------------------------------------------------===// 236 // Utility functions. 237 //===----------------------------------------------------------------------===// 238 239 static bool isVoidPointer(QualType T) { 240 while (!T.isNull()) { 241 if (T->isVoidPointerType()) 242 return true; 243 T = T->getPointeeType(); 244 } 245 return false; 246 } 247