• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //=== UndefResultChecker.cpp ------------------------------------*- 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 UndefResultChecker, a builtin check in ExprEngine that
11 // performs checks for undefined results of non-assignment binary operators.
12 //
13 //===----------------------------------------------------------------------===//
14 
15 #include "ClangSACheckers.h"
16 #include "clang/StaticAnalyzer/Core/Checker.h"
17 #include "clang/StaticAnalyzer/Core/CheckerManager.h"
18 #include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
19 #include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
20 #include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h"
21 
22 using namespace clang;
23 using namespace ento;
24 
25 namespace {
26 class UndefResultChecker
27   : public Checker< check::PostStmt<BinaryOperator> > {
28 
29   mutable llvm::OwningPtr<BugType> BT;
30 
31 public:
32   void checkPostStmt(const BinaryOperator *B, CheckerContext &C) const;
33 };
34 } // end anonymous namespace
35 
checkPostStmt(const BinaryOperator * B,CheckerContext & C) const36 void UndefResultChecker::checkPostStmt(const BinaryOperator *B,
37                                        CheckerContext &C) const {
38   const GRState *state = C.getState();
39   if (state->getSVal(B).isUndef()) {
40     // Generate an error node.
41     ExplodedNode *N = C.generateSink();
42     if (!N)
43       return;
44 
45     if (!BT)
46       BT.reset(new BuiltinBug("Result of operation is garbage or undefined"));
47 
48     llvm::SmallString<256> sbuf;
49     llvm::raw_svector_ostream OS(sbuf);
50     const Expr *Ex = NULL;
51     bool isLeft = true;
52 
53     if (state->getSVal(B->getLHS()).isUndef()) {
54       Ex = B->getLHS()->IgnoreParenCasts();
55       isLeft = true;
56     }
57     else if (state->getSVal(B->getRHS()).isUndef()) {
58       Ex = B->getRHS()->IgnoreParenCasts();
59       isLeft = false;
60     }
61 
62     if (Ex) {
63       OS << "The " << (isLeft ? "left" : "right")
64          << " operand of '"
65          << BinaryOperator::getOpcodeStr(B->getOpcode())
66          << "' is a garbage value";
67     }
68     else {
69       // Neither operand was undefined, but the result is undefined.
70       OS << "The result of the '"
71          << BinaryOperator::getOpcodeStr(B->getOpcode())
72          << "' expression is undefined";
73     }
74     EnhancedBugReport *report = new EnhancedBugReport(*BT, OS.str(), N);
75     if (Ex) {
76       report->addRange(Ex->getSourceRange());
77       report->addVisitorCreator(bugreporter::registerTrackNullOrUndefValue, Ex);
78     }
79     else
80       report->addVisitorCreator(bugreporter::registerTrackNullOrUndefValue, B);
81     C.EmitReport(report);
82   }
83 }
84 
registerUndefResultChecker(CheckerManager & mgr)85 void ento::registerUndefResultChecker(CheckerManager &mgr) {
86   mgr.registerChecker<UndefResultChecker>();
87 }
88