Coverage Report

Created: 2019-07-24 05:18

/Users/buildslave/jenkins/workspace/clang-stage2-coverage-R/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ObjCAtSyncChecker.cpp
Line
Count
Source (jump to first uncovered line)
1
//== ObjCAtSyncChecker.cpp - nil mutex checker for @synchronized -*- C++ -*--=//
2
//
3
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4
// See https://llvm.org/LICENSE.txt for license information.
5
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6
//
7
//===----------------------------------------------------------------------===//
8
//
9
// This defines ObjCAtSyncChecker, a builtin check that checks for null pointers
10
// used as mutexes for @synchronized.
11
//
12
//===----------------------------------------------------------------------===//
13
14
#include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h"
15
#include "clang/AST/StmtObjC.h"
16
#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
17
#include "clang/StaticAnalyzer/Core/Checker.h"
18
#include "clang/StaticAnalyzer/Core/CheckerManager.h"
19
#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
20
#include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h"
21
22
using namespace clang;
23
using namespace ento;
24
25
namespace {
26
class ObjCAtSyncChecker
27
    : public Checker< check::PreStmt<ObjCAtSynchronizedStmt> > {
28
  mutable std::unique_ptr<BuiltinBug> BT_null;
29
  mutable std::unique_ptr<BuiltinBug> BT_undef;
30
31
public:
32
  void checkPreStmt(const ObjCAtSynchronizedStmt *S, CheckerContext &C) const;
33
};
34
} // end anonymous namespace
35
36
void ObjCAtSyncChecker::checkPreStmt(const ObjCAtSynchronizedStmt *S,
37
14
                                     CheckerContext &C) const {
38
14
39
14
  const Expr *Ex = S->getSynchExpr();
40
14
  ProgramStateRef state = C.getState();
41
14
  SVal V = C.getSVal(Ex);
42
14
43
14
  // Uninitialized value used for the mutex?
44
14
  if (V.getAs<UndefinedVal>()) {
45
2
    if (ExplodedNode *N = C.generateErrorNode()) {
46
2
      if (!BT_undef)
47
2
        BT_undef.reset(new BuiltinBug(this, "Uninitialized value used as mutex "
48
2
                                            "for @synchronized"));
49
2
      auto report =
50
2
          llvm::make_unique<BugReport>(*BT_undef, BT_undef->getDescription(), N);
51
2
      bugreporter::trackExpressionValue(N, Ex, *report);
52
2
      C.emitReport(std::move(report));
53
2
    }
54
2
    return;
55
2
  }
56
12
57
12
  if (V.isUnknown())
58
0
    return;
59
12
60
12
  // Check for null mutexes.
61
12
  ProgramStateRef notNullState, nullState;
62
12
  std::tie(notNullState, nullState) = state->assume(V.castAs<DefinedSVal>());
63
12
64
12
  if (nullState) {
65
10
    if (!notNullState) {
66
4
      // Generate an error node.  This isn't a sink since
67
4
      // a null mutex just means no synchronization occurs.
68
4
      if (ExplodedNode *N = C.generateNonFatalErrorNode(nullState)) {
69
4
        if (!BT_null)
70
2
          BT_null.reset(new BuiltinBug(
71
2
              this, "Nil value used as mutex for @synchronized() "
72
2
                    "(no synchronization will occur)"));
73
4
        auto report =
74
4
            llvm::make_unique<BugReport>(*BT_null, BT_null->getDescription(), N);
75
4
        bugreporter::trackExpressionValue(N, Ex, *report);
76
4
77
4
        C.emitReport(std::move(report));
78
4
        return;
79
4
      }
80
8
    }
81
10
    // Don't add a transition for 'nullState'.  If the value is
82
10
    // under-constrained to be null or non-null, assume it is non-null
83
10
    // afterwards.
84
10
  }
85
8
86
8
  if (notNullState)
87
8
    C.addTransition(notNullState);
88
8
}
89
90
8
void ento::registerObjCAtSyncChecker(CheckerManager &mgr) {
91
8
  mgr.registerChecker<ObjCAtSyncChecker>();
92
8
}
93
94
25
bool ento::shouldRegisterObjCAtSyncChecker(const LangOptions &LO) {
95
25
  return LO.ObjC;
96
25
}