blob: 30775d57ce015f23268a24b4deda11fe61befa13 [file] [log] [blame]
Ted Kremenekb107c4b2009-11-04 04:24:16 +00001//===--- UndefinedAssignmentChecker.h ---------------------------*- 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//
Argyrios Kyrtzidis267aa5c2011-02-28 01:27:37 +000010// This defines UndefinedAssignmentChecker, a builtin check in ExprEngine that
Ted Kremenekb107c4b2009-11-04 04:24:16 +000011// checks for assigning undefined values.
12//
13//===----------------------------------------------------------------------===//
14
Argyrios Kyrtzidis267aa5c2011-02-28 01:27:37 +000015#include "ClangSACheckers.h"
Chandler Carruth55fc8732012-12-04 09:13:33 +000016#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
Argyrios Kyrtzidisec8605f2011-03-01 01:16:21 +000017#include "clang/StaticAnalyzer/Core/Checker.h"
Argyrios Kyrtzidis267aa5c2011-02-28 01:27:37 +000018#include "clang/StaticAnalyzer/Core/CheckerManager.h"
19#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
Ted Kremenekb107c4b2009-11-04 04:24:16 +000020
21using namespace clang;
Ted Kremenek9ef65372010-12-23 07:20:52 +000022using namespace ento;
Ted Kremenekb107c4b2009-11-04 04:24:16 +000023
Zhongxing Xuc3372e02009-11-22 12:29:52 +000024namespace {
Kovarththanan Rajaratnamba5fb5a2009-11-28 06:07:30 +000025class UndefinedAssignmentChecker
Argyrios Kyrtzidisec8605f2011-03-01 01:16:21 +000026 : public Checker<check::Bind> {
Stephen Hines651f13c2014-04-23 16:59:28 -070027 mutable std::unique_ptr<BugType> BT;
Argyrios Kyrtzidis267aa5c2011-02-28 01:27:37 +000028
Zhongxing Xuc3372e02009-11-22 12:29:52 +000029public:
Anna Zaks390909c2011-10-06 00:43:15 +000030 void checkBind(SVal location, SVal val, const Stmt *S,
31 CheckerContext &C) const;
Zhongxing Xuc3372e02009-11-22 12:29:52 +000032};
33}
34
Argyrios Kyrtzidis267aa5c2011-02-28 01:27:37 +000035void UndefinedAssignmentChecker::checkBind(SVal location, SVal val,
Anna Zaks390909c2011-10-06 00:43:15 +000036 const Stmt *StoreE,
Argyrios Kyrtzidis267aa5c2011-02-28 01:27:37 +000037 CheckerContext &C) const {
Ted Kremenekb107c4b2009-11-04 04:24:16 +000038 if (!val.isUndef())
39 return;
40
Anna Zaks52810c52013-06-18 23:16:15 +000041 // Do not report assignments of uninitialized values inside swap functions.
42 // This should allow to swap partially uninitialized structs
43 // (radar://14129997)
44 if (const FunctionDecl *EnclosingFunctionDecl =
45 dyn_cast<FunctionDecl>(C.getStackFrame()->getDecl()))
46 if (C.getCalleeName(EnclosingFunctionDecl) == "swap")
47 return;
48
Ted Kremenekd048c6e2010-12-20 21:19:09 +000049 ExplodedNode *N = C.generateSink();
Ted Kremenekb107c4b2009-11-04 04:24:16 +000050
51 if (!N)
52 return;
53
Ted Kremenek12182a02010-03-22 22:16:26 +000054 const char *str = "Assigned value is garbage or undefined";
55
Ted Kremenekb107c4b2009-11-04 04:24:16 +000056 if (!BT)
Stephen Hines651f13c2014-04-23 16:59:28 -070057 BT.reset(new BuiltinBug(this, str));
Ted Kremenekb107c4b2009-11-04 04:24:16 +000058
59 // Generate a report for this bug.
Ted Kremenek12182a02010-03-22 22:16:26 +000060 const Expr *ex = 0;
Ted Kremenekb107c4b2009-11-04 04:24:16 +000061
Ted Kremenek79d73042010-09-02 00:56:20 +000062 while (StoreE) {
63 if (const BinaryOperator *B = dyn_cast<BinaryOperator>(StoreE)) {
Ted Kremenek12182a02010-03-22 22:16:26 +000064 if (B->isCompoundAssignmentOp()) {
Ted Kremenek8bef8232012-01-26 21:29:00 +000065 ProgramStateRef state = C.getState();
Ted Kremenek5eca4822012-01-06 22:09:28 +000066 if (state->getSVal(B->getLHS(), C.getLocationContext()).isUndef()) {
Ted Kremenek12182a02010-03-22 22:16:26 +000067 str = "The left expression of the compound assignment is an "
68 "uninitialized value. The computed value will also be garbage";
69 ex = B->getLHS();
70 break;
71 }
72 }
Ted Kremenekb107c4b2009-11-04 04:24:16 +000073
Ted Kremenek50ecd152009-11-05 00:42:23 +000074 ex = B->getRHS();
Ted Kremenek12182a02010-03-22 22:16:26 +000075 break;
76 }
77
Ted Kremenek79d73042010-09-02 00:56:20 +000078 if (const DeclStmt *DS = dyn_cast<DeclStmt>(StoreE)) {
Ted Kremenek9c378f72011-08-12 23:37:29 +000079 const VarDecl *VD = dyn_cast<VarDecl>(DS->getSingleDecl());
Ted Kremenek50ecd152009-11-05 00:42:23 +000080 ex = VD->getInit();
81 }
Ted Kremenek12182a02010-03-22 22:16:26 +000082
83 break;
Ted Kremenekb107c4b2009-11-04 04:24:16 +000084 }
85
Anna Zakse172e8b2011-08-17 23:00:25 +000086 BugReport *R = new BugReport(*BT, str, N);
Ted Kremenek12182a02010-03-22 22:16:26 +000087 if (ex) {
88 R->addRange(ex->getSourceRange());
Jordan Rosea1f81bb2012-08-28 00:50:51 +000089 bugreporter::trackNullOrUndefValue(N, ex, *R);
Ted Kremenek12182a02010-03-22 22:16:26 +000090 }
Jordan Rose785950e2012-11-02 01:53:40 +000091 C.emitReport(R);
Ted Kremenek12182a02010-03-22 22:16:26 +000092}
Ted Kremenekb107c4b2009-11-04 04:24:16 +000093
Argyrios Kyrtzidis267aa5c2011-02-28 01:27:37 +000094void ento::registerUndefinedAssignmentChecker(CheckerManager &mgr) {
95 mgr.registerChecker<UndefinedAssignmentChecker>();
96}