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 "UninitializedObject.h" 22 #include "ClangSACheckers.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 // Utility function declarations. 32 33 /// Returns whether T can be (transitively) dereferenced to a void pointer type 34 /// (void*, void**, ...). The type of the region behind a void pointer isn't 35 /// known, and thus FD can not be analyzed. 36 static bool isVoidPointer(QualType T); 37 38 //===----------------------------------------------------------------------===// 39 // Methods for FindUninitializedFields. 40 //===----------------------------------------------------------------------===// 41 42 // Note that pointers/references don't contain fields themselves, so in this 43 // function we won't add anything to LocalChain. 44 bool FindUninitializedFields::isPointerOrReferenceUninit( 45 const FieldRegion *FR, FieldChainInfo LocalChain) { 46 47 assert((FR->getDecl()->getType()->isPointerType() || 48 FR->getDecl()->getType()->isReferenceType() || 49 FR->getDecl()->getType()->isBlockPointerType()) && 50 "This method only checks pointer/reference objects!"); 51 52 SVal V = State->getSVal(FR); 53 54 if (V.isUnknown() || V.getAs<loc::ConcreteInt>()) { 55 IsAnyFieldInitialized = true; 56 return false; 57 } 58 59 if (V.isUndef()) { 60 return addFieldToUninits({LocalChain, FR}); 61 } 62 63 if (!CheckPointeeInitialization) { 64 IsAnyFieldInitialized = true; 65 return false; 66 } 67 68 assert(V.getAs<loc::MemRegionVal>() && 69 "At this point V must be loc::MemRegionVal!"); 70 auto L = V.castAs<loc::MemRegionVal>(); 71 72 // We can't reason about symbolic regions, assume its initialized. 73 // Note that this also avoids a potential infinite recursion, because 74 // constructors for list-like classes are checked without being called, and 75 // the Static Analyzer will construct a symbolic region for Node *next; or 76 // similar code snippets. 77 if (L.getRegion()->getSymbolicBase()) { 78 IsAnyFieldInitialized = true; 79 return false; 80 } 81 82 DynamicTypeInfo DynTInfo = getDynamicTypeInfo(State, L.getRegion()); 83 if (!DynTInfo.isValid()) { 84 IsAnyFieldInitialized = true; 85 return false; 86 } 87 88 QualType DynT = DynTInfo.getType(); 89 90 if (isVoidPointer(DynT)) { 91 IsAnyFieldInitialized = true; 92 return false; 93 } 94 95 // At this point the pointer itself is initialized and points to a valid 96 // location, we'll now check the pointee. 97 SVal DerefdV = State->getSVal(V.castAs<Loc>(), DynT); 98 99 // If DerefdV is still a pointer value, we'll dereference it again (e.g.: 100 // int** -> int*). 101 while (auto Tmp = DerefdV.getAs<loc::MemRegionVal>()) { 102 if (Tmp->getRegion()->getSymbolicBase()) { 103 IsAnyFieldInitialized = true; 104 return false; 105 } 106 107 DynTInfo = getDynamicTypeInfo(State, Tmp->getRegion()); 108 if (!DynTInfo.isValid()) { 109 IsAnyFieldInitialized = true; 110 return false; 111 } 112 113 DynT = DynTInfo.getType(); 114 if (isVoidPointer(DynT)) { 115 IsAnyFieldInitialized = true; 116 return false; 117 } 118 119 DerefdV = State->getSVal(*Tmp, DynT); 120 } 121 122 // If FR is a pointer pointing to a non-primitive type. 123 if (Optional<nonloc::LazyCompoundVal> RecordV = 124 DerefdV.getAs<nonloc::LazyCompoundVal>()) { 125 126 const TypedValueRegion *R = RecordV->getRegion(); 127 128 if (DynT->getPointeeType()->isStructureOrClassType()) 129 return isNonUnionUninit(R, {LocalChain, FR}); 130 131 if (DynT->getPointeeType()->isUnionType()) { 132 if (isUnionUninit(R)) { 133 return addFieldToUninits({LocalChain, FR, /*IsDereferenced*/ true}); 134 } else { 135 IsAnyFieldInitialized = true; 136 return false; 137 } 138 } 139 140 if (DynT->getPointeeType()->isArrayType()) { 141 IsAnyFieldInitialized = true; 142 return false; 143 } 144 145 llvm_unreachable("All cases are handled!"); 146 } 147 148 assert((isPrimitiveType(DynT->getPointeeType()) || DynT->isPointerType() || 149 DynT->isReferenceType()) && 150 "At this point FR must either have a primitive dynamic type, or it " 151 "must be a null, undefined, unknown or concrete pointer!"); 152 153 if (isPrimitiveUninit(DerefdV)) 154 return addFieldToUninits({LocalChain, FR, /*IsDereferenced*/ true}); 155 156 IsAnyFieldInitialized = true; 157 return false; 158 } 159 160 //===----------------------------------------------------------------------===// 161 // Utility functions. 162 //===----------------------------------------------------------------------===// 163 164 static bool isVoidPointer(QualType T) { 165 while (!T.isNull()) { 166 if (T->isVoidPointerType()) 167 return true; 168 T = T->getPointeeType(); 169 } 170 return false; 171 } 172