blob: 7d440ab17e9f10e6614260a875c24c5b595f0921 [file] [log] [blame]
Ted Kremenek942e24d2010-09-10 03:45:29 +00001//== 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
Argyrios Kyrtzidis027a6ab2011-02-15 07:42:33 +000015#include "ClangSACheckers.h"
Argyrios Kyrtzidis695fb502011-02-17 21:39:17 +000016#include "clang/StaticAnalyzer/Core/CheckerManager.h"
Ted Kremenek9b663712011-02-10 01:03:03 +000017#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
Ted Kremenek21142582010-12-23 19:38:26 +000018#include "clang/StaticAnalyzer/Checkers/DereferenceChecker.h"
Ted Kremenek9b663712011-02-10 01:03:03 +000019#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerVisitor.h"
20#include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h"
Ted Kremenek942e24d2010-09-10 03:45:29 +000021
22using namespace clang;
Ted Kremenek9ef65372010-12-23 07:20:52 +000023using namespace ento;
Ted Kremenek942e24d2010-09-10 03:45:29 +000024
25namespace {
26class ObjCAtSyncChecker : public CheckerVisitor<ObjCAtSyncChecker> {
27 BuiltinBug *BT_null;
28 BuiltinBug *BT_undef;
29public:
30 ObjCAtSyncChecker() : BT_null(0), BT_undef(0) {}
31 static void *getTag() { static int tag = 0; return &tag; }
32 void PreVisitObjCAtSynchronizedStmt(CheckerContext &C,
33 const ObjCAtSynchronizedStmt *S);
34};
35} // end anonymous namespace
36
Argyrios Kyrtzidis695fb502011-02-17 21:39:17 +000037static void RegisterObjCAtSyncChecker(ExprEngine &Eng) {
Ted Kremenek67e40d42010-11-08 16:52:54 +000038 // @synchronized is an Objective-C 2 feature.
39 if (Eng.getContext().getLangOptions().ObjC2)
40 Eng.registerCheck(new ObjCAtSyncChecker());
Ted Kremenek942e24d2010-09-10 03:45:29 +000041}
42
Argyrios Kyrtzidis695fb502011-02-17 21:39:17 +000043void ento::registerObjCAtSyncChecker(CheckerManager &mgr) {
44 mgr.addCheckerRegisterFunction(RegisterObjCAtSyncChecker);
45}
46
Ted Kremenek942e24d2010-09-10 03:45:29 +000047void ObjCAtSyncChecker::PreVisitObjCAtSynchronizedStmt(CheckerContext &C,
48 const ObjCAtSynchronizedStmt *S) {
49
50 const Expr *Ex = S->getSynchExpr();
51 const GRState *state = C.getState();
52 SVal V = state->getSVal(Ex);
53
54 // Uninitialized value used for the mutex?
55 if (isa<UndefinedVal>(V)) {
Ted Kremenekd048c6e2010-12-20 21:19:09 +000056 if (ExplodedNode *N = C.generateSink()) {
Ted Kremenek942e24d2010-09-10 03:45:29 +000057 if (!BT_undef)
58 BT_undef = new BuiltinBug("Uninitialized value used as mutex "
59 "for @synchronized");
60 EnhancedBugReport *report =
61 new EnhancedBugReport(*BT_undef, BT_undef->getDescription(), N);
62 report->addVisitorCreator(bugreporter::registerTrackNullOrUndefValue, Ex);
63 C.EmitReport(report);
64 }
65 return;
66 }
67
Ted Kremenek0d4f7672010-10-25 20:20:56 +000068 if (V.isUnknown())
69 return;
70
Ted Kremenek942e24d2010-09-10 03:45:29 +000071 // Check for null mutexes.
72 const GRState *notNullState, *nullState;
Ted Kremenek28f47b92010-12-01 22:16:56 +000073 llvm::tie(notNullState, nullState) = state->assume(cast<DefinedSVal>(V));
Ted Kremenek942e24d2010-09-10 03:45:29 +000074
75 if (nullState) {
76 if (!notNullState) {
77 // Generate an error node. This isn't a sink since
78 // a null mutex just means no synchronization occurs.
Ted Kremenekd048c6e2010-12-20 21:19:09 +000079 if (ExplodedNode *N = C.generateNode(nullState)) {
Ted Kremenek942e24d2010-09-10 03:45:29 +000080 if (!BT_null)
81 BT_null = new BuiltinBug("Nil value used as mutex for @synchronized() "
82 "(no synchronization will occur)");
83 EnhancedBugReport *report =
84 new EnhancedBugReport(*BT_null, BT_null->getDescription(), N);
85 report->addVisitorCreator(bugreporter::registerTrackNullOrUndefValue,
86 Ex);
87
88 C.EmitReport(report);
Ted Kremenek1adee4b2010-10-21 15:38:55 +000089 return;
Ted Kremenek942e24d2010-09-10 03:45:29 +000090 }
91 }
Ted Kremenek1adee4b2010-10-21 15:38:55 +000092 // Don't add a transition for 'nullState'. If the value is
93 // under-constrained to be null or non-null, assume it is non-null
94 // afterwards.
Ted Kremenek942e24d2010-09-10 03:45:29 +000095 }
96
97 if (notNullState)
98 C.addTransition(notNullState);
99}
Ted Kremenek1adee4b2010-10-21 15:38:55 +0000100