blob: 90d2ff00510ecb742a282ae18ae3a2622702163a [file] [log] [blame]
Kristof Umann56963ae2018-08-13 18:17:05 +00001//===----- 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
Kristof Umann56963ae2018-08-13 18:17:05 +000021#include "ClangSACheckers.h"
Kristof Umanna37bba42018-08-13 18:22:22 +000022#include "UninitializedObject.h"
Kristof Umann56963ae2018-08-13 18:17:05 +000023#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
28using namespace clang;
29using 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.
36static 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.
44bool 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
164static bool isVoidPointer(QualType T) {
165 while (!T.isNull()) {
166 if (T->isVoidPointerType())
167 return true;
168 T = T->getPointeeType();
169 }
170 return false;
171}