1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | |
8 | |
9 | |
10 | |
11 | |
12 | |
13 | #include "clang/AST/StmtObjC.h" |
14 | #include "clang/StaticAnalyzer/Core/CheckerManager.h" |
15 | #include "clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h" |
16 | #include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h" |
17 | |
18 | using namespace clang; |
19 | using namespace ento; |
20 | |
21 | void ExprEngine::VisitLvalObjCIvarRefExpr(const ObjCIvarRefExpr *Ex, |
22 | ExplodedNode *Pred, |
23 | ExplodedNodeSet &Dst) { |
24 | ProgramStateRef state = Pred->getState(); |
25 | const LocationContext *LCtx = Pred->getLocationContext(); |
26 | SVal baseVal = state->getSVal(Ex->getBase(), LCtx); |
27 | SVal location = state->getLValue(Ex->getDecl(), baseVal); |
28 | |
29 | ExplodedNodeSet dstIvar; |
30 | StmtNodeBuilder Bldr(Pred, dstIvar, *currBldrCtx); |
31 | Bldr.generateNode(Ex, Pred, state->BindExpr(Ex, LCtx, location)); |
32 | |
33 | |
34 | |
35 | getCheckerManager().runCheckersForPostStmt(Dst, dstIvar, Ex, *this); |
36 | } |
37 | |
38 | void ExprEngine::VisitObjCAtSynchronizedStmt(const ObjCAtSynchronizedStmt *S, |
39 | ExplodedNode *Pred, |
40 | ExplodedNodeSet &Dst) { |
41 | getCheckerManager().runCheckersForPreStmt(Dst, Pred, S, *this); |
42 | } |
43 | |
44 | |
45 | |
46 | static void populateObjCForDestinationSet( |
47 | ExplodedNodeSet &dstLocation, SValBuilder &svalBuilder, |
48 | const ObjCForCollectionStmt *S, const Stmt *elem, SVal elementV, |
49 | SymbolManager &SymMgr, const NodeBuilderContext *currBldrCtx, |
50 | StmtNodeBuilder &Bldr, bool hasElements) { |
51 | |
52 | for (ExplodedNode *Pred : dstLocation) { |
53 | ProgramStateRef state = Pred->getState(); |
54 | const LocationContext *LCtx = Pred->getLocationContext(); |
55 | |
56 | SVal hasElementsV = svalBuilder.makeTruthVal(hasElements); |
57 | |
58 | |
59 | ProgramStateRef nextState = state->BindExpr(S, LCtx, hasElementsV); |
60 | |
61 | if (auto MV = elementV.getAs<loc::MemRegionVal>()) |
62 | if (const auto *R = dyn_cast<TypedValueRegion>(MV->getRegion())) { |
63 | |
64 | |
65 | |
66 | QualType T = R->getValueType(); |
67 | assert(Loc::isLocType(T)); |
68 | |
69 | SVal V; |
70 | if (hasElements) { |
71 | SymbolRef Sym = SymMgr.conjureSymbol(elem, LCtx, T, |
72 | currBldrCtx->blockCount()); |
73 | V = svalBuilder.makeLoc(Sym); |
74 | } else { |
75 | V = svalBuilder.makeIntVal(0, T); |
76 | } |
77 | |
78 | nextState = nextState->bindLoc(elementV, V, LCtx); |
79 | } |
80 | |
81 | Bldr.generateNode(S, Pred, nextState); |
82 | } |
83 | } |
84 | |
85 | void ExprEngine::VisitObjCForCollectionStmt(const ObjCForCollectionStmt *S, |
86 | ExplodedNode *Pred, |
87 | ExplodedNodeSet &Dst) { |
88 | |
89 | |
90 | |
91 | |
92 | |
93 | |
94 | |
95 | |
96 | |
97 | |
98 | |
99 | |
100 | |
101 | |
102 | |
103 | |
104 | |
105 | |
106 | |
107 | |
108 | |
109 | |
110 | |
111 | |
112 | |
113 | |
114 | const Stmt *elem = S->getElement(); |
115 | const Stmt *collection = S->getCollection(); |
116 | ProgramStateRef state = Pred->getState(); |
117 | SVal collectionV = state->getSVal(collection, Pred->getLocationContext()); |
118 | |
119 | SVal elementV; |
120 | if (const auto *DS = dyn_cast<DeclStmt>(elem)) { |
121 | const VarDecl *elemD = cast<VarDecl>(DS->getSingleDecl()); |
122 | getInit() == nullptr", "/home/seafit/code_projects/clang_source/clang/lib/StaticAnalyzer/Core/ExprEngineObjC.cpp", 122, __PRETTY_FUNCTION__))" file_link="../../../../include/assert.h.html#88" macro="true">assert(elemD->getInit() == nullptr); |
123 | elementV = state->getLValue(elemD, Pred->getLocationContext()); |
124 | } else { |
125 | elementV = state->getSVal(elem, Pred->getLocationContext()); |
126 | } |
127 | |
128 | bool isContainerNull = state->isNull(collectionV).isConstrainedTrue(); |
129 | |
130 | ExplodedNodeSet dstLocation; |
131 | evalLocation(dstLocation, S, elem, Pred, state, elementV, false); |
132 | |
133 | ExplodedNodeSet Tmp; |
134 | StmtNodeBuilder Bldr(Pred, Tmp, *currBldrCtx); |
135 | |
136 | if (!isContainerNull) |
137 | populateObjCForDestinationSet(dstLocation, svalBuilder, S, elem, elementV, |
138 | SymMgr, currBldrCtx, Bldr, |
139 | ); |
140 | |
141 | populateObjCForDestinationSet(dstLocation, svalBuilder, S, elem, elementV, |
142 | SymMgr, currBldrCtx, Bldr, |
143 | ); |
144 | |
145 | |
146 | |
147 | getCheckerManager().runCheckersForPostStmt(Dst, Tmp, S, *this); |
148 | } |
149 | |
150 | void ExprEngine::VisitObjCMessage(const ObjCMessageExpr *ME, |
151 | ExplodedNode *Pred, |
152 | ExplodedNodeSet &Dst) { |
153 | CallEventManager &CEMgr = getStateManager().getCallEventManager(); |
154 | CallEventRef<ObjCMethodCall> Msg = |
155 | CEMgr.getObjCMethodCall(ME, Pred->getState(), Pred->getLocationContext()); |
156 | |
157 | |
158 | |
159 | |
160 | |
161 | |
162 | |
163 | |
164 | |
165 | |
166 | |
167 | |
168 | |
169 | |
170 | |
171 | |
172 | |
173 | |
174 | |
175 | |
176 | |
177 | |
178 | |
179 | |
180 | |
181 | |
182 | |
183 | |
184 | |
185 | |
186 | if (Msg->isInstanceMessage()) { |
187 | SVal recVal = Msg->getReceiverSVal(); |
188 | if (!recVal.isUndef()) { |
189 | |
190 | DefinedOrUnknownSVal receiverVal = |
191 | recVal.castAs<DefinedOrUnknownSVal>(); |
192 | ProgramStateRef State = Pred->getState(); |
193 | |
194 | ProgramStateRef notNilState, nilState; |
195 | std::tie(notNilState, nilState) = State->assume(receiverVal); |
196 | |
197 | |
198 | if (nilState && !notNilState) { |
199 | ExplodedNodeSet dstNil; |
200 | StmtNodeBuilder Bldr(Pred, dstNil, *currBldrCtx); |
201 | bool HasTag = Pred->getLocation().getTag(); |
202 | Pred = Bldr.generateNode(ME, Pred, nilState, nullptr, |
203 | ProgramPoint::PreStmtKind); |
204 | (0) . __assert_fail ("(Pred || HasTag) && \"Should have cached out already!\"", "/home/seafit/code_projects/clang_source/clang/lib/StaticAnalyzer/Core/ExprEngineObjC.cpp", 204, __PRETTY_FUNCTION__))" file_link="../../../../include/assert.h.html#88" macro="true">assert((Pred || HasTag) && "Should have cached out already!"); |
205 | (void)HasTag; |
206 | if (!Pred) |
207 | return; |
208 | |
209 | ExplodedNodeSet dstPostCheckers; |
210 | getCheckerManager().runCheckersForObjCMessageNil(dstPostCheckers, Pred, |
211 | *Msg, *this); |
212 | for (auto I : dstPostCheckers) |
213 | finishArgumentConstruction(Dst, I, *Msg); |
214 | return; |
215 | } |
216 | |
217 | ExplodedNodeSet dstNonNil; |
218 | StmtNodeBuilder Bldr(Pred, dstNonNil, *currBldrCtx); |
219 | |
220 | |
221 | if (notNilState != State) { |
222 | bool HasTag = Pred->getLocation().getTag(); |
223 | Pred = Bldr.generateNode(ME, Pred, notNilState); |
224 | (0) . __assert_fail ("(Pred || HasTag) && \"Should have cached out already!\"", "/home/seafit/code_projects/clang_source/clang/lib/StaticAnalyzer/Core/ExprEngineObjC.cpp", 224, __PRETTY_FUNCTION__))" file_link="../../../../include/assert.h.html#88" macro="true">assert((Pred || HasTag) && "Should have cached out already!"); |
225 | (void)HasTag; |
226 | if (!Pred) |
227 | return; |
228 | } |
229 | } |
230 | } |
231 | |
232 | |
233 | ExplodedNodeSet dstPrevisit; |
234 | getCheckerManager().runCheckersForPreObjCMessage(dstPrevisit, Pred, |
235 | *Msg, *this); |
236 | ExplodedNodeSet dstGenericPrevisit; |
237 | getCheckerManager().runCheckersForPreCall(dstGenericPrevisit, dstPrevisit, |
238 | *Msg, *this); |
239 | |
240 | |
241 | ExplodedNodeSet dstEval; |
242 | StmtNodeBuilder Bldr(dstGenericPrevisit, dstEval, *currBldrCtx); |
243 | |
244 | for (ExplodedNodeSet::iterator DI = dstGenericPrevisit.begin(), |
245 | DE = dstGenericPrevisit.end(); DI != DE; ++DI) { |
246 | ExplodedNode *Pred = *DI; |
247 | ProgramStateRef State = Pred->getState(); |
248 | CallEventRef<ObjCMethodCall> UpdatedMsg = Msg.cloneWithState(State); |
249 | |
250 | if (UpdatedMsg->isInstanceMessage()) { |
251 | SVal recVal = UpdatedMsg->getReceiverSVal(); |
252 | if (!recVal.isUndef()) { |
253 | if (ObjCNoRet.isImplicitNoReturn(ME)) { |
254 | |
255 | |
256 | Bldr.generateSink(ME, Pred, State); |
257 | continue; |
258 | } |
259 | } |
260 | } else { |
261 | |
262 | |
263 | if (ObjCNoRet.isImplicitNoReturn(ME)) { |
264 | |
265 | |
266 | Bldr.generateSink(ME, Pred, Pred->getState()); |
267 | continue; |
268 | } |
269 | } |
270 | |
271 | defaultEvalCall(Bldr, Pred, *UpdatedMsg); |
272 | } |
273 | |
274 | |
275 | ExplodedNodeSet dstArgCleanup; |
276 | for (auto I : dstEval) |
277 | finishArgumentConstruction(dstArgCleanup, I, *Msg); |
278 | |
279 | ExplodedNodeSet dstPostvisit; |
280 | getCheckerManager().runCheckersForPostCall(dstPostvisit, dstArgCleanup, |
281 | *Msg, *this); |
282 | |
283 | |
284 | |
285 | getCheckerManager().runCheckersForPostObjCMessage(Dst, dstPostvisit, |
286 | *Msg, *this); |
287 | } |
288 | |