blob: 52b4ca7d7704ade716e2e063fff9438d3d7447ca [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) {
Roman Lebedev88b56ca2017-11-30 09:18:35 +000063 if (const UnaryOperator *U = dyn_cast<UnaryOperator>(StoreE)) {
64 str = "The expression is an uninitialized value. "
65 "The computed value will also be garbage";
66
67 ex = U->getSubExpr();
68 break;
69 }
70
Ted Kremenek07343c02010-09-02 00:56:20 +000071 if (const BinaryOperator *B = dyn_cast<BinaryOperator>(StoreE)) {
Ted Kremenek28ec56d2010-03-22 22:16:26 +000072 if (B->isCompoundAssignmentOp()) {
George Karpenkovd703ec92018-01-17 20:27:29 +000073 if (C.getSVal(B->getLHS()).isUndef()) {
Ted Kremenek28ec56d2010-03-22 22:16:26 +000074 str = "The left expression of the compound assignment is an "
75 "uninitialized value. The computed value will also be garbage";
76 ex = B->getLHS();
77 break;
78 }
79 }
Ted Kremenekef910042009-11-04 04:24:16 +000080
Ted Kremenek209e31b2009-11-05 00:42:23 +000081 ex = B->getRHS();
Ted Kremenek28ec56d2010-03-22 22:16:26 +000082 break;
83 }
84
Ted Kremenek07343c02010-09-02 00:56:20 +000085 if (const DeclStmt *DS = dyn_cast<DeclStmt>(StoreE)) {
Ted Kremenek5ef32db2011-08-12 23:37:29 +000086 const VarDecl *VD = dyn_cast<VarDecl>(DS->getSingleDecl());
Ted Kremenek209e31b2009-11-05 00:42:23 +000087 ex = VD->getInit();
88 }
Ted Kremenek28ec56d2010-03-22 22:16:26 +000089
90 break;
Ted Kremenekef910042009-11-04 04:24:16 +000091 }
92
Aaron Ballman8d3a7a52015-06-23 13:15:32 +000093 auto R = llvm::make_unique<BugReport>(*BT, str, N);
Ted Kremenek28ec56d2010-03-22 22:16:26 +000094 if (ex) {
95 R->addRange(ex->getSourceRange());
Jordan Rosea0f7d352012-08-28 00:50:51 +000096 bugreporter::trackNullOrUndefValue(N, ex, *R);
Ted Kremenek28ec56d2010-03-22 22:16:26 +000097 }
Aaron Ballman8d3a7a52015-06-23 13:15:32 +000098 C.emitReport(std::move(R));
Ted Kremenek28ec56d2010-03-22 22:16:26 +000099}
Ted Kremenekef910042009-11-04 04:24:16 +0000100
Argyrios Kyrtzidis098874a2011-02-28 01:27:37 +0000101void ento::registerUndefinedAssignmentChecker(CheckerManager &mgr) {
102 mgr.registerChecker<UndefinedAssignmentChecker>();
103}