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)