clang  8.0.0svn
ObjCAtSyncChecker.cpp
Go to the documentation of this file.
1 //== ObjCAtSyncChecker.cpp - nil mutex checker for @synchronized -*- 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 ObjCAtSyncChecker, a builtin check that checks for null pointers
11 // used as mutexes for @synchronized.
12 //
13 //===----------------------------------------------------------------------===//
14 
15 #include "ClangSACheckers.h"
16 #include "clang/AST/StmtObjC.h"
22 
23 using namespace clang;
24 using namespace ento;
25 
26 namespace {
27 class ObjCAtSyncChecker
28  : public Checker< check::PreStmt<ObjCAtSynchronizedStmt> > {
29  mutable std::unique_ptr<BuiltinBug> BT_null;
30  mutable std::unique_ptr<BuiltinBug> BT_undef;
31 
32 public:
33  void checkPreStmt(const ObjCAtSynchronizedStmt *S, CheckerContext &C) const;
34 };
35 } // end anonymous namespace
36 
37 void ObjCAtSyncChecker::checkPreStmt(const ObjCAtSynchronizedStmt *S,
38  CheckerContext &C) const {
39 
40  const Expr *Ex = S->getSynchExpr();
41  ProgramStateRef state = C.getState();
42  SVal V = C.getSVal(Ex);
43 
44  // Uninitialized value used for the mutex?
45  if (V.getAs<UndefinedVal>()) {
46  if (ExplodedNode *N = C.generateErrorNode()) {
47  if (!BT_undef)
48  BT_undef.reset(new BuiltinBug(this, "Uninitialized value used as mutex "
49  "for @synchronized"));
50  auto report =
51  llvm::make_unique<BugReport>(*BT_undef, BT_undef->getDescription(), N);
52  bugreporter::trackNullOrUndefValue(N, Ex, *report);
53  C.emitReport(std::move(report));
54  }
55  return;
56  }
57 
58  if (V.isUnknown())
59  return;
60 
61  // Check for null mutexes.
62  ProgramStateRef notNullState, nullState;
63  std::tie(notNullState, nullState) = state->assume(V.castAs<DefinedSVal>());
64 
65  if (nullState) {
66  if (!notNullState) {
67  // Generate an error node. This isn't a sink since
68  // a null mutex just means no synchronization occurs.
69  if (ExplodedNode *N = C.generateNonFatalErrorNode(nullState)) {
70  if (!BT_null)
71  BT_null.reset(new BuiltinBug(
72  this, "Nil value used as mutex for @synchronized() "
73  "(no synchronization will occur)"));
74  auto report =
75  llvm::make_unique<BugReport>(*BT_null, BT_null->getDescription(), N);
76  bugreporter::trackNullOrUndefValue(N, Ex, *report);
77 
78  C.emitReport(std::move(report));
79  return;
80  }
81  }
82  // Don't add a transition for 'nullState'. If the value is
83  // under-constrained to be null or non-null, assume it is non-null
84  // afterwards.
85  }
86 
87  if (notNullState)
88  C.addTransition(notNullState);
89 }
90 
91 void ento::registerObjCAtSyncChecker(CheckerManager &mgr) {
92  if (mgr.getLangOpts().ObjC2)
93  mgr.registerChecker<ObjCAtSyncChecker>();
94 }
IntrusiveRefCntPtr< const ProgramState > ProgramStateRef
Defines the Objective-C statement AST node classes.
i32 captured_struct **param SharedsTy A type which contains references the shared variables *param Shareds Context with the list of shared variables from the p *TaskFunction *param Data Additional data for task generation like final * state
This represents one expression.
Definition: Expr.h:105
Represents Objective-C&#39;s @synchronized statement.
Definition: StmtObjC.h:262
Dataflow Directional Tag Classes.
const Expr * getSynchExpr() const
Definition: StmtObjC.h:290