clang  3.7.0
ObjCSelfInitChecker.cpp
Go to the documentation of this file.
1 //== ObjCSelfInitChecker.cpp - Checker for 'self' initialization -*- 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 defines ObjCSelfInitChecker, a builtin check that checks for uses of
11 // 'self' before proper initialization.
12 //
13 //===----------------------------------------------------------------------===//
14 
15 // This checks initialization methods to verify that they assign 'self' to the
16 // result of an initialization call (e.g. [super init], or [self initWith..])
17 // before using 'self' or any instance variable.
18 //
19 // To perform the required checking, values are tagged with flags that indicate
20 // 1) if the object is the one pointed to by 'self', and 2) if the object
21 // is the result of an initializer (e.g. [super init]).
22 //
23 // Uses of an object that is true for 1) but not 2) trigger a diagnostic.
24 // The uses that are currently checked are:
25 // - Using instance variables.
26 // - Returning the object.
27 //
28 // Note that we don't check for an invalid 'self' that is the receiver of an
29 // obj-c message expression to cut down false positives where logging functions
30 // get information from self (like its class) or doing "invalidation" on self
31 // when the initialization fails.
32 //
33 // Because the object that 'self' points to gets invalidated when a call
34 // receives a reference to 'self', the checker keeps track and passes the flags
35 // for 1) and 2) to the new object that 'self' points to after the call.
36 //
37 //===----------------------------------------------------------------------===//
38 
39 #include "ClangSACheckers.h"
40 #include "clang/AST/ParentMap.h"
47 #include "llvm/Support/raw_ostream.h"
48 
49 using namespace clang;
50 using namespace ento;
51 
52 static bool shouldRunOnFunctionOrMethod(const NamedDecl *ND);
53 static bool isInitializationMethod(const ObjCMethodDecl *MD);
54 static bool isInitMessage(const ObjCMethodCall &Msg);
55 static bool isSelfVar(SVal location, CheckerContext &C);
56 
57 namespace {
58 class ObjCSelfInitChecker : public Checker< check::PostObjCMessage,
59  check::PostStmt<ObjCIvarRefExpr>,
60  check::PreStmt<ReturnStmt>,
61  check::PreCall,
62  check::PostCall,
63  check::Location,
64  check::Bind > {
65  mutable std::unique_ptr<BugType> BT;
66 
67  void checkForInvalidSelf(const Expr *E, CheckerContext &C,
68  const char *errorStr) const;
69 
70 public:
71  ObjCSelfInitChecker() {}
72  void checkPostObjCMessage(const ObjCMethodCall &Msg, CheckerContext &C) const;
73  void checkPostStmt(const ObjCIvarRefExpr *E, CheckerContext &C) const;
74  void checkPreStmt(const ReturnStmt *S, CheckerContext &C) const;
75  void checkLocation(SVal location, bool isLoad, const Stmt *S,
76  CheckerContext &C) const;
77  void checkBind(SVal loc, SVal val, const Stmt *S, CheckerContext &C) const;
78 
79  void checkPreCall(const CallEvent &CE, CheckerContext &C) const;
80  void checkPostCall(const CallEvent &CE, CheckerContext &C) const;
81 
82  void printState(raw_ostream &Out, ProgramStateRef State,
83  const char *NL, const char *Sep) const override;
84 };
85 } // end anonymous namespace
86 
87 namespace {
89  /// \brief No flag set.
90  SelfFlag_None = 0x0,
91  /// \brief Value came from 'self'.
92  SelfFlag_Self = 0x1,
93  /// \brief Value came from the result of an initializer (e.g. [super init]).
94  SelfFlag_InitRes = 0x2
95 };
96 }
97 
98 REGISTER_MAP_WITH_PROGRAMSTATE(SelfFlag, SymbolRef, unsigned)
99 REGISTER_TRAIT_WITH_PROGRAMSTATE(CalledInit, bool)
100 
101 /// \brief A call receiving a reference to 'self' invalidates the object that
102 /// 'self' contains. This keeps the "self flags" assigned to the 'self'
103 /// object before the call so we can assign them to the new object that 'self'
104 /// points to after the call.
105 REGISTER_TRAIT_WITH_PROGRAMSTATE(PreCallSelfFlags, unsigned)
106 
108  if (SymbolRef sym = val.getAsSymbol())
109  if (const unsigned *attachedFlags = state->get<SelfFlag>(sym))
110  return (SelfFlagEnum)*attachedFlags;
111  return SelfFlag_None;
112 }
113 
115  return getSelfFlags(val, C.getState());
116 }
117 
118 static void addSelfFlag(ProgramStateRef state, SVal val,
119  SelfFlagEnum flag, CheckerContext &C) {
120  // We tag the symbol that the SVal wraps.
121  if (SymbolRef sym = val.getAsSymbol()) {
122  state = state->set<SelfFlag>(sym, getSelfFlags(val, state) | flag);
123  C.addTransition(state);
124  }
125 }
126 
127 static bool hasSelfFlag(SVal val, SelfFlagEnum flag, CheckerContext &C) {
128  return getSelfFlags(val, C) & flag;
129 }
130 
131 /// \brief Returns true of the value of the expression is the object that 'self'
132 /// points to and is an object that did not come from the result of calling
133 /// an initializer.
134 static bool isInvalidSelf(const Expr *E, CheckerContext &C) {
135  SVal exprVal = C.getState()->getSVal(E, C.getLocationContext());
136  if (!hasSelfFlag(exprVal, SelfFlag_Self, C))
137  return false; // value did not come from 'self'.
138  if (hasSelfFlag(exprVal, SelfFlag_InitRes, C))
139  return false; // 'self' is properly initialized.
140 
141  return true;
142 }
143 
144 void ObjCSelfInitChecker::checkForInvalidSelf(const Expr *E, CheckerContext &C,
145  const char *errorStr) const {
146  if (!E)
147  return;
148 
149  if (!C.getState()->get<CalledInit>())
150  return;
151 
152  if (!isInvalidSelf(E, C))
153  return;
154 
155  // Generate an error node.
156  ExplodedNode *N = C.generateSink();
157  if (!N)
158  return;
159 
160  if (!BT)
161  BT.reset(new BugType(this, "Missing \"self = [(super or self) init...]\"",
163  C.emitReport(llvm::make_unique<BugReport>(*BT, errorStr, N));
164 }
165 
166 void ObjCSelfInitChecker::checkPostObjCMessage(const ObjCMethodCall &Msg,
167  CheckerContext &C) const {
168  // When encountering a message that does initialization (init rule),
169  // tag the return value so that we know later on that if self has this value
170  // then it is properly initialized.
171 
172  // FIXME: A callback should disable checkers at the start of functions.
173  if (!shouldRunOnFunctionOrMethod(dyn_cast<NamedDecl>(
175  return;
176 
177  if (isInitMessage(Msg)) {
178  // Tag the return value as the result of an initializer.
179  ProgramStateRef state = C.getState();
180 
181  // FIXME this really should be context sensitive, where we record
182  // the current stack frame (for IPA). Also, we need to clean this
183  // value out when we return from this method.
184  state = state->set<CalledInit>(true);
185 
186  SVal V = state->getSVal(Msg.getOriginExpr(), C.getLocationContext());
187  addSelfFlag(state, V, SelfFlag_InitRes, C);
188  return;
189  }
190 
191  // We don't check for an invalid 'self' in an obj-c message expression to cut
192  // down false positives where logging functions get information from self
193  // (like its class) or doing "invalidation" on self when the initialization
194  // fails.
195 }
196 
197 void ObjCSelfInitChecker::checkPostStmt(const ObjCIvarRefExpr *E,
198  CheckerContext &C) const {
199  // FIXME: A callback should disable checkers at the start of functions.
200  if (!shouldRunOnFunctionOrMethod(dyn_cast<NamedDecl>(
202  return;
203 
204  checkForInvalidSelf(
205  E->getBase(), C,
206  "Instance variable used while 'self' is not set to the result of "
207  "'[(super or self) init...]'");
208 }
209 
210 void ObjCSelfInitChecker::checkPreStmt(const ReturnStmt *S,
211  CheckerContext &C) const {
212  // FIXME: A callback should disable checkers at the start of functions.
213  if (!shouldRunOnFunctionOrMethod(dyn_cast<NamedDecl>(
215  return;
216 
217  checkForInvalidSelf(S->getRetValue(), C,
218  "Returning 'self' while it is not set to the result of "
219  "'[(super or self) init...]'");
220 }
221 
222 // When a call receives a reference to 'self', [Pre/Post]Call pass
223 // the SelfFlags from the object 'self' points to before the call to the new
224 // object after the call. This is to avoid invalidation of 'self' by logging
225 // functions.
226 // Another common pattern in classes with multiple initializers is to put the
227 // subclass's common initialization bits into a static function that receives
228 // the value of 'self', e.g:
229 // @code
230 // if (!(self = [super init]))
231 // return nil;
232 // if (!(self = _commonInit(self)))
233 // return nil;
234 // @endcode
235 // Until we can use inter-procedural analysis, in such a call, transfer the
236 // SelfFlags to the result of the call.
237 
238 void ObjCSelfInitChecker::checkPreCall(const CallEvent &CE,
239  CheckerContext &C) const {
240  // FIXME: A callback should disable checkers at the start of functions.
241  if (!shouldRunOnFunctionOrMethod(dyn_cast<NamedDecl>(
243  return;
244 
245  ProgramStateRef state = C.getState();
246  unsigned NumArgs = CE.getNumArgs();
247  // If we passed 'self' as and argument to the call, record it in the state
248  // to be propagated after the call.
249  // Note, we could have just given up, but try to be more optimistic here and
250  // assume that the functions are going to continue initialization or will not
251  // modify self.
252  for (unsigned i = 0; i < NumArgs; ++i) {
253  SVal argV = CE.getArgSVal(i);
254  if (isSelfVar(argV, C)) {
255  unsigned selfFlags = getSelfFlags(state->getSVal(argV.castAs<Loc>()), C);
256  C.addTransition(state->set<PreCallSelfFlags>(selfFlags));
257  return;
258  } else if (hasSelfFlag(argV, SelfFlag_Self, C)) {
259  unsigned selfFlags = getSelfFlags(argV, C);
260  C.addTransition(state->set<PreCallSelfFlags>(selfFlags));
261  return;
262  }
263  }
264 }
265 
266 void ObjCSelfInitChecker::checkPostCall(const CallEvent &CE,
267  CheckerContext &C) const {
268  // FIXME: A callback should disable checkers at the start of functions.
269  if (!shouldRunOnFunctionOrMethod(dyn_cast<NamedDecl>(
271  return;
272 
273  ProgramStateRef state = C.getState();
274  SelfFlagEnum prevFlags = (SelfFlagEnum)state->get<PreCallSelfFlags>();
275  if (!prevFlags)
276  return;
277  state = state->remove<PreCallSelfFlags>();
278 
279  unsigned NumArgs = CE.getNumArgs();
280  for (unsigned i = 0; i < NumArgs; ++i) {
281  SVal argV = CE.getArgSVal(i);
282  if (isSelfVar(argV, C)) {
283  // If the address of 'self' is being passed to the call, assume that the
284  // 'self' after the call will have the same flags.
285  // EX: log(&self)
286  addSelfFlag(state, state->getSVal(argV.castAs<Loc>()), prevFlags, C);
287  return;
288  } else if (hasSelfFlag(argV, SelfFlag_Self, C)) {
289  // If 'self' is passed to the call by value, assume that the function
290  // returns 'self'. So assign the flags, which were set on 'self' to the
291  // return value.
292  // EX: self = performMoreInitialization(self)
293  addSelfFlag(state, CE.getReturnValue(), prevFlags, C);
294  return;
295  }
296  }
297 
298  C.addTransition(state);
299 }
300 
301 void ObjCSelfInitChecker::checkLocation(SVal location, bool isLoad,
302  const Stmt *S,
303  CheckerContext &C) const {
304  if (!shouldRunOnFunctionOrMethod(dyn_cast<NamedDecl>(
306  return;
307 
308  // Tag the result of a load from 'self' so that we can easily know that the
309  // value is the object that 'self' points to.
310  ProgramStateRef state = C.getState();
311  if (isSelfVar(location, C))
312  addSelfFlag(state, state->getSVal(location.castAs<Loc>()), SelfFlag_Self,
313  C);
314 }
315 
316 
317 void ObjCSelfInitChecker::checkBind(SVal loc, SVal val, const Stmt *S,
318  CheckerContext &C) const {
319  // Allow assignment of anything to self. Self is a local variable in the
320  // initializer, so it is legal to assign anything to it, like results of
321  // static functions/method calls. After self is assigned something we cannot
322  // reason about, stop enforcing the rules.
323  // (Only continue checking if the assigned value should be treated as self.)
324  if ((isSelfVar(loc, C)) &&
325  !hasSelfFlag(val, SelfFlag_InitRes, C) &&
326  !hasSelfFlag(val, SelfFlag_Self, C) &&
327  !isSelfVar(val, C)) {
328 
329  // Stop tracking the checker-specific state in the state.
331  State = State->remove<CalledInit>();
332  if (SymbolRef sym = loc.getAsSymbol())
333  State = State->remove<SelfFlag>(sym);
334  C.addTransition(State);
335  }
336 }
337 
338 void ObjCSelfInitChecker::printState(raw_ostream &Out, ProgramStateRef State,
339  const char *NL, const char *Sep) const {
340  SelfFlagTy FlagMap = State->get<SelfFlag>();
341  bool DidCallInit = State->get<CalledInit>();
342  SelfFlagEnum PreCallFlags = (SelfFlagEnum)State->get<PreCallSelfFlags>();
343 
344  if (FlagMap.isEmpty() && !DidCallInit && !PreCallFlags)
345  return;
346 
347  Out << Sep << NL << *this << " :" << NL;
348 
349  if (DidCallInit)
350  Out << " An init method has been called." << NL;
351 
352  if (PreCallFlags != SelfFlag_None) {
353  if (PreCallFlags & SelfFlag_Self) {
354  Out << " An argument of the current call came from the 'self' variable."
355  << NL;
356  }
357  if (PreCallFlags & SelfFlag_InitRes) {
358  Out << " An argument of the current call came from an init method."
359  << NL;
360  }
361  }
362 
363  Out << NL;
364  for (SelfFlagTy::iterator I = FlagMap.begin(), E = FlagMap.end();
365  I != E; ++I) {
366  Out << I->first << " : ";
367 
368  if (I->second == SelfFlag_None)
369  Out << "none";
370 
371  if (I->second & SelfFlag_Self)
372  Out << "self variable";
373 
374  if (I->second & SelfFlag_InitRes) {
375  if (I->second != SelfFlag_InitRes)
376  Out << " | ";
377  Out << "result of init method";
378  }
379 
380  Out << NL;
381  }
382 }
383 
384 
385 // FIXME: A callback should disable checkers at the start of functions.
386 static bool shouldRunOnFunctionOrMethod(const NamedDecl *ND) {
387  if (!ND)
388  return false;
389 
390  const ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(ND);
391  if (!MD)
392  return false;
393  if (!isInitializationMethod(MD))
394  return false;
395 
396  // self = [super init] applies only to NSObject subclasses.
397  // For instance, NSProxy doesn't implement -init.
398  ASTContext &Ctx = MD->getASTContext();
399  IdentifierInfo* NSObjectII = &Ctx.Idents.get("NSObject");
401  for ( ; ID ; ID = ID->getSuperClass()) {
402  IdentifierInfo *II = ID->getIdentifier();
403 
404  if (II == NSObjectII)
405  break;
406  }
407  if (!ID)
408  return false;
409 
410  return true;
411 }
412 
413 /// \brief Returns true if the location is 'self'.
414 static bool isSelfVar(SVal location, CheckerContext &C) {
416  if (!analCtx->getSelfDecl())
417  return false;
418  if (!location.getAs<loc::MemRegionVal>())
419  return false;
420 
421  loc::MemRegionVal MRV = location.castAs<loc::MemRegionVal>();
422  if (const DeclRegion *DR = dyn_cast<DeclRegion>(MRV.stripCasts()))
423  return (DR->getDecl() == analCtx->getSelfDecl());
424 
425  return false;
426 }
427 
428 static bool isInitializationMethod(const ObjCMethodDecl *MD) {
429  return MD->getMethodFamily() == OMF_init;
430 }
431 
432 static bool isInitMessage(const ObjCMethodCall &Call) {
433  return Call.getMethodFamily() == OMF_init;
434 }
435 
436 //===----------------------------------------------------------------------===//
437 // Registration.
438 //===----------------------------------------------------------------------===//
439 
440 void ento::registerObjCSelfInitChecker(CheckerManager &mgr) {
441  mgr.registerChecker<ObjCSelfInitChecker>();
442 }
virtual SVal getArgSVal(unsigned Index) const
Returns the value of a given argument at the time of the call.
Definition: CallEvent.cpp:195
const Expr * getBase() const
Definition: ExprObjC.h:504
const char *const CoreFoundationObjectiveC
ObjCInterfaceDecl * getClassInterface()
Definition: DeclObjC.cpp:1014
const MemRegion * stripCasts(bool StripBaseCasts=true) const
Get the underlining region and strip casts.
Definition: SVals.cpp:145
IdentifierInfo * getIdentifier() const
Definition: Decl.h:163
ExplodedNode * addTransition(ProgramStateRef State=nullptr, const ProgramPointTag *Tag=nullptr)
Generates a new transition in the program state graph (ExplodedGraph). Uses the default CheckerContex...
const ImplicitParamDecl * getSelfDecl() const
Symbolic value. These values used to capture symbolic execution of the program.
Definition: SymbolManager.h:42
static bool isInvalidSelf(const Expr *E, CheckerContext &C)
Returns true of the value of the expression is the object that 'self' points to and is an object that...
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
Definition: ASTContext.h:89
LineState State
IdentifierTable & Idents
Definition: ASTContext.h:439
static bool isInitMessage(const ObjCMethodCall &Msg)
static bool isInitializationMethod(const ObjCMethodDecl *MD)
Represents any expression that calls an Objective-C method.
Definition: CallEvent.h:791
ObjCMethodFamily getMethodFamily() const
Determines the family of this method.
Definition: DeclObjC.cpp:856
static void addSelfFlag(ProgramStateRef state, SVal val, SelfFlagEnum flag, CheckerContext &C)
static SelfFlagEnum getSelfFlags(SVal val, ProgramStateRef state)
A call receiving a reference to 'self' invalidates the object that 'self' contains. This keeps the "self flags" assigned to the 'self' object before the call so we can assign them to the new object that 'self' points to after the call.
const Decl * getDecl() const
Represents an ObjC class declaration.
Definition: DeclObjC.h:851
ExplodedNode * generateSink(ProgramStateRef State=nullptr, ExplodedNode *Pred=nullptr, const ProgramPointTag *Tag=nullptr)
Generate a sink node. Generating a sink stops exploration of the given path.
ID
Defines the set of possible language-specific address spaces.
Definition: AddressSpaces.h:27
const ProgramStateRef & getState() const
static bool shouldRunOnFunctionOrMethod(const NamedDecl *ND)
Optional< T > getAs() const
Convert to the specified SVal type, returning None if this SVal is not of the desired type...
Definition: SVals.h:86
ObjCMethodFamily getMethodFamily() const
Definition: CallEvent.h:829
void emitReport(std::unique_ptr< BugReport > R)
Emit the diagnostics report.
static bool hasSelfFlag(SVal val, SelfFlagEnum flag, CheckerContext &C)
#define REGISTER_TRAIT_WITH_PROGRAMSTATE(Name, Type)
CHECKER * registerChecker()
Used to register checkers.
IdentifierInfo & get(StringRef Name)
Return the identifier token info for the specified named identifier.
ASTContext & getASTContext() const LLVM_READONLY
Definition: DeclBase.cpp:284
static bool isSelfVar(SVal location, CheckerContext &C)
Returns true if the location is 'self'.
REGISTER_MAP_WITH_PROGRAMSTATE(AllocatedData, SymbolRef, MacOSKeychainAPIChecker::AllocationState) static bool isEnclosingFunctionParam(const Expr *E)
const Expr * getRetValue() const
Definition: Stmt.cpp:1013
Represents an abstract call to a function or method along a particular path.
Definition: CallEvent.h:113
ObjCIvarRefExpr - A reference to an ObjC instance variable.
Definition: ExprObjC.h:474
AnalysisDeclContext * getCurrentAnalysisDeclContext() const
virtual unsigned getNumArgs() const =0
Returns the number of arguments (explicit and implicit).
SymbolRef getAsSymbol(bool IncludeBaseRegions=false) const
If this SVal wraps a symbol return that SymbolRef. Otherwise, return 0.
Definition: SVals.cpp:111
ObjCInterfaceDecl * getSuperClass() const
Definition: DeclObjC.cpp:271
virtual const ObjCMessageExpr * getOriginExpr() const
Definition: CallEvent.h:813
SVal getReturnValue() const
Returns the return value of the call.
Definition: CallEvent.cpp:209
T castAs() const
Convert to the specified SVal type, asserting that this SVal is of the desired type.
Definition: SVals.h:75
const LocationContext * getLocationContext() const