UndefinedAssignmentChecker.cpp revision 243830
1169695Skan//===--- UndefinedAssignmentChecker.h ---------------------------*- C++ -*--==// 2169695Skan// 3169695Skan// The LLVM Compiler Infrastructure 4169695Skan// 5169695Skan// This file is distributed under the University of Illinois Open Source 6169695Skan// License. See LICENSE.TXT for details. 7169695Skan// 8169695Skan//===----------------------------------------------------------------------===// 9169695Skan// 10169695Skan// This defines UndefinedAssignmentChecker, a builtin check in ExprEngine that 11169695Skan// checks for assigning undefined values. 12169695Skan// 13169695Skan//===----------------------------------------------------------------------===// 14169695Skan 15169695Skan#include "ClangSACheckers.h" 16169695Skan#include "clang/StaticAnalyzer/Core/Checker.h" 17169695Skan#include "clang/StaticAnalyzer/Core/CheckerManager.h" 18169695Skan#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h" 19169695Skan#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h" 20169695Skan 21169695Skanusing namespace clang; 22169695Skanusing namespace ento; 23169695Skan 24169695Skannamespace { 25169695Skanclass UndefinedAssignmentChecker 26169695Skan : public Checker<check::Bind> { 27169695Skan mutable OwningPtr<BugType> BT; 28169695Skan 29169695Skanpublic: 30169695Skan void checkBind(SVal location, SVal val, const Stmt *S, 31169695Skan CheckerContext &C) const; 32169695Skan}; 33169695Skan} 34169695Skan 35169695Skanvoid UndefinedAssignmentChecker::checkBind(SVal location, SVal val, 36169695Skan const Stmt *StoreE, 37169695Skan CheckerContext &C) const { 38169695Skan if (!val.isUndef()) 39169695Skan return; 40169695Skan 41169695Skan ExplodedNode *N = C.generateSink(); 42169695Skan 43169695Skan if (!N) 44169695Skan return; 45169695Skan 46169695Skan const char *str = "Assigned value is garbage or undefined"; 47169695Skan 48169695Skan if (!BT) 49169695Skan BT.reset(new BuiltinBug(str)); 50169695Skan 51169695Skan // Generate a report for this bug. 52169695Skan const Expr *ex = 0; 53169695Skan 54169695Skan while (StoreE) { 55169695Skan if (const BinaryOperator *B = dyn_cast<BinaryOperator>(StoreE)) { 56169695Skan if (B->isCompoundAssignmentOp()) { 57169695Skan ProgramStateRef state = C.getState(); 58169695Skan if (state->getSVal(B->getLHS(), C.getLocationContext()).isUndef()) { 59169695Skan str = "The left expression of the compound assignment is an " 60169695Skan "uninitialized value. The computed value will also be garbage"; 61169695Skan ex = B->getLHS(); 62169695Skan break; 63169695Skan } 64169695Skan } 65169695Skan 66169695Skan ex = B->getRHS(); 67169695Skan break; 68169695Skan } 69169695Skan 70169695Skan if (const DeclStmt *DS = dyn_cast<DeclStmt>(StoreE)) { 71169695Skan const VarDecl *VD = dyn_cast<VarDecl>(DS->getSingleDecl()); 72169695Skan ex = VD->getInit(); 73169695Skan } 74169695Skan 75169695Skan break; 76169695Skan } 77169695Skan 78169695Skan BugReport *R = new BugReport(*BT, str, N); 79169695Skan if (ex) { 80169695Skan R->addRange(ex->getSourceRange()); 81169695Skan bugreporter::trackNullOrUndefValue(N, ex, *R); 82169695Skan } 83169695Skan C.emitReport(R); 84169695Skan} 85169695Skan 86169695Skanvoid ento::registerUndefinedAssignmentChecker(CheckerManager &mgr) { 87169695Skan mgr.registerChecker<UndefinedAssignmentChecker>(); 88169695Skan} 89169695Skan