示例#1
0
void ExprEngine::VisitBlockExpr(const BlockExpr *BE, ExplodedNode *Pred,
                                ExplodedNodeSet &Dst) {
  
  CanQualType T = getContext().getCanonicalType(BE->getType());

  // Get the value of the block itself.
  SVal V = svalBuilder.getBlockPointer(BE->getBlockDecl(), T,
                                       Pred->getLocationContext());
  
  ProgramStateRef State = Pred->getState();
  
  // If we created a new MemRegion for the block, we should explicitly bind
  // the captured variables.
  if (const BlockDataRegion *BDR =
      dyn_cast_or_null<BlockDataRegion>(V.getAsRegion())) {
    
    BlockDataRegion::referenced_vars_iterator I = BDR->referenced_vars_begin(),
                                              E = BDR->referenced_vars_end();
    
    for (; I != E; ++I) {
      const MemRegion *capturedR = I.getCapturedRegion();
      const MemRegion *originalR = I.getOriginalRegion();
      if (capturedR != originalR) {
        SVal originalV = State->getSVal(loc::MemRegionVal(originalR));
        State = State->bindLoc(loc::MemRegionVal(capturedR), originalV);
      }
    }
  }
  
  ExplodedNodeSet Tmp;
  StmtNodeBuilder Bldr(Pred, Tmp, *currBldrCtx);
  Bldr.generateNode(BE, Pred,
                    State->BindExpr(BE, Pred->getLocationContext(), V),
                    0, ProgramPoint::PostLValueKind);
  
  // FIXME: Move all post/pre visits to ::Visit().
  getCheckerManager().runCheckersForPostStmt(Dst, Tmp, BE, *this);
}
std::shared_ptr<PathDiagnosticPiece>
DivisionBRVisitor::VisitNode(const ExplodedNode *Succ, const ExplodedNode *Pred,
                             BugReporterContext &BRC, BugReport &BR) {
  if (Satisfied)
    return nullptr;

  const Expr *E = nullptr;

  if (Optional<PostStmt> P = Succ->getLocationAs<PostStmt>())
    if (const BinaryOperator *BO = P->getStmtAs<BinaryOperator>()) {
      BinaryOperator::Opcode Op = BO->getOpcode();
      if (Op == BO_Div || Op == BO_Rem || Op == BO_DivAssign ||
          Op == BO_RemAssign) {
        E = BO->getRHS();
      }
    }

  if (!E)
    return nullptr;

  SVal S = Succ->getSVal(E);
  if (ZeroSymbol == S.getAsSymbol() && SFC == Succ->getStackFrame()) {
    Satisfied = true;

    // Construct a new PathDiagnosticPiece.
    ProgramPoint P = Succ->getLocation();
    PathDiagnosticLocation L =
        PathDiagnosticLocation::create(P, BRC.getSourceManager());

    if (!L.isValid() || !L.asLocation().isValid())
      return nullptr;

    return std::make_shared<PathDiagnosticEventPiece>(
        L, "Division with compared value made here");
  }

  return nullptr;
}
示例#3
0
SVal ProgramState::getSVal(Loc location, QualType T) const {
  SVal V = getRawSVal(cast<Loc>(location), T);

  // If 'V' is a symbolic value that is *perfectly* constrained to
  // be a constant value, use that value instead to lessen the burden
  // on later analysis stages (so we have less symbolic values to reason
  // about).
  if (!T.isNull()) {
    if (SymbolRef sym = V.getAsSymbol()) {
      if (const llvm::APSInt *Int = getStateManager()
                                    .getConstraintManager()
                                    .getSymVal(this, sym)) {
        // FIXME: Because we don't correctly model (yet) sign-extension
        // and truncation of symbolic values, we need to convert
        // the integer value to the correct signedness and bitwidth.
        //
        // This shows up in the following:
        //
        //   char foo();
        //   unsigned x = foo();
        //   if (x == 54)
        //     ...
        //
        //  The symbolic value stored to 'x' is actually the conjured
        //  symbol for the call to foo(); the type of that symbol is 'char',
        //  not unsigned.
        const llvm::APSInt &NewV = getBasicVals().Convert(T, *Int);
        
        if (V.getAs<Loc>())
          return loc::ConcreteInt(NewV);
        else
          return nonloc::ConcreteInt(NewV);
      }
    }
  }
  
  return V;
}
void PointerSubChecker::checkPreStmt(const BinaryOperator *B,
                                     CheckerContext &C) const {
  // When doing pointer subtraction, if the two pointers do not point to the
  // same memory chunk, emit a warning.
  if (B->getOpcode() != BO_Sub)
    return;

  ProgramStateRef state = C.getState();
  const LocationContext *LCtx = C.getLocationContext();
  SVal LV = state->getSVal(B->getLHS(), LCtx);
  SVal RV = state->getSVal(B->getRHS(), LCtx);

  const MemRegion *LR = LV.getAsRegion();
  const MemRegion *RR = RV.getAsRegion();

  if (!(LR && RR))
    return;

  const MemRegion *BaseLR = LR->getBaseRegion();
  const MemRegion *BaseRR = RR->getBaseRegion();

  if (BaseLR == BaseRR)
    return;

  // Allow arithmetic on different symbolic regions.
  if (isa<SymbolicRegion>(BaseLR) || isa<SymbolicRegion>(BaseRR))
    return;

  if (ExplodedNode *N = C.addTransition()) {
    if (!BT)
      BT.reset(new BuiltinBug("Pointer subtraction", 
                          "Subtraction of two pointers that do not point to "
                          "the same memory chunk may cause incorrect result."));
    BugReport *R = new BugReport(*BT, BT->getDescription(), N);
    R->addRange(B->getSourceRange());
    C.EmitReport(R);
  }
}
void TestAfterDivZeroChecker::reportBug(SVal Val, CheckerContext &C) const {
  if (ExplodedNode *N = C.generateSink(C.getState())) {
    if (!DivZeroBug)
      DivZeroBug.reset(new BuiltinBug(this, "Division by zero"));

    BugReport *R =
        new BugReport(*DivZeroBug, "Value being compared against zero has "
                                   "already been used for division",
                      N);

    R->addVisitor(new DivisionBRVisitor(Val.getAsSymbol(), C.getStackFrame()));
    C.emitReport(R);
  }
}
// Handle assigning to an iterator where we don't have the LValue MemRegion.
const ProgramState *IteratorsChecker::handleAssign(const ProgramState *state,
    const Expr *lexp, const Expr *rexp, const LocationContext *LC) const {
  // Skip the cast if present.
  if (const MaterializeTemporaryExpr *M 
                                    = dyn_cast<MaterializeTemporaryExpr>(lexp))
    lexp = M->GetTemporaryExpr();
  if (const ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(lexp))
    lexp = ICE->getSubExpr();
  SVal sv = state->getSVal(lexp);
  const MemRegion *MR = sv.getAsRegion();
  if (!MR)
    return state;
  RefKind kind = getTemplateKind(lexp->getType());

  // If assigning to a vector, invalidate any iterators currently associated.
  if (kind == VectorKind)
    return invalidateIterators(state, MR, 0);

  // Make sure that we are assigning to an iterator.
  if (getTemplateKind(lexp->getType()) != VectorIteratorKind)
    return state;
  return handleAssign(state, MR, rexp, LC);
}
示例#7
0
void CallAndMessageChecker::checkPreStmt(const CallExpr *CE,
                                         CheckerContext &C) const{

  const Expr *Callee = CE->getCallee()->IgnoreParens();
  ProgramStateRef State = C.getState();
  const LocationContext *LCtx = C.getLocationContext();
  SVal L = State->getSVal(Callee, LCtx);

  if (L.isUndef()) {
    if (!BT_call_undef)
      BT_call_undef.reset(new BuiltinBug("Called function pointer is an "
                                         "uninitalized pointer value"));
    EmitBadCall(BT_call_undef.get(), C, CE);
    return;
  }

  if (L.isZeroConstant()) {
    if (!BT_call_null)
      BT_call_null.reset(
        new BuiltinBug("Called function pointer is null (null dereference)"));
    EmitBadCall(BT_call_null.get(), C, CE);
  }
}
bool OSAtomicChecker::evalCall(const CallExpr *CE, CheckerContext &C) const {
  const ProgramState *state = C.getState();
  const Expr *Callee = CE->getCallee();
  SVal L = state->getSVal(Callee);

  const FunctionDecl *FD = L.getAsFunctionDecl();
  if (!FD)
    return false;

  const IdentifierInfo *II = FD->getIdentifier();
  if (!II)
    return false;
  
  StringRef FName(II->getName());

  // Check for compare and swap.
  if (FName.startswith("OSAtomicCompareAndSwap") ||
      FName.startswith("objc_atomicCompareAndSwap"))
    return evalOSAtomicCompareAndSwap(C, CE);

  // FIXME: Other atomics.
  return false;
}
bool DoubleFetchChecker::isLocTainted(ProgramStateRef state, SVal loc) const{
	if (MaxTag == -1)
		return false;
	else{
		const MemRegion *mrptr = loc.getAsRegion();
		if(!mrptr)
			std::cout<<"(isLocTainted) getAsRegion failed!"<<std::endl;
		const TaintList *tl = state->get<LocalVarMap>(mrptr);
		if (tl){
			return true;
		}
		return false;
	}
}
void CallAndMessageChecker::checkPreStmt(const CXXDeleteExpr *DE,
                                         CheckerContext &C) const {

  SVal Arg = C.getSVal(DE->getArgument());
  if (Arg.isUndef()) {
    StringRef Desc;
    ExplodedNode *N = C.generateSink();
    if (!N)
      return;
    if (!BT_cxx_delete_undef)
      BT_cxx_delete_undef.reset(
          new BuiltinBug(this, "Uninitialized argument value"));
    if (DE->isArrayFormAsWritten())
      Desc = "Argument to 'delete[]' is uninitialized";
    else
      Desc = "Argument to 'delete' is uninitialized";
    BugType *BT = BT_cxx_delete_undef.get();
    auto R = llvm::make_unique<BugReport>(*BT, Desc, N);
    bugreporter::trackNullOrUndefValue(N, DE, *R);
    C.emitReport(std::move(R));
    return;
  }
}
void UndefinedAssignmentChecker::checkBind(SVal location, SVal val,
                                           const Stmt *StoreE,
                                           CheckerContext &C) const {
  if (!val.isUndef())
    return;

  ExplodedNode *N = C.generateSink();

  if (!N)
    return;

  const char *str = "Assigned value is garbage or undefined";

  if (!BT)
    BT.reset(new BuiltinBug(str));

  // Generate a report for this bug.
  const Expr *ex = 0;

  while (StoreE) {
    if (const BinaryOperator *B = dyn_cast<BinaryOperator>(StoreE)) {
      if (B->isCompoundAssignmentOp()) {
        ProgramStateRef state = C.getState();
        if (state->getSVal(B->getLHS(), C.getLocationContext()).isUndef()) {
          str = "The left expression of the compound assignment is an "
                "uninitialized value. The computed value will also be garbage";
          ex = B->getLHS();
          break;
        }
      }

      ex = B->getRHS();
      break;
    }

    if (const DeclStmt *DS = dyn_cast<DeclStmt>(StoreE)) {
      const VarDecl *VD = dyn_cast<VarDecl>(DS->getSingleDecl());
      ex = VD->getInit();
    }

    break;
  }

  BugReport *R = new BugReport(*BT, str, N);
  if (ex) {
    R->addRange(ex->getSourceRange());
    bugreporter::trackNullOrUndefValue(N, ex, *R);
  }
  C.EmitReport(R);
}
示例#12
0
void PointerSubChecker::checkPreStmt(const BinaryOperator *B,
                                     CheckerContext &C) const {
  // When doing pointer subtraction, if the two pointers do not point to the
  // same memory chunk, emit a warning.
  if (B->getOpcode() != BO_Sub)
    return;

  SVal LV = C.getSVal(B->getLHS());
  SVal RV = C.getSVal(B->getRHS());

  const MemRegion *LR = LV.getAsRegion();
  const MemRegion *RR = RV.getAsRegion();

  if (!(LR && RR))
    return;

  const MemRegion *BaseLR = LR->getBaseRegion();
  const MemRegion *BaseRR = RR->getBaseRegion();

  if (BaseLR == BaseRR)
    return;

  // Allow arithmetic on different symbolic regions.
  if (isa<SymbolicRegion>(BaseLR) || isa<SymbolicRegion>(BaseRR))
    return;

  if (ExplodedNode *N = C.generateNonFatalErrorNode()) {
    if (!BT)
      BT.reset(
          new BuiltinBug(this, "Pointer subtraction",
                         "Subtraction of two pointers that do not point to "
                         "the same memory chunk may cause incorrect result."));
    auto R = llvm::make_unique<BugReport>(*BT, BT->getDescription(), N);
    R->addRange(B->getSourceRange());
    C.emitReport(std::move(R));
  }
}
// on a member call, first check the args for any bad iterators
// then, check to see if it is a call to a function that will invalidate
// the iterators
void IteratorsChecker::checkPreStmt(const CXXMemberCallExpr *MCE,
                                    CheckerContext &C) const {
  // Check the arguments.
  checkArgs(C, MCE);
  const MemberExpr *ME = dyn_cast<MemberExpr>(MCE->getCallee());
  if (!ME)
    return;
  // Make sure we have the right kind of container.
  const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(ME->getBase());
  if (!DRE || getTemplateKind(DRE->getType()) != VectorKind)
    return;
  SVal tsv = C.getState()->getSVal(DRE);
  // Get the MemRegion associated with the container instance.
  const MemRegion *MR = tsv.getAsRegion();
  if (!MR)
    return;
  // If we are calling a function that invalidates iterators, mark them
  // appropriately by finding matching instances.
  const ProgramState *state = C.getState();
  StringRef mName = ME->getMemberDecl()->getName();
  if (llvm::StringSwitch<bool>(mName)
      .Cases("insert", "reserve", "push_back", true)
      .Cases("erase", "pop_back", "clear", "resize", true)
      .Default(false)) {
    // If there was a 'reserve' call, assume iterators are good.
    if (!state->contains<CalledReserved>(MR))
      state = invalidateIterators(state, MR, ME);
  }
  // Keep track of instances that have called 'reserve'
  // note: do this after we invalidate any iterators by calling 
  // 'reserve' itself.
  if (mName == "reserve")
    state = state->add<CalledReserved>(MR);
  
  if (state != C.getState())
    C.addTransition(state);
}
示例#14
0
void DereferenceChecker::checkLocation(SVal l, bool isLoad, const Stmt* S,
                                       CheckerContext &C) const {
  // Check for dereference of an undefined value.
  if (l.isUndef()) {
    if (ExplodedNode *N = C.generateSink()) {
      if (!BT_undef)
        BT_undef.reset(new BuiltinBug("Dereference of undefined pointer value"));

      BugReport *report =
        new BugReport(*BT_undef, BT_undef->getDescription(), N);
      bugreporter::addTrackNullOrUndefValueVisitor(N,
                                                   bugreporter::GetDerefExpr(N),
                                                   report);
      report->disablePathPruning();
      C.EmitReport(report);
    }
    return;
  }

  DefinedOrUnknownSVal location = cast<DefinedOrUnknownSVal>(l);

  // Check for null dereferences.
  if (!isa<Loc>(location))
    return;

  ProgramStateRef state = C.getState();

  ProgramStateRef notNullState, nullState;
  llvm::tie(notNullState, nullState) = state->assume(location);

  // The explicit NULL case.
  if (nullState) {
    if (!notNullState) {
      reportBug(nullState, S, C);
      return;
    }

    // Otherwise, we have the case where the location could either be
    // null or not-null.  Record the error node as an "implicit" null
    // dereference.
    if (ExplodedNode *N = C.generateSink(nullState)) {
      ImplicitNullDerefEvent event = { l, isLoad, N, &C.getBugReporter() };
      dispatchEvent(event);
    }
  }

  // From this point forward, we know that the location is not null.
  C.addTransition(notNullState);
}
示例#15
0
SymbolRef DoubleFetchChecker::getSymbolRef(SVal val) const {
	if(val.isConstant()){
		std::cout<<"--->(getSymbolRef) failed! IsConstant."<<"\tval is:"<<toStr(val)<<std::endl;
		return NULL;
	}
	if(val.isUnknownOrUndef()){
		std::cout<<"--->(getSymbolRef) failed! IsUnknownOrUndef."<<"\tval is:"<<toStr(val)<<std::endl;
		return NULL;
	}
	const SymExpr * SE = val.getAsSymExpr();
	if (SE != NULL){
		//std::cout<<"--->(getSymbolRef) getAsSymExpr succeed!"<<std::endl;
		return SE;
	}
	else{
		//std::cout<<"--->(getSymbolRef) getAsSymExpr failed!, try get memregion"<<"\tval is:"<<toStr(val)<<std::endl;
		const MemRegion *Reg = val.getAsRegion();
		if(!Reg){
			std::cout<<"--->(getSymbolRef) getAsRegion failed!"<<"\tval is:"<<toStr(val)<<std::endl;
			return NULL;
		}
		else{
			if (const SymbolicRegion *SR = dyn_cast_or_null<SymbolicRegion>(Reg)){
				//std::cout<<"--->(getSymbolRef) getAsRegion succeed."<<std::endl;
				return SR->getSymbol();
			}
			else{
				std::cout<<"--->(getSymbolRef) memRegion get symbolref failed."<<std::endl;
				return NULL;
			}


		}
	}

}
示例#16
0
Optional<SVal> GenericTaintChecker::getPointedToSVal(CheckerContext &C,
                                                     const Expr *Arg) {
  ProgramStateRef State = C.getState();
  SVal AddrVal = C.getSVal(Arg->IgnoreParens());
  if (AddrVal.isUnknownOrUndef())
    return None;

  Optional<Loc> AddrLoc = AddrVal.getAs<Loc>();
  if (!AddrLoc)
    return None;

  QualType ArgTy = Arg->getType().getCanonicalType();
  if (!ArgTy->isPointerType())
    return None;

  QualType ValTy = ArgTy->getPointeeType();

  // Do not dereference void pointers. Treat them as byte pointers instead.
  // FIXME: we might want to consider more than just the first byte.
  if (ValTy->isVoidType())
    ValTy = C.getASTContext().CharTy;

  return State->getSVal(*AddrLoc, ValTy);
}
void TestAfterDivZeroChecker::reportBug(SVal Val, CheckerContext &C) const {
  if (ExplodedNode *N = C.generateSink(C.getState())) {
    if (!DivZeroBug)
      DivZeroBug.reset(new BuiltinBug(this, "Division by zero"));

    auto R = llvm::make_unique<BugReport>(
        *DivZeroBug, "Value being compared against zero has already been used "
                     "for division",
        N);

    R->addVisitor(llvm::make_unique<DivisionBRVisitor>(Val.getAsSymbol(),
                                                       C.getStackFrame()));
    C.emitReport(std::move(R));
  }
}
示例#18
0
bool ScanReachableSymbols::scan(SVal val) {
  if (loc::MemRegionVal *X = dyn_cast<loc::MemRegionVal>(&val))
    return scan(X->getRegion());

  if (nonloc::LocAsInteger *X = dyn_cast<nonloc::LocAsInteger>(&val))
    return scan(X->getLoc());

  if (SymbolRef Sym = val.getAsSymbol())
    return visitor.VisitSymbol(Sym);

  if (nonloc::CompoundVal *X = dyn_cast<nonloc::CompoundVal>(&val))
    return scan(*X);

  return true;
}
示例#19
0
bool StoreManager::FindUniqueBinding::HandleBinding(StoreManager& SMgr,
                                                    Store store,
                                                    const MemRegion* R,
                                                    SVal val) {
  SymbolRef SymV = val.getAsLocSymbol();
  if (!SymV || SymV != Sym)
    return true;

  if (Binding) {
    First = false;
    return false;
  }
  else
    Binding = R;

  return true;
}
示例#20
0
// Check if the location is a freed symbolic region.
void MallocChecker::checkLocation(SVal l, bool isLoad,CheckerContext &C) const {
  SymbolRef Sym = l.getLocSymbolInBase();
  if (Sym) {
    const RefState *RS = C.getState()->get<RegionState>(Sym);
    if (RS && RS->isReleased()) {
      if (ExplodedNode *N = C.generateNode()) {
        if (!BT_UseFree)
          BT_UseFree.reset(new BuiltinBug("Use dynamically allocated memory "
                                          "after it is freed."));

        BugReport *R = new BugReport(*BT_UseFree, BT_UseFree->getDescription(),
                                     N);
        C.EmitReport(R);
      }
    }
  }
}
Store BasicStoreManager::Bind(Store store, Loc loc, SVal V) {
    if (isa<loc::ConcreteInt>(loc))
        return store;

    const MemRegion* R = cast<loc::MemRegionVal>(loc).getRegion();
    ASTContext &C = StateMgr.getContext();

    // Special case: handle store of pointer values (Loc) to pointers via
    // a cast to intXX_t*, void*, etc.  This is needed to handle
    // OSCompareAndSwap32Barrier/OSCompareAndSwap64Barrier.
    if (isa<Loc>(V) || isa<nonloc::LocAsInteger>(V))
        if (const ElementRegion *ER = dyn_cast<ElementRegion>(R)) {
            // FIXME: Should check for index 0.
            QualType T = ER->getLocationType(C);

            if (isHigherOrderRawPtr(T, C))
                R = ER->getSuperRegion();
        }

    if (!(isa<VarRegion>(R) || isa<ObjCIvarRegion>(R)))
        return store;

    const TypedRegion *TyR = cast<TypedRegion>(R);

    // Do not bind to arrays.  We need to explicitly check for this so that
    // we do not encounter any weirdness of trying to load/store from arrays.
    if (TyR->isBoundable() && TyR->getValueType(C)->isArrayType())
        return store;

    if (nonloc::LocAsInteger *X = dyn_cast<nonloc::LocAsInteger>(&V)) {
        // Only convert 'V' to a location iff the underlying region type
        // is a location as well.
        // FIXME: We are allowing a store of an arbitrary location to
        // a pointer.  We may wish to flag a type error here if the types
        // are incompatible.  This may also cause lots of breakage
        // elsewhere. Food for thought.
        if (TyR->isBoundable() && Loc::IsLocType(TyR->getValueType(C)))
            V = X->getLoc();
    }

    BindingsTy B = GetBindings(store);
    return V.isUnknown()
           ? VBFactory.Remove(B, R).getRoot()
           : VBFactory.Add(B, R, V).getRoot();
}
示例#22
0
void PthreadLockChecker::ReleaseLock(CheckerContext &C, const CallExpr *CE,
                                     SVal lock) {

  const MemRegion *lockR = lock.getAsRegion();
  if (!lockR)
    return;
  
  const GRState *state = C.getState();

  // Record that the lock was released.  
  // FIXME: Handle unlocking locks that were never acquired.  This may
  // require IPA for wrappers.
  const GRState *unlockState = state->remove<LockSet>(lockR);
  
  if (state == unlockState)
    return;
  
  C.addTransition(C.generateNode(CE, unlockState));  
}
示例#23
0
static bool regionMatchesCXXRecordType(SVal V, QualType Ty) {
  const MemRegion *MR = V.getAsRegion();
  if (!MR)
    return true;

  const auto *TVR = dyn_cast<TypedValueRegion>(MR);
  if (!TVR)
    return true;

  const CXXRecordDecl *RD = TVR->getValueType()->getAsCXXRecordDecl();
  if (!RD)
    return true;

  const CXXRecordDecl *Expected = Ty->getPointeeCXXRecordDecl();
  if (!Expected)
    Expected = Ty->getAsCXXRecordDecl();

  return Expected->getCanonicalDecl() == RD->getCanonicalDecl();
}
示例#24
0
void ObjCSelfInitChecker::checkBind(SVal loc, SVal val, const Stmt *S,
                                    CheckerContext &C) const {
  // Allow assignment of anything to self. Self is a local variable in the
  // initializer, so it is legal to assign anything to it, like results of
  // static functions/method calls. After self is assigned something we cannot
  // reason about, stop enforcing the rules.
  // (Only continue checking if the assigned value should be treated as self.)
  if ((isSelfVar(loc, C)) &&
      !hasSelfFlag(val, SelfFlag_InitRes, C) &&
      !hasSelfFlag(val, SelfFlag_Self, C) &&
      !isSelfVar(val, C)) {

    // Stop tracking the checker-specific state in the state.
    ProgramStateRef State = C.getState();
    State = State->remove<CalledInit>();
    if (SymbolRef sym = loc.getAsSymbol())
      State = State->remove<SelfFlag>(sym);
    C.addTransition(State);
  }
}
示例#25
0
/// CastRetrievedVal - Used by subclasses of StoreManager to implement
///  implicit casts that arise from loads from regions that are reinterpreted
///  as another region.
SVal StoreManager::CastRetrievedVal(SVal V, const TypedValueRegion *R,
                                    QualType castTy, bool performTestOnly) {
  
  if (castTy.isNull() || V.isUnknownOrUndef())
    return V;
  
  ASTContext &Ctx = svalBuilder.getContext();

  if (performTestOnly) {  
    // Automatically translate references to pointers.
    QualType T = R->getValueType();
    if (const ReferenceType *RT = T->getAs<ReferenceType>())
      T = Ctx.getPointerType(RT->getPointeeType());
    
    assert(svalBuilder.getContext().hasSameUnqualifiedType(castTy, T));
    return V;
  }
  
  return svalBuilder.dispatchCast(V, castTy);
}
示例#26
0
/// When a symbol is assumed to be nil, remove it from the set of symbols
/// require to be nil.
ProgramStateRef ObjCDeallocChecker::evalAssume(ProgramStateRef State, SVal Cond,
                                               bool Assumption) const {
  if (State->get<UnreleasedIvarMap>().isEmpty())
    return State;

  auto *CondBSE = dyn_cast_or_null<BinarySymExpr>(Cond.getAsSymExpr());
  if (!CondBSE)
    return State;

  BinaryOperator::Opcode OpCode = CondBSE->getOpcode();
  if (Assumption) {
    if (OpCode != BO_EQ)
      return State;
  } else {
    if (OpCode != BO_NE)
      return State;
  }

  SymbolRef NullSymbol = nullptr;
  if (auto *SIE = dyn_cast<SymIntExpr>(CondBSE)) {
    const llvm::APInt &RHS = SIE->getRHS();
    if (RHS != 0)
      return State;
    NullSymbol = SIE->getLHS();
  } else if (auto *SIE = dyn_cast<IntSymExpr>(CondBSE)) {
    const llvm::APInt &LHS = SIE->getLHS();
    if (LHS != 0)
      return State;
    NullSymbol = SIE->getRHS();
  } else {
    return State;
  }

  SymbolRef InstanceSymbol = getInstanceSymbolFromIvarSymbol(NullSymbol);
  if (!InstanceSymbol)
    return State;

  State = removeValueRequiringRelease(State, InstanceSymbol, NullSymbol);

  return State;
}
示例#27
0
SVal StoreManager::getLValueFieldOrIvar(const Decl *D, SVal Base) {
  if (Base.isUnknownOrUndef())
    return Base;

  Loc BaseL = Base.castAs<Loc>();
  const SubRegion* BaseR = nullptr;

  switch (BaseL.getSubKind()) {
  case loc::MemRegionValKind:
    BaseR = cast<SubRegion>(BaseL.castAs<loc::MemRegionVal>().getRegion());
    break;

  case loc::GotoLabelKind:
    // These are anormal cases. Flag an undefined value.
    return UndefinedVal();

  case loc::ConcreteIntKind:
    // While these seem funny, this can happen through casts.
    // FIXME: What we should return is the field offset, not base. For example,
    //  add the field offset to the integer value.  That way things
    //  like this work properly:  &(((struct foo *) 0xa)->f)
    //  However, that's not easy to fix without reducing our abilities
    //  to catch null pointer dereference. Eg., ((struct foo *)0x0)->f = 7
    //  is a null dereference even though we're dereferencing offset of f
    //  rather than null. Coming up with an approach that computes offsets
    //  over null pointers properly while still being able to catch null
    //  dereferences might be worth it.
    return Base;

  default:
    llvm_unreachable("Unhandled Base.");
  }

  // NOTE: We must have this check first because ObjCIvarDecl is a subclass
  // of FieldDecl.
  if (const auto *ID = dyn_cast<ObjCIvarDecl>(D))
    return loc::MemRegionVal(MRMgr.getObjCIvarRegion(ID, BaseR));

  return loc::MemRegionVal(MRMgr.getFieldRegion(cast<FieldDecl>(D), BaseR));
}
示例#28
0
std::string StackHintGeneratorForSymbol::getMessage(const ExplodedNode *N){
  ProgramPoint P = N->getLocation();
  const CallExitEnd *CExit = dyn_cast<CallExitEnd>(&P);
  assert(CExit && "Stack Hints should be constructed at CallExitEnd points.");

  // FIXME: Use CallEvent to abstract this over all calls.
  const Stmt *CallSite = CExit->getCalleeContext()->getCallSite();
  const CallExpr *CE = dyn_cast_or_null<CallExpr>(CallSite);
  if (!CE)
    return "";

  if (!N)
    return getMessageForSymbolNotFound();

  // Check if one of the parameters are set to the interesting symbol.
  ProgramStateRef State = N->getState();
  const LocationContext *LCtx = N->getLocationContext();
  unsigned ArgIndex = 0;
  for (CallExpr::const_arg_iterator I = CE->arg_begin(),
                                    E = CE->arg_end(); I != E; ++I, ++ArgIndex){
    SVal SV = State->getSVal(*I, LCtx);

    // Check if the variable corresponding to the symbol is passed by value.
    SymbolRef AS = SV.getAsLocSymbol();
    if (AS == Sym) {
      return getMessageForArg(*I, ArgIndex);
    }

    // Check if the parameter is a pointer to the symbol.
    if (const loc::MemRegionVal *Reg = dyn_cast<loc::MemRegionVal>(&SV)) {
      SVal PSV = State->getSVal(Reg->getRegion());
      SymbolRef AS = PSV.getAsLocSymbol();
      if (AS == Sym) {
        return getMessageForArg(*I, ArgIndex);
      }
    }
  }

  // Check if we are returning the interesting symbol.
  SVal SV = State->getSVal(CE, LCtx);
  SymbolRef RetSym = SV.getAsLocSymbol();
  if (RetSym == Sym) {
    return getMessageForReturn(CE);
  }

  return getMessageForSymbolNotFound();
}
示例#29
0
std::string StackHintGeneratorForSymbol::getMessage(const ExplodedNode *N){
  if (!N)
    return getMessageForSymbolNotFound();

  ProgramPoint P = N->getLocation();
  CallExitEnd CExit = P.castAs<CallExitEnd>();

  // FIXME: Use CallEvent to abstract this over all calls.
  const Stmt *CallSite = CExit.getCalleeContext()->getCallSite();
  const auto *CE = dyn_cast_or_null<CallExpr>(CallSite);
  if (!CE)
    return {};

  // Check if one of the parameters are set to the interesting symbol.
  unsigned ArgIndex = 0;
  for (CallExpr::const_arg_iterator I = CE->arg_begin(),
                                    E = CE->arg_end(); I != E; ++I, ++ArgIndex){
    SVal SV = N->getSVal(*I);

    // Check if the variable corresponding to the symbol is passed by value.
    SymbolRef AS = SV.getAsLocSymbol();
    if (AS == Sym) {
      return getMessageForArg(*I, ArgIndex);
    }

    // Check if the parameter is a pointer to the symbol.
    if (Optional<loc::MemRegionVal> Reg = SV.getAs<loc::MemRegionVal>()) {
      // Do not attempt to dereference void*.
      if ((*I)->getType()->isVoidPointerType())
        continue;
      SVal PSV = N->getState()->getSVal(Reg->getRegion());
      SymbolRef AS = PSV.getAsLocSymbol();
      if (AS == Sym) {
        return getMessageForArg(*I, ArgIndex);
      }
    }
  }

  // Check if we are returning the interesting symbol.
  SVal SV = N->getSVal(CE);
  SymbolRef RetSym = SV.getAsLocSymbol();
  if (RetSym == Sym) {
    return getMessageForReturn(CE);
  }

  return getMessageForSymbolNotFound();
}
示例#30
0
ProgramStateRef ProgramState::assumeInBound(DefinedOrUnknownSVal Idx,
                                      DefinedOrUnknownSVal UpperBound,
                                      bool Assumption,
                                      QualType indexTy) const {
  if (Idx.isUnknown() || UpperBound.isUnknown())
    return this;

  // Build an expression for 0 <= Idx < UpperBound.
  // This is the same as Idx + MIN < UpperBound + MIN, if overflow is allowed.
  // FIXME: This should probably be part of SValBuilder.
  ProgramStateManager &SM = getStateManager();
  SValBuilder &svalBuilder = SM.getSValBuilder();
  ASTContext &Ctx = svalBuilder.getContext();

  // Get the offset: the minimum value of the array index type.
  BasicValueFactory &BVF = svalBuilder.getBasicValueFactory();
  // FIXME: This should be using ValueManager::ArrayindexTy...somehow.
  if (indexTy.isNull())
    indexTy = Ctx.IntTy;
  nonloc::ConcreteInt Min(BVF.getMinValue(indexTy));

  // Adjust the index.
  SVal newIdx = svalBuilder.evalBinOpNN(this, BO_Add,
                                        cast<NonLoc>(Idx), Min, indexTy);
  if (newIdx.isUnknownOrUndef())
    return this;

  // Adjust the upper bound.
  SVal newBound =
    svalBuilder.evalBinOpNN(this, BO_Add, cast<NonLoc>(UpperBound),
                            Min, indexTy);

  if (newBound.isUnknownOrUndef())
    return this;

  // Build the actual comparison.
  SVal inBound = svalBuilder.evalBinOpNN(this, BO_LT,
                                cast<NonLoc>(newIdx), cast<NonLoc>(newBound),
                                Ctx.IntTy);
  if (inBound.isUnknownOrUndef())
    return this;

  // Finally, let the constraint manager take care of it.
  ConstraintManager &CM = SM.getConstraintManager();
  return CM.assume(this, cast<DefinedSVal>(inBound), Assumption);
}