UndefinedAssignmentChecker.cpp revision ec8605f1d7ec846dbf51047bfd5c56d32d1ff91c
1868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)//===--- UndefinedAssignmentChecker.h ---------------------------*- C++ -*--==// 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// The LLVM Compiler Infrastructure 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 58bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)// This file is distributed under the University of Illinois Open Source 68bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)// License. See LICENSE.TXT for details. 75d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// 88bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)//===----------------------------------------------------------------------===// 95d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// 100f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)// This defines UndefinedAssignmentChecker, a builtin check in ExprEngine that 115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// checks for assigning undefined values. 12010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)// 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//===----------------------------------------------------------------------===// 1490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 1590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "ClangSACheckers.h" 1690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "clang/StaticAnalyzer/Core/Checker.h" 1790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "clang/StaticAnalyzer/Core/CheckerManager.h" 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h" 192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h" 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)using namespace clang; 225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)using namespace ento; 235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)namespace { 255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)class UndefinedAssignmentChecker 265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) : public Checker<check::Bind> { 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) mutable llvm::OwningPtr<BugType> BT; 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)public: 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void checkBind(SVal location, SVal val, CheckerContext &C) const; 312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}; 322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void UndefinedAssignmentChecker::checkBind(SVal location, SVal val, 352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) CheckerContext &C) const { 362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!val.isUndef()) 372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return; 382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ExplodedNode *N = C.generateSink(); 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!N) 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const char *str = "Assigned value is garbage or undefined"; 452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!BT) 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BT.reset(new BuiltinBug(str)); 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Generate a report for this bug. 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const Expr *ex = 0; 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const Stmt *StoreE = C.getStmt(); 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) while (StoreE) { 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (const BinaryOperator *B = dyn_cast<BinaryOperator>(StoreE)) { 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (B->isCompoundAssignmentOp()) { 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const GRState *state = C.getState(); 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (state->getSVal(B->getLHS()).isUndef()) { 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) str = "The left expression of the compound assignment is an " 592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) "uninitialized value. The computed value will also be garbage"; 601e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) ex = B->getLHS(); 612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) break; 622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ex = B->getRHS(); 662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) break; 672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (const DeclStmt *DS = dyn_cast<DeclStmt>(StoreE)) { 702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const VarDecl* VD = dyn_cast<VarDecl>(DS->getSingleDecl()); 712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ex = VD->getInit(); 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EnhancedBugReport *R = new EnhancedBugReport(*BT, str, N); 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (ex) { 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) R->addRange(ex->getSourceRange()); 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) R->addVisitorCreator(bugreporter::registerTrackNullOrUndefValue, ex); 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) C.EmitReport(R); 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ento::registerUndefinedAssignmentChecker(CheckerManager &mgr) { 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) mgr.registerChecker<UndefinedAssignmentChecker>(); 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)