DereferenceChecker.cpp revision 80de487e03dd0f44e4572e2122ebc1aa6a3961f5
13c827367444ee418f129b2c238299f49d3264554Jarkko Poyry//== NullDerefChecker.cpp - Null dereference checker ------------*- C++ -*--==//
23c827367444ee418f129b2c238299f49d3264554Jarkko Poyry//
33c827367444ee418f129b2c238299f49d3264554Jarkko Poyry//                     The LLVM Compiler Infrastructure
43c827367444ee418f129b2c238299f49d3264554Jarkko Poyry//
53c827367444ee418f129b2c238299f49d3264554Jarkko Poyry// This file is distributed under the University of Illinois Open Source
63c827367444ee418f129b2c238299f49d3264554Jarkko Poyry// License. See LICENSE.TXT for details.
73c827367444ee418f129b2c238299f49d3264554Jarkko Poyry//
83c827367444ee418f129b2c238299f49d3264554Jarkko Poyry//===----------------------------------------------------------------------===//
93c827367444ee418f129b2c238299f49d3264554Jarkko Poyry//
103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry// This defines NullDerefChecker, a builtin check in ExprEngine that performs
113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry// checks for null pointers at loads and stores.
123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry//
133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry//===----------------------------------------------------------------------===//
143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "ClangSACheckers.h"
163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "clang/AST/ExprObjC.h"
173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "clang/StaticAnalyzer/Core/Checker.h"
183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "clang/StaticAnalyzer/Core/CheckerManager.h"
193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "llvm/ADT/SmallString.h"
223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
233c827367444ee418f129b2c238299f49d3264554Jarkko Poyryusing namespace clang;
243c827367444ee418f129b2c238299f49d3264554Jarkko Poyryusing namespace ento;
253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
263c827367444ee418f129b2c238299f49d3264554Jarkko Poyrynamespace {
273c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass DereferenceChecker
283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry    : public Checker< check::Location,
293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry                      check::Bind,
303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry                      EventDispatcher<ImplicitNullDerefEvent> > {
313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  mutable OwningPtr<BuiltinBug> BT_null;
323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  mutable OwningPtr<BuiltinBug> BT_undef;
333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  void reportBug(ProgramStateRef State, const Stmt *S, CheckerContext &C,
353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry                 bool IsBind = false) const;
363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
373c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic:
383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  void checkLocation(SVal location, bool isLoad, const Stmt* S,
393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry                     CheckerContext &C) const;
403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  void checkBind(SVal L, SVal V, const Stmt *S, CheckerContext &C) const;
413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  static const MemRegion *AddDerefSource(raw_ostream &os,
433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry                             SmallVectorImpl<SourceRange> &Ranges,
443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry                             const Expr *Ex, const ProgramState *state,
453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry                             const LocationContext *LCtx,
463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry                             bool loadedFrom = false);
473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} // end anonymous namespace
493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
503c827367444ee418f129b2c238299f49d3264554Jarkko Poyryconst MemRegion *
513c827367444ee418f129b2c238299f49d3264554Jarkko PoyryDereferenceChecker::AddDerefSource(raw_ostream &os,
523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry                                   SmallVectorImpl<SourceRange> &Ranges,
533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry                                   const Expr *Ex,
543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry                                   const ProgramState *state,
553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry                                   const LocationContext *LCtx,
563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry                                   bool loadedFrom) {
573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  Ex = Ex->IgnoreParenLValueCasts();
583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  const MemRegion *sourceR = 0;
593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  switch (Ex->getStmtClass()) {
603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry    default:
613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry      break;
623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry    case Stmt::DeclRefExprClass: {
633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry      const DeclRefExpr *DR = cast<DeclRefExpr>(Ex);
643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry      if (const VarDecl *VD = dyn_cast<VarDecl>(DR->getDecl())) {
653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry        os << " (" << (loadedFrom ? "loaded from" : "from")
663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry           << " variable '" <<  VD->getName() << "')";
673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry        Ranges.push_back(DR->getSourceRange());
683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry        sourceR = state->getLValue(VD, LCtx).getAsRegion();
693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry      }
703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry      break;
713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry    }
723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry    case Stmt::MemberExprClass: {
733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry      const MemberExpr *ME = cast<MemberExpr>(Ex);
743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry      os << " (" << (loadedFrom ? "loaded from" : "via")
753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry         << " field '" << ME->getMemberNameInfo() << "')";
763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry      SourceLocation L = ME->getMemberLoc();
773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry      Ranges.push_back(SourceRange(L, L));
783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry      break;
793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry    }
803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  }
813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  return sourceR;
823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
843c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid DereferenceChecker::reportBug(ProgramStateRef State, const Stmt *S,
853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry                                   CheckerContext &C, bool IsBind) const {
863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  // Generate an error node.
873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  ExplodedNode *N = C.generateSink(State);
883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  if (!N)
893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry    return;
903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  // We know that 'location' cannot be non-null.  This is what
923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  // we call an "explicit" null dereference.
933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  if (!BT_null)
943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry    BT_null.reset(new BuiltinBug("Dereference of null pointer"));
953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  SmallString<100> buf;
973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  SmallVector<SourceRange, 2> Ranges;
983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  // Walk through lvalue casts to get the original expression
1003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  // that syntactically caused the load.
1013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  if (const Expr *expr = dyn_cast<Expr>(S))
1023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry    S = expr->IgnoreParenLValueCasts();
1033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  const MemRegion *sourceR = 0;
1053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  if (IsBind) {
1073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry    if (const BinaryOperator *BO = dyn_cast<BinaryOperator>(S)) {
1083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry      if (BO->isAssignmentOp())
1093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry        S = BO->getRHS();
1103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry    } else if (const DeclStmt *DS = dyn_cast<DeclStmt>(S)) {
1113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry      assert(DS->isSingleDecl() && "We process decls one by one");
1123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry      if (const VarDecl *VD = dyn_cast<VarDecl>(DS->getSingleDecl()))
1133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry        if (const Expr *Init = VD->getAnyInitializer())
1143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry          S = Init;
1153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry    }
1163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  }
1173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  switch (S->getStmtClass()) {
1193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  case Stmt::ArraySubscriptExprClass: {
1203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry    llvm::raw_svector_ostream os(buf);
1213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry    os << "Array access";
1223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry    const ArraySubscriptExpr *AE = cast<ArraySubscriptExpr>(S);
1233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry    sourceR = AddDerefSource(os, Ranges, AE->getBase()->IgnoreParenCasts(),
1243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry                             State.getPtr(), N->getLocationContext());
1253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry    os << " results in a null pointer dereference";
1263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry    break;
1273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  }
1283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  case Stmt::UnaryOperatorClass: {
1293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry    llvm::raw_svector_ostream os(buf);
1303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry    os << "Dereference of null pointer";
1313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry    const UnaryOperator *U = cast<UnaryOperator>(S);
1323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry    sourceR = AddDerefSource(os, Ranges, U->getSubExpr()->IgnoreParens(),
1333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry                             State.getPtr(), N->getLocationContext(), true);
1343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry    break;
1353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  }
1363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  case Stmt::MemberExprClass: {
1373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry    const MemberExpr *M = cast<MemberExpr>(S);
1383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry    if (M->isArrow()) {
1393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry      llvm::raw_svector_ostream os(buf);
1403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry      os << "Access to field '" << M->getMemberNameInfo()
1413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry         << "' results in a dereference of a null pointer";
1423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry      sourceR = AddDerefSource(os, Ranges, M->getBase()->IgnoreParenCasts(),
1433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry                               State.getPtr(), N->getLocationContext(), true);
1443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry    }
1453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry    break;
1463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  }
1473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  case Stmt::ObjCIvarRefExprClass: {
1483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry    const ObjCIvarRefExpr *IV = cast<ObjCIvarRefExpr>(S);
1493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry    if (const DeclRefExpr *DR =
1503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry        dyn_cast<DeclRefExpr>(IV->getBase()->IgnoreParenCasts())) {
1513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry      if (const VarDecl *VD = dyn_cast<VarDecl>(DR->getDecl())) {
1523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry        llvm::raw_svector_ostream os(buf);
1533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry        os << "Instance variable access (via '" << VD->getName()
1543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry           << "') results in a null pointer dereference";
1553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry      }
1563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry    }
1573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry    Ranges.push_back(IV->getSourceRange());
1583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry    break;
1593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  }
1603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  default:
1613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry    break;
1623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  }
1633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  BugReport *report =
1653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry    new BugReport(*BT_null,
1663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry                  buf.empty() ? BT_null->getDescription() : buf.str(),
1673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry                  N);
1683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  bugreporter::trackNullOrUndefValue(N, bugreporter::GetDerefExpr(N), *report);
1703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  for (SmallVectorImpl<SourceRange>::iterator
1723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry       I = Ranges.begin(), E = Ranges.end(); I!=E; ++I)
1733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry    report->addRange(*I);
1743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  if (sourceR) {
1763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry    report->markInteresting(sourceR);
1773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry    report->markInteresting(State->getRawSVal(loc::MemRegionVal(sourceR)));
1783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  }
1793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  C.EmitReport(report);
1813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
1823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1833c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid DereferenceChecker::checkLocation(SVal l, bool isLoad, const Stmt* S,
1843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry                                       CheckerContext &C) const {
1853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  // Check for dereference of an undefined value.
1863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  if (l.isUndef()) {
1873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry    if (ExplodedNode *N = C.generateSink()) {
1883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry      if (!BT_undef)
1893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry        BT_undef.reset(new BuiltinBug("Dereference of undefined pointer value"));
1903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry      BugReport *report =
1923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry        new BugReport(*BT_undef, BT_undef->getDescription(), N);
1933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry      bugreporter::trackNullOrUndefValue(N, bugreporter::GetDerefExpr(N),
1943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry                                         *report);
1953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry      C.EmitReport(report);
1963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry    }
1973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry    return;
1983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  }
1993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  DefinedOrUnknownSVal location = cast<DefinedOrUnknownSVal>(l);
2013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  // Check for null dereferences.
2033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  if (!isa<Loc>(location))
2043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry    return;
2053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  ProgramStateRef state = C.getState();
2073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  ProgramStateRef notNullState, nullState;
2093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  llvm::tie(notNullState, nullState) = state->assume(location);
2103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  // The explicit NULL case.
2123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  if (nullState) {
2133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry    if (!notNullState) {
2143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry      reportBug(nullState, S, C);
2153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry      return;
2163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry    }
2173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry    // Otherwise, we have the case where the location could either be
2193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry    // null or not-null.  Record the error node as an "implicit" null
2203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry    // dereference.
2213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry    if (ExplodedNode *N = C.generateSink(nullState)) {
2223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry      ImplicitNullDerefEvent event = { l, isLoad, N, &C.getBugReporter() };
2233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry      dispatchEvent(event);
2243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry    }
2253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  }
2263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  // From this point forward, we know that the location is not null.
2283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  C.addTransition(notNullState);
2293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
2303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2313c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid DereferenceChecker::checkBind(SVal L, SVal V, const Stmt *S,
2323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry                                   CheckerContext &C) const {
2333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  // If we're binding to a reference, check if the value is known to be null.
2343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  if (V.isUndef())
2353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry    return;
2363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  const MemRegion *MR = L.getAsRegion();
2383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  const TypedValueRegion *TVR = dyn_cast_or_null<TypedValueRegion>(MR);
2393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  if (!TVR)
2403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry    return;
2413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  if (!TVR->getValueType()->isReferenceType())
2433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry    return;
2443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  ProgramStateRef State = C.getState();
2463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  ProgramStateRef StNonNull, StNull;
2483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  llvm::tie(StNonNull, StNull) = State->assume(cast<DefinedOrUnknownSVal>(V));
2493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  if (StNull) {
2513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry    if (!StNonNull) {
2523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry      reportBug(StNull, S, C, /*isBind=*/true);
2533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry      return;
2543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry    }
2553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry    // At this point the value could be either null or non-null.
2573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry    // Record this as an "implicit" null dereference.
2583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry    if (ExplodedNode *N = C.generateSink(StNull)) {
2593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry      ImplicitNullDerefEvent event = { V, /*isLoad=*/true, N,
2603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry                                       &C.getBugReporter() };
2613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry      dispatchEvent(event);
2623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry    }
2633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  }
2643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  // Unlike a regular null dereference, initializing a reference with a
2663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  // dereferenced null pointer does not actually cause a runtime exception in
2673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  // Clang's implementation of references.
2683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  //
2693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  //   int &r = *p; // safe??
2703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  //   if (p != NULL) return; // uh-oh
2713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  //   r = 5; // trap here
2723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  //
2733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  // The standard says this is invalid as soon as we try to create a "null
2743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  // reference" (there is no such thing), but turning this into an assumption
2753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  // that 'p' is never null will not match our actual runtime behavior.
2763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  // So we do not record this assumption, allowing us to warn on the last line
2773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  // of this example.
2783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  //
2793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  // We do need to add a transition because we may have generated a sink for
2803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  // the "implicit" null dereference.
2813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  C.addTransition(State, this);
2823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
2833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2843c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid ento::registerDereferenceChecker(CheckerManager &mgr) {
2853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  mgr.registerChecker<DereferenceChecker>();
2863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
2873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry