UndefResultChecker.cpp revision 04291a7c76e16a2dc5433c80c3d13c826bf372dc
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 "InternalChecks.h" 16#include "clang/StaticAnalyzer/BugReporter/BugType.h" 17#include "clang/StaticAnalyzer/PathSensitive/CheckerVisitor.h" 18#include "clang/StaticAnalyzer/PathSensitive/ExprEngine.h" 19 20using namespace clang; 21using namespace ento; 22 23namespace { 24class UndefResultChecker 25 : public CheckerVisitor<UndefResultChecker> { 26 27 BugType *BT; 28 29public: 30 UndefResultChecker() : BT(0) {} 31 static void *getTag() { static int tag = 0; return &tag; } 32 void PostVisitBinaryOperator(CheckerContext &C, const BinaryOperator *B); 33}; 34} // end anonymous namespace 35 36void ento::RegisterUndefResultChecker(ExprEngine &Eng) { 37 Eng.registerCheck(new UndefResultChecker()); 38} 39 40void UndefResultChecker::PostVisitBinaryOperator(CheckerContext &C, 41 const BinaryOperator *B) { 42 const GRState *state = C.getState(); 43 if (state->getSVal(B).isUndef()) { 44 // Generate an error node. 45 ExplodedNode *N = C.generateSink(); 46 if (!N) 47 return; 48 49 if (!BT) 50 BT = new BuiltinBug("Result of operation is garbage or undefined"); 51 52 llvm::SmallString<256> sbuf; 53 llvm::raw_svector_ostream OS(sbuf); 54 const Expr *Ex = NULL; 55 bool isLeft = true; 56 57 if (state->getSVal(B->getLHS()).isUndef()) { 58 Ex = B->getLHS()->IgnoreParenCasts(); 59 isLeft = true; 60 } 61 else if (state->getSVal(B->getRHS()).isUndef()) { 62 Ex = B->getRHS()->IgnoreParenCasts(); 63 isLeft = false; 64 } 65 66 if (Ex) { 67 OS << "The " << (isLeft ? "left" : "right") 68 << " operand of '" 69 << BinaryOperator::getOpcodeStr(B->getOpcode()) 70 << "' is a garbage value"; 71 } 72 else { 73 // Neither operand was undefined, but the result is undefined. 74 OS << "The result of the '" 75 << BinaryOperator::getOpcodeStr(B->getOpcode()) 76 << "' expression is undefined"; 77 } 78 EnhancedBugReport *report = new EnhancedBugReport(*BT, OS.str(), N); 79 if (Ex) { 80 report->addRange(Ex->getSourceRange()); 81 report->addVisitorCreator(bugreporter::registerTrackNullOrUndefValue, Ex); 82 } 83 else 84 report->addVisitorCreator(bugreporter::registerTrackNullOrUndefValue, B); 85 C.EmitReport(report); 86 } 87} 88