xref: /llvm-project/clang/lib/StaticAnalyzer/Checkers/UndefinedAssignmentChecker.cpp (revision d99bd55a5e092774214ba31fc5a871bfc31e711c)
1 //===--- 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 //
10 // This defines UndefinedAssginmentChecker, a builtin check in ExprEngine that
11 // checks for assigning undefined values.
12 //
13 //===----------------------------------------------------------------------===//
14 
15 #include "ExprEngineInternalChecks.h"
16 #include "clang/StaticAnalyzer/BugReporter/BugType.h"
17 #include "clang/StaticAnalyzer/PathSensitive/CheckerVisitor.h"
18 
19 using namespace clang;
20 using namespace ento;
21 
22 namespace {
23 class UndefinedAssignmentChecker
24   : public CheckerVisitor<UndefinedAssignmentChecker> {
25   BugType *BT;
26 public:
27   UndefinedAssignmentChecker() : BT(0) {}
28   static void *getTag();
29   virtual void PreVisitBind(CheckerContext &C, const Stmt *StoreE,
30                             SVal location, SVal val);
31 };
32 }
33 
34 void ento::RegisterUndefinedAssignmentChecker(ExprEngine &Eng){
35   Eng.registerCheck(new UndefinedAssignmentChecker());
36 }
37 
38 void *UndefinedAssignmentChecker::getTag() {
39   static int x = 0;
40   return &x;
41 }
42 
43 void UndefinedAssignmentChecker::PreVisitBind(CheckerContext &C,
44                                               const Stmt *StoreE,
45                                               SVal location,
46                                               SVal val) {
47   if (!val.isUndef())
48     return;
49 
50   ExplodedNode *N = C.generateSink();
51 
52   if (!N)
53     return;
54 
55   const char *str = "Assigned value is garbage or undefined";
56 
57   if (!BT)
58     BT = new BuiltinBug(str);
59 
60   // Generate a report for this bug.
61   const Expr *ex = 0;
62 
63   while (StoreE) {
64     if (const BinaryOperator *B = dyn_cast<BinaryOperator>(StoreE)) {
65       if (B->isCompoundAssignmentOp()) {
66         const GRState *state = C.getState();
67         if (state->getSVal(B->getLHS()).isUndef()) {
68           str = "The left expression of the compound assignment is an "
69                 "uninitialized value. The computed value will also be garbage";
70           ex = B->getLHS();
71           break;
72         }
73       }
74 
75       ex = B->getRHS();
76       break;
77     }
78 
79     if (const DeclStmt *DS = dyn_cast<DeclStmt>(StoreE)) {
80       const VarDecl* VD = dyn_cast<VarDecl>(DS->getSingleDecl());
81       ex = VD->getInit();
82     }
83 
84     break;
85   }
86 
87   EnhancedBugReport *R = new EnhancedBugReport(*BT, str, N);
88   if (ex) {
89     R->addRange(ex->getSourceRange());
90     R->addVisitorCreator(bugreporter::registerTrackNullOrUndefValue, ex);
91   }
92   C.EmitReport(R);
93 }
94 
95