blob: 7a31efc8cef88580c0563b556fc8b17e3f23940a [file] [log] [blame]
Ted Kremenekef910042009-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 Kyrtzidis098874a2011-02-28 01:27:37 +000010// This defines UndefinedAssignmentChecker, a builtin check in ExprEngine that
Ted Kremenekef910042009-11-04 04:24:16 +000011// checks for assigning undefined values.
12//
13//===----------------------------------------------------------------------===//
14
Argyrios Kyrtzidis098874a2011-02-28 01:27:37 +000015#include "ClangSACheckers.h"
Chandler Carruth3a022472012-12-04 09:13:33 +000016#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
Argyrios Kyrtzidis6a5674f2011-03-01 01:16:21 +000017#include "clang/StaticAnalyzer/Core/Checker.h"
Argyrios Kyrtzidis098874a2011-02-28 01:27:37 +000018#include "clang/StaticAnalyzer/Core/CheckerManager.h"
19#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
Ted Kremenekef910042009-11-04 04:24:16 +000020
21using namespace clang;
Ted Kremenek98857c92010-12-23 07:20:52 +000022using namespace ento;
Ted Kremenekef910042009-11-04 04:24:16 +000023
Zhongxing Xuf0b7fc82009-11-22 12:29:52 +000024namespace {
Kovarththanan Rajaratnam65c65662009-11-28 06:07:30 +000025class UndefinedAssignmentChecker
Argyrios Kyrtzidis6a5674f2011-03-01 01:16:21 +000026 : public Checker<check::Bind> {
Ahmed Charlesb8984322014-03-07 20:03:18 +000027 mutable std::unique_ptr<BugType> BT;
Argyrios Kyrtzidis098874a2011-02-28 01:27:37 +000028
Zhongxing Xuf0b7fc82009-11-22 12:29:52 +000029public:
Anna Zaks3e0f4152011-10-06 00:43:15 +000030 void checkBind(SVal location, SVal val, const Stmt *S,
31 CheckerContext &C) const;
Zhongxing Xuf0b7fc82009-11-22 12:29:52 +000032};
33}
34
Argyrios Kyrtzidis098874a2011-02-28 01:27:37 +000035void UndefinedAssignmentChecker::checkBind(SVal location, SVal val,
Anna Zaks3e0f4152011-10-06 00:43:15 +000036 const Stmt *StoreE,
Argyrios Kyrtzidis098874a2011-02-28 01:27:37 +000037 CheckerContext &C) const {
Ted Kremenekef910042009-11-04 04:24:16 +000038 if (!val.isUndef())
39 return;
40
Anna Zaks03256462013-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
Devin Coughline39bd402015-09-16 22:03:05 +000049 ExplodedNode *N = C.generateErrorNode();
Ted Kremenekef910042009-11-04 04:24:16 +000050
51 if (!N)
52 return;
53
Ted Kremenek28ec56d2010-03-22 22:16:26 +000054 const char *str = "Assigned value is garbage or undefined";
55
Ted Kremenekef910042009-11-04 04:24:16 +000056 if (!BT)
Alexander Kornienko4aca9b12014-02-11 21:49:21 +000057 BT.reset(new BuiltinBug(this, str));
Ted Kremenekef910042009-11-04 04:24:16 +000058
59 // Generate a report for this bug.
Craig Topper0dbb7832014-05-27 02:45:47 +000060 const Expr *ex = nullptr;
Ted Kremenekef910042009-11-04 04:24:16 +000061
Ted Kremenek07343c02010-09-02 00:56:20 +000062 while (StoreE) {
63 if (const BinaryOperator *B = dyn_cast<BinaryOperator>(StoreE)) {
Ted Kremenek28ec56d2010-03-22 22:16:26 +000064 if (B->isCompoundAssignmentOp()) {
Ted Kremenek49b1e382012-01-26 21:29:00 +000065 ProgramStateRef state = C.getState();
Ted Kremenek632e3b72012-01-06 22:09:28 +000066 if (state->getSVal(B->getLHS(), C.getLocationContext()).isUndef()) {
Ted Kremenek28ec56d2010-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 Kremenekef910042009-11-04 04:24:16 +000073
Ted Kremenek209e31b2009-11-05 00:42:23 +000074 ex = B->getRHS();
Ted Kremenek28ec56d2010-03-22 22:16:26 +000075 break;
76 }
77
Ted Kremenek07343c02010-09-02 00:56:20 +000078 if (const DeclStmt *DS = dyn_cast<DeclStmt>(StoreE)) {
Ted Kremenek5ef32db2011-08-12 23:37:29 +000079 const VarDecl *VD = dyn_cast<VarDecl>(DS->getSingleDecl());
Ted Kremenek209e31b2009-11-05 00:42:23 +000080 ex = VD->getInit();
81 }
Ted Kremenek28ec56d2010-03-22 22:16:26 +000082
83 break;
Ted Kremenekef910042009-11-04 04:24:16 +000084 }
85
Aaron Ballman8d3a7a52015-06-23 13:15:32 +000086 auto R = llvm::make_unique<BugReport>(*BT, str, N);
Ted Kremenek28ec56d2010-03-22 22:16:26 +000087 if (ex) {
88 R->addRange(ex->getSourceRange());
Jordan Rosea0f7d352012-08-28 00:50:51 +000089 bugreporter::trackNullOrUndefValue(N, ex, *R);
Ted Kremenek28ec56d2010-03-22 22:16:26 +000090 }
Aaron Ballman8d3a7a52015-06-23 13:15:32 +000091 C.emitReport(std::move(R));
Ted Kremenek28ec56d2010-03-22 22:16:26 +000092}
Ted Kremenekef910042009-11-04 04:24:16 +000093
Argyrios Kyrtzidis098874a2011-02-28 01:27:37 +000094void ento::registerUndefinedAssignmentChecker(CheckerManager &mgr) {
95 mgr.registerChecker<UndefinedAssignmentChecker>();
96}