Пример #1
0
static ProgramStateRef assumeExprIsNonNull(const Expr *NonNullExpr,
        ProgramStateRef State,
        CheckerContext &C) {
    SVal Val = State->getSVal(NonNullExpr, C.getLocationContext());
    if (Optional<DefinedOrUnknownSVal> DV = Val.getAs<DefinedOrUnknownSVal>())
        return State->assume(*DV, true);
    return State;
}
void UndefinedAssignmentChecker::checkBind(SVal location, SVal val,
        const Stmt *StoreE,
        CheckerContext &C) const {
    if (!val.isUndef())
        return;

    // Do not report assignments of uninitialized values inside swap functions.
    // This should allow to swap partially uninitialized structs
    // (radar://14129997)
    if (const FunctionDecl *EnclosingFunctionDecl =
                dyn_cast<FunctionDecl>(C.getStackFrame()->getDecl()))
        if (C.getCalleeName(EnclosingFunctionDecl) == "swap")
            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);
}
Пример #3
0
void MacOSKeychainAPIChecker::checkPostStmt(const CallExpr *CE,
                                            CheckerContext &C) const {
  ProgramStateRef State = C.getState();
  const FunctionDecl *FD = C.getCalleeDecl(CE);
  if (!FD || FD->getKind() != Decl::Function)
    return;

  StringRef funName = C.getCalleeName(FD);

  // If a value has been allocated, add it to the set for tracking.
  unsigned idx = getTrackedFunctionIndex(funName, true);
  if (idx == InvalidIdx)
    return;

  const Expr *ArgExpr = CE->getArg(FunctionsToTrack[idx].Param);
  // If the argument entered as an enclosing function parameter, skip it to
  // avoid false positives.
  if (isEnclosingFunctionParam(ArgExpr) &&
      C.getLocationContext()->getParent() == 0)
    return;

  if (SymbolRef V = getAsPointeeSymbol(ArgExpr, C)) {
    // If the argument points to something that's not a symbolic region, it
    // can be:
    //  - unknown (cannot reason about it)
    //  - undefined (already reported by other checker)
    //  - constant (null - should not be tracked,
    //              other constant will generate a compiler warning)
    //  - goto (should be reported by other checker)

    // The call return value symbol should stay alive for as long as the
    // allocated value symbol, since our diagnostics depend on the value
    // returned by the call. Ex: Data should only be freed if noErr was
    // returned during allocation.)
    SymbolRef RetStatusSymbol =
      State->getSVal(CE, C.getLocationContext()).getAsSymbol();
    C.getSymbolManager().addSymbolDependency(V, RetStatusSymbol);

    // Track the allocated value in the checker state.
    State = State->set<AllocatedData>(V, AllocationState(ArgExpr, idx,
                                                         RetStatusSymbol));
    assert(State);
    C.addTransition(State);
  }
}
Пример #4
0
void DoubleFetchChecker::checkPreStmt(const Expr* E, CheckerContext &Ctx) const {
	ProgramStateRef state = Ctx.getState();
	SVal ExpVal = state->getSVal(E, Ctx.getLocationContext());

	SourceLocation L = E->getExprLoc();



}
Пример #5
0
/// \brief Returns true of the value of the expression is the object that 'self'
/// points to and is an object that did not come from the result of calling
/// an initializer.
static bool isInvalidSelf(const Expr *E, CheckerContext &C) {
  SVal exprVal = C.getState()->getSVal(E, C.getLocationContext());
  if (!hasSelfFlag(exprVal, SelfFlag_Self, C))
    return false; // value did not come from 'self'.
  if (hasSelfFlag(exprVal, SelfFlag_InitRes, C))
    return false; // 'self' is properly initialized.

  return true;
}
Пример #6
0
void ObjCContainersChecker::addSizeInfo(const Expr *Array, const Expr *Size,
                                        CheckerContext &C) const {
  ProgramStateRef State = C.getState();
  SVal SizeV = State->getSVal(Size, C.getLocationContext());
  // Undefined is reported by another checker.
  if (SizeV.isUnknownOrUndef())
    return;

  // Get the ArrayRef symbol.
  SVal ArrayRef = State->getSVal(Array, C.getLocationContext());
  SymbolRef ArraySym = ArrayRef.getAsSymbol();
  if (!ArraySym)
    return;

  C.addTransition(
      State->set<ArraySizeMap>(ArraySym, SizeV.castAs<DefinedSVal>()));
  return;
}
void AdjustedReturnValueChecker::checkPostStmt(const CallExpr *CE,
                                               CheckerContext &C) const {
  
  // Get the result type of the call.
  QualType expectedResultTy = CE->getType();

  // Fetch the signature of the called function.
  const ProgramState *state = C.getState();
  const LocationContext *LCtx = C.getLocationContext();

  SVal V = state->getSVal(CE, LCtx);
  
  if (V.isUnknown())
    return;
  
  // Casting to void?  Discard the value.
  if (expectedResultTy->isVoidType()) {
    C.addTransition(state->BindExpr(CE, LCtx, UnknownVal()));
    return;
  }                   

  const MemRegion *callee = state->getSVal(CE->getCallee(), LCtx).getAsRegion();
  if (!callee)
    return;

  QualType actualResultTy;
  
  if (const FunctionTextRegion *FT = dyn_cast<FunctionTextRegion>(callee)) {
    const FunctionDecl *FD = FT->getDecl();
    actualResultTy = FD->getResultType();
  }
  else if (const BlockDataRegion *BD = dyn_cast<BlockDataRegion>(callee)) {
    const BlockTextRegion *BR = BD->getCodeRegion();
    const BlockPointerType *BT=BR->getLocationType()->getAs<BlockPointerType>();
    const FunctionType *FT = BT->getPointeeType()->getAs<FunctionType>();
    actualResultTy = FT->getResultType();
  }

  // Can this happen?
  if (actualResultTy.isNull())
    return;

  // For now, ignore references.
  if (actualResultTy->getAs<ReferenceType>())
    return;
  

  // Are they the same?
  if (expectedResultTy != actualResultTy) {
    // FIXME: Do more checking and actual emit an error. At least performing
    // the cast avoids some assertion failures elsewhere.
    SValBuilder &svalBuilder = C.getSValBuilder();
    V = svalBuilder.evalCast(V, expectedResultTy, actualResultTy);
    C.addTransition(state->BindExpr(CE, LCtx, V));
  }
}
Пример #8
0
void CallAndMessageChecker::checkPreObjCMessage(ObjCMessage msg,
                                                CheckerContext &C) const {

  ProgramStateRef state = C.getState();
  const LocationContext *LCtx = C.getLocationContext();

  // FIXME: Handle 'super'?
  if (const Expr *receiver = msg.getInstanceReceiver()) {
    SVal recVal = state->getSVal(receiver, LCtx);
    if (recVal.isUndef()) {
      if (ExplodedNode *N = C.generateSink()) {
        BugType *BT = 0;
        if (msg.isPureMessageExpr()) {
          if (!BT_msg_undef)
            BT_msg_undef.reset(new BuiltinBug("Receiver in message expression "
                                              "is an uninitialized value"));
          BT = BT_msg_undef.get();
        }
        else {
          if (!BT_objc_prop_undef)
            BT_objc_prop_undef.reset(new BuiltinBug("Property access on an "
                                              "uninitialized object pointer"));
          BT = BT_objc_prop_undef.get();
        }
        BugReport *R =
          new BugReport(*BT, BT->getName(), N);
        R->addRange(receiver->getSourceRange());
        R->addVisitor(bugreporter::getTrackNullOrUndefValueVisitor(N,
                                                                   receiver,
                                                                   R));
        C.EmitReport(R);
      }
      return;
    } else {
      // Bifurcate the state into nil and non-nil ones.
      DefinedOrUnknownSVal receiverVal = cast<DefinedOrUnknownSVal>(recVal);
  
      ProgramStateRef notNilState, nilState;
      llvm::tie(notNilState, nilState) = state->assume(receiverVal);
  
      // Handle receiver must be nil.
      if (nilState && !notNilState) {
        HandleNilReceiver(C, state, msg);
        return;
      }
    }
  }

  const char *bugDesc = msg.isPropertySetter() ?
                     "Argument for property setter is an uninitialized value"
                   : "Argument in message expression is an uninitialized value";
  // Check for any arguments that are uninitialized/undefined.
  PreVisitProcessArgs(C, CallOrObjCMessage(msg, state, LCtx),
                      bugDesc, BT_msg_arg);
}
Пример #9
0
/// Explicit casts are trusted. If there is a disagreement in the nullability
/// annotations in the destination and the source or '0' is casted to nonnull
/// track the value as having contraditory nullability. This will allow users to
/// suppress warnings.
void NullabilityChecker::checkPostStmt(const ExplicitCastExpr *CE,
                                       CheckerContext &C) const {
  QualType OriginType = CE->getSubExpr()->getType();
  QualType DestType = CE->getType();
  if (!OriginType->isAnyPointerType())
    return;
  if (!DestType->isAnyPointerType())
    return;

  ProgramStateRef State = C.getState();
  if (State->get<PreconditionViolated>())
    return;

  Nullability DestNullability = getNullabilityAnnotation(DestType);

  // No explicit nullability in the destination type, so this cast does not
  // change the nullability.
  if (DestNullability == Nullability::Unspecified)
    return;

  auto RegionSVal =
      State->getSVal(CE, C.getLocationContext()).getAs<DefinedOrUnknownSVal>();
  const MemRegion *Region = getTrackRegion(*RegionSVal);
  if (!Region)
    return;

  // When 0 is converted to nonnull mark it as contradicted.
  if (DestNullability == Nullability::Nonnull) {
    NullConstraint Nullness = getNullConstraint(*RegionSVal, State);
    if (Nullness == NullConstraint::IsNull) {
      State = State->set<NullabilityMap>(Region, Nullability::Contradicted);
      C.addTransition(State);
      return;
    }
  }

  const NullabilityState *TrackedNullability =
      State->get<NullabilityMap>(Region);

  if (!TrackedNullability) {
    if (DestNullability != Nullability::Nullable)
      return;
    State = State->set<NullabilityMap>(Region,
                                       NullabilityState(DestNullability, CE));
    C.addTransition(State);
    return;
  }

  if (TrackedNullability->getValue() != DestNullability &&
      TrackedNullability->getValue() != Nullability::Contradicted) {
    State = State->set<NullabilityMap>(Region, Nullability::Contradicted);
    C.addTransition(State);
  }
}
Пример #10
0
void ReturnPointerRangeChecker::checkPreStmt(const ReturnStmt *RS,
                                             CheckerContext &C) const {
  ProgramStateRef state = C.getState();

  const Expr *RetE = RS->getRetValue();
  if (!RetE)
    return;

  SVal V = state->getSVal(RetE, C.getLocationContext());
  const MemRegion *R = V.getAsRegion();

  const ElementRegion *ER = dyn_cast_or_null<ElementRegion>(R);
  if (!ER)
    return;

  DefinedOrUnknownSVal Idx = ER->getIndex().castAs<DefinedOrUnknownSVal>();
  // Zero index is always in bound, this also passes ElementRegions created for
  // pointer casts.
  if (Idx.isZeroConstant())
    return;
  // FIXME: All of this out-of-bounds checking should eventually be refactored
  // into a common place.

  DefinedOrUnknownSVal NumElements
    = C.getStoreManager().getSizeInElements(state, ER->getSuperRegion(),
                                           ER->getValueType());

  ProgramStateRef StInBound = state->assumeInBound(Idx, NumElements, true);
  ProgramStateRef StOutBound = state->assumeInBound(Idx, NumElements, false);
  if (StOutBound && !StInBound) {
    ExplodedNode *N = C.generateSink(StOutBound);

    if (!N)
      return;

    // FIXME: This bug correspond to CWE-466.  Eventually we should have bug
    // types explicitly reference such exploit categories (when applicable).
    if (!BT)
      BT.reset(new BuiltinBug(
          this, "Return of pointer value outside of expected range",
          "Returned pointer value points outside the original object "
          "(potential buffer overflow)"));

    // FIXME: It would be nice to eventually make this diagnostic more clear,
    // e.g., by referencing the original declaration or by saying *why* this
    // reference is outside the range.

    // Generate a report for this bug.
    auto report = llvm::make_unique<BugReport>(*BT, BT->getDescription(), N);

    report->addRange(RetE->getSourceRange());
    C.emitReport(std::move(report));
  }
}
static ProgramStateRef
assumeCollectionNonEmpty(CheckerContext &C, ProgramStateRef State,
                         const ObjCForCollectionStmt *FCS,
                         bool Assumption) {
  if (!State)
    return nullptr;

  SymbolRef CollectionS =
    State->getSVal(FCS->getCollection(), C.getLocationContext()).getAsSymbol();
  return assumeCollectionNonEmpty(C, State, CollectionS, Assumption);
}
Пример #12
0
void CallDumper::checkPreCall(const CallEvent &Call, CheckerContext &C) const {
  unsigned Indentation = 0;
  for (const LocationContext *LC = C.getLocationContext()->getParent();
       LC != nullptr; LC = LC->getParent())
    ++Indentation;

  // It is mildly evil to print directly to llvm::outs() rather than emitting
  // warnings, but this ensures things do not get filtered out by the rest of
  // the static analyzer machinery.
  llvm::outs().indent(Indentation);
  Call.dump(llvm::outs());
}
Пример #13
0
void CastSizeChecker::checkPreStmt(const CastExpr *CE,CheckerContext &C) const {
  const Expr *E = CE->getSubExpr();
  ASTContext &Ctx = C.getASTContext();
  QualType ToTy = Ctx.getCanonicalType(CE->getType());
  const PointerType *ToPTy = dyn_cast<PointerType>(ToTy.getTypePtr());

  if (!ToPTy)
    return;

  QualType ToPointeeTy = ToPTy->getPointeeType();

  // Only perform the check if 'ToPointeeTy' is a complete type.
  if (ToPointeeTy->isIncompleteType())
    return;

  ProgramStateRef state = C.getState();
  const MemRegion *R = state->getSVal(E, C.getLocationContext()).getAsRegion();
  if (!R)
    return;

  const SymbolicRegion *SR = dyn_cast<SymbolicRegion>(R);
  if (!SR)
    return;

  SValBuilder &svalBuilder = C.getSValBuilder();
  SVal extent = SR->getExtent(svalBuilder);
  const llvm::APSInt *extentInt = svalBuilder.getKnownValue(state, extent);
  if (!extentInt)
    return;

  CharUnits regionSize = CharUnits::fromQuantity(extentInt->getSExtValue());
  CharUnits typeSize = C.getASTContext().getTypeSizeInChars(ToPointeeTy);

  // Ignore void, and a few other un-sizeable types.
  if (typeSize.isZero())
    return;

  if (regionSize % typeSize == 0)
    return;

  if (evenFlexibleArraySize(Ctx, regionSize, typeSize, ToPointeeTy))
    return;

  if (ExplodedNode *errorNode = C.generateErrorNode()) {
    if (!BT)
      BT.reset(new BuiltinBug(this, "Cast region with wrong size.",
                                    "Cast a region whose size is not a multiple"
                                    " of the destination type size."));
    auto R = llvm::make_unique<BugReport>(*BT, BT->getDescription(), errorNode);
    R->addRange(CE->getSourceRange());
    C.emitReport(std::move(R));
  }
}
Пример #14
0
void ObjCAtSyncChecker::checkPreStmt(const ObjCAtSynchronizedStmt *S,
                                     CheckerContext &C) const {

  const Expr *Ex = S->getSynchExpr();
  ProgramStateRef state = C.getState();
  SVal V = state->getSVal(Ex, C.getLocationContext());

  // Uninitialized value used for the mutex?
  if (V.getAs<UndefinedVal>()) {
    if (ExplodedNode *N = C.generateSink()) {
      if (!BT_undef)
        BT_undef.reset(new BuiltinBug(this, "Uninitialized value used as mutex "
                                            "for @synchronized"));
      BugReport *report =
        new BugReport(*BT_undef, BT_undef->getDescription(), N);
      bugreporter::trackNullOrUndefValue(N, Ex, *report);
      C.emitReport(report);
    }
    return;
  }

  if (V.isUnknown())
    return;

  // Check for null mutexes.
  ProgramStateRef notNullState, nullState;
  llvm::tie(notNullState, nullState) = state->assume(V.castAs<DefinedSVal>());

  if (nullState) {
    if (!notNullState) {
      // Generate an error node.  This isn't a sink since
      // a null mutex just means no synchronization occurs.
      if (ExplodedNode *N = C.addTransition(nullState)) {
        if (!BT_null)
          BT_null.reset(new BuiltinBug(
              this, "Nil value used as mutex for @synchronized() "
                    "(no synchronization will occur)"));
        BugReport *report =
          new BugReport(*BT_null, BT_null->getDescription(), N);
        bugreporter::trackNullOrUndefValue(N, Ex, *report);

        C.emitReport(report);
        return;
      }
    }
    // Don't add a transition for 'nullState'.  If the value is
    // under-constrained to be null or non-null, assume it is non-null
    // afterwards.
  }

  if (notNullState)
    C.addTransition(notNullState);
}
Пример #15
0
/// If this is the beginning of -dealloc, mark the values initially stored in
/// instance variables that must be released by the end of -dealloc
/// as unreleased in the state.
void ObjCDeallocChecker::checkBeginFunction(
    CheckerContext &C) const {
  initIdentifierInfoAndSelectors(C.getASTContext());

  // Only do this if the current method is -dealloc.
  SVal SelfVal;
  if (!isInInstanceDealloc(C, SelfVal))
    return;

  SymbolRef SelfSymbol = SelfVal.getAsSymbol();

  const LocationContext *LCtx = C.getLocationContext();
  ProgramStateRef InitialState = C.getState();

  ProgramStateRef State = InitialState;

  SymbolSet::Factory &F = State->getStateManager().get_context<SymbolSet>();

  // Symbols that must be released by the end of the -dealloc;
  SymbolSet RequiredReleases = F.getEmptySet();

  // If we're an inlined -dealloc, we should add our symbols to the existing
  // set from our subclass.
  if (const SymbolSet *CurrSet = State->get<UnreleasedIvarMap>(SelfSymbol))
    RequiredReleases = *CurrSet;

  for (auto *PropImpl : getContainingObjCImpl(LCtx)->property_impls()) {
    ReleaseRequirement Requirement = getDeallocReleaseRequirement(PropImpl);
    if (Requirement != ReleaseRequirement::MustRelease)
      continue;

    SVal LVal = State->getLValue(PropImpl->getPropertyIvarDecl(), SelfVal);
    Optional<Loc> LValLoc = LVal.getAs<Loc>();
    if (!LValLoc)
      continue;

    SVal InitialVal = State->getSVal(LValLoc.getValue());
    SymbolRef Symbol = InitialVal.getAsSymbol();
    if (!Symbol || !isa<SymbolRegionValue>(Symbol))
      continue;

    // Mark the value as requiring a release.
    RequiredReleases = F.add(RequiredReleases, Symbol);
  }

  if (!RequiredReleases.isEmpty()) {
    State = State->set<UnreleasedIvarMap>(SelfSymbol, RequiredReleases);
  }

  if (State != InitialState) {
    C.addTransition(State);
  }
}
Пример #16
0
void IteratorChecker::checkPostStmt(const MaterializeTemporaryExpr *MTE,
                                    CheckerContext &C) const {
  /* Transfer iterator state to temporary objects */
  auto State = C.getState();
  const auto *LCtx = C.getLocationContext();
  const auto *Pos =
      getIteratorPosition(State, State->getSVal(MTE->GetTemporaryExpr(), LCtx));
  if (!Pos)
    return;
  State = setIteratorPosition(State, State->getSVal(MTE, LCtx), *Pos);
  C.addTransition(State);
}
Пример #17
0
/// Given the address expression, retrieve the value it's pointing to. Assume
/// that value is itself an address, and return the corresponding symbol.
static SymbolRef getAsPointeeSymbol(const Expr *Expr,
                                    CheckerContext &C) {
  const ProgramState *State = C.getState();
  SVal ArgV = State->getSVal(Expr, C.getLocationContext());

  if (const loc::MemRegionVal *X = dyn_cast<loc::MemRegionVal>(&ArgV)) {
    StoreManager& SM = C.getStoreManager();
    const MemRegion *V = SM.getBinding(State->getStore(), *X).getAsRegion();
    if (V)
      return getSymbolForRegion(C, V);
  }
  return 0;
}
Пример #18
0
/// Returns true if there is a call to -dealloc anywhere on the stack and false
/// otherwise. If true, it also sets InstanceValOut to the value of
/// 'self' in the frame for -dealloc.
bool ObjCDeallocChecker::instanceDeallocIsOnStack(const CheckerContext &C,
                                                  SVal &InstanceValOut) const {
  const LocationContext *LCtx = C.getLocationContext();

  while (LCtx) {
    if (isInInstanceDealloc(C, LCtx, InstanceValOut))
      return true;

    LCtx = LCtx->getParent();
  }

  return false;
}
Пример #19
0
/// Given the address expression, retrieve the value it's pointing to. Assume
/// that value is itself an address, and return the corresponding symbol.
static SymbolRef getAsPointeeSymbol(const Expr *Expr,
                                    CheckerContext &C) {
  ProgramStateRef State = C.getState();
  SVal ArgV = State->getSVal(Expr, C.getLocationContext());

  if (Optional<loc::MemRegionVal> X = ArgV.getAs<loc::MemRegionVal>()) {
    StoreManager& SM = C.getStoreManager();
    SymbolRef sym = SM.getBinding(State->getStore(), *X).getAsLocSymbol();
    if (sym)
      return sym;
  }
  return 0;
}
Пример #20
0
void DoubleFetchChecker::checkBind(SVal loc, SVal val,const Stmt *StoreE,CheckerContext &Ctx) const{

	ProgramStateRef state = Ctx.getState();
	std::cout<<"\n";

	unsigned int bloc = Ctx.getSourceManager().getExpansionLineNumber(StoreE->getLocEnd());
	std::cout<<"[checkBind] location: "<<bloc<<std::endl;

	const LocationContext *LC = Ctx.getLocationContext();
	const Decl *D = LC->getAnalysisDeclContext()->getDecl();
	const FunctionDecl *FD = dyn_cast<FunctionDecl>(D);
	std::string funcName = FD->getNameAsString();



	std::cout<<"[checkbind()]"<<" funcName is: "<<funcName<<std::endl;
	if(isValTainted(state,val)){
		std::cout<<"[checkbind()] tainted"<<"\tlocation is: "<<toStr(loc)<<"\tbind value is: "<<toStr(val)<<std::endl;
		unsigned int curTime = this->getCurTime(state);
		TaintList *tl = this->getTaintList(state, val);
		if(tl != NULL)
			tl->showTaints("--->");

		/* it is the value in loc that should be reference*/
		SymbolRef sr  = this->getSymbolRef(val);
		if (!sr){
			std::cout<<"[checkbind()]  SymbolRef failed!\n";
			return;
		}

		/*update locationMap.
		 * LocationMap, records when each local var is created.
		 */
		state = state->set<LocalVarAccessRecord>(sr,curTime);
		std::cout<<"--->add loc to LocalVarAccessRecord: SymbolRef is: "<<toStr(sr)<<"\t time is:"<<curTime<<std::endl;

		/*update timer of the checker, only when taint is passed to another expr */
		state = this->increTime(state);
		/*update program state*/
		Ctx.addTransition(state);

	}
	else
		std::cout<<"[checkbind()] untainted"<<"\tlocation is: "<<toStr(loc)<<"\tbind value is: "<<toStr(val)<<std::endl;






}
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());
    R->addVisitor(bugreporter::getTrackNullOrUndefValueVisitor(N, ex, R));
  }
  C.EmitReport(R);
}
Пример #22
0
static QualType parameterTypeFromSVal(SVal val, CheckerContext &C) {
  const StackFrameContext *
    SFC = C.getLocationContext()->getCurrentStackFrame();
  if (Optional<loc::MemRegionVal> X = val.getAs<loc::MemRegionVal>()) {
    const MemRegion* R = X->getRegion();
    if (const VarRegion *VR = R->getAs<VarRegion>())
      if (const StackArgumentsSpaceRegion *
          stackReg = dyn_cast<StackArgumentsSpaceRegion>(VR->getMemorySpace()))
        if (stackReg->getStackFrame() == SFC)
          return VR->getValueType();
  }

  return QualType();
}
void
UndefCapturedBlockVarChecker::checkPostStmt(const BlockExpr *BE,
                                            CheckerContext &C) const {
  if (!BE->getBlockDecl()->hasCaptures())
    return;

  ProgramStateRef state = C.getState();
  const BlockDataRegion *R =
    cast<BlockDataRegion>(state->getSVal(BE,
                                         C.getLocationContext()).getAsRegion());

  BlockDataRegion::referenced_vars_iterator I = R->referenced_vars_begin(),
                                            E = R->referenced_vars_end();

  for (; I != E; ++I) {
    // This VarRegion is the region associated with the block; we need
    // the one associated with the encompassing context.
    const VarRegion *VR = I.getCapturedRegion();
    const VarDecl *VD = VR->getDecl();

    if (VD->hasAttr<BlocksAttr>() || !VD->hasLocalStorage())
      continue;

    // Get the VarRegion associated with VD in the local stack frame.
    if (Optional<UndefinedVal> V =
          state->getSVal(I.getOriginalRegion()).getAs<UndefinedVal>()) {
      if (ExplodedNode *N = C.generateSink()) {
        if (!BT)
          BT.reset(
              new BuiltinBug(this, "uninitialized variable captured by block"));

        // Generate a bug report.
        SmallString<128> buf;
        llvm::raw_svector_ostream os(buf);

        os << "Variable '" << VD->getName()
           << "' is uninitialized when captured by block";

        BugReport *R = new BugReport(*BT, os.str(), N);
        if (const Expr *Ex = FindBlockDeclRefExpr(BE->getBody(), VD))
          R->addRange(Ex->getSourceRange());
        R->addVisitor(llvm::make_unique<FindLastStoreBRVisitor>(
            *V, VR, /*EnableNullFPSuppression*/ false));
        R->disablePathPruning();
        // need location of block
        C.emitReport(R);
      }
    }
  }
}
// Handle operator calls. First, if it is operator=, check the argument,
// and handle assigning and set target state appropriately. Otherwise, for
// other operators, check the args for bad iterators and handle comparisons.
void IteratorsChecker::checkPreStmt(const CXXOperatorCallExpr *OCE,
                                    CheckerContext &C) const
{
  const LocationContext *LC = C.getLocationContext();
  const ProgramState *state = C.getState();
  OverloadedOperatorKind Kind = OCE->getOperator();
  if (Kind == OO_Equal) {
    checkExpr(C, OCE->getArg(1));
    state = handleAssign(state, OCE->getArg(0), OCE->getArg(1), LC);
    C.addTransition(state);
    return;
  }
  else {
    checkArgs(C, OCE);
    // If it is a compare and both are iterators, ensure that they are for
    // the same container.
    if (Kind == OO_EqualEqual || Kind == OO_ExclaimEqual ||
        Kind == OO_Less || Kind == OO_LessEqual ||
        Kind == OO_Greater || Kind == OO_GreaterEqual) {
      const MemRegion *MR0, *MR1;
      MR0 = getRegion(state, OCE->getArg(0), LC);
      if (!MR0)
        return;
      MR1 = getRegion(state, OCE->getArg(1), LC);
      if (!MR1)
        return;
      const RefState *RS0, *RS1;
      RS0 = state->get<IteratorState>(MR0);
      if (!RS0)
        return;
      RS1 = state->get<IteratorState>(MR1);
      if (!RS1)
        return;
      if (RS0->getMemRegion() != RS1->getMemRegion()) {
      if (ExplodedNode *N = C.addTransition()) {
          if (!BT_Incompatible)
            const_cast<IteratorsChecker*>(this)->BT_Incompatible =
              new BuiltinBug(
                      "Cannot compare iterators from different containers");

          BugReport *R = new BugReport(*BT_Incompatible,
                                        BT_Incompatible->getDescription(), N);
          R->addRange(OCE->getSourceRange());
          C.EmitReport(R);
        }
      }
    }
  }
}
Пример #25
0
void UndefResultChecker::checkPostStmt(const BinaryOperator *B,
                                       CheckerContext &C) const {
  const ProgramState *state = C.getState();
  const LocationContext *LCtx = C.getLocationContext();
  if (state->getSVal(B, LCtx).isUndef()) {
    // Generate an error node.
    ExplodedNode *N = C.generateSink();
    if (!N)
      return;
    
    if (!BT)
      BT.reset(new BuiltinBug("Result of operation is garbage or undefined"));

    llvm::SmallString<256> sbuf;
    llvm::raw_svector_ostream OS(sbuf);
    const Expr *Ex = NULL;
    bool isLeft = true;
    
    if (state->getSVal(B->getLHS(), LCtx).isUndef()) {
      Ex = B->getLHS()->IgnoreParenCasts();
      isLeft = true;
    }
    else if (state->getSVal(B->getRHS(), LCtx).isUndef()) {
      Ex = B->getRHS()->IgnoreParenCasts();
      isLeft = false;
    }
    
    if (Ex) {
      OS << "The " << (isLeft ? "left" : "right")
         << " operand of '"
         << BinaryOperator::getOpcodeStr(B->getOpcode())
         << "' is a garbage value";
    }          
    else {
      // Neither operand was undefined, but the result is undefined.
      OS << "The result of the '"
         << BinaryOperator::getOpcodeStr(B->getOpcode())
         << "' expression is undefined";
    }
    BugReport *report = new BugReport(*BT, OS.str(), N);
    if (Ex) {
      report->addRange(Ex->getSourceRange());
      report->addVisitor(bugreporter::getTrackNullOrUndefValueVisitor(N, Ex));
    }
    else
      report->addVisitor(bugreporter::getTrackNullOrUndefValueVisitor(N, B));
    C.EmitReport(report);
  }
}
Пример #26
0
void IteratorChecker::assignToContainer(CheckerContext &C, const Expr *CE,
                                        const SVal &RetVal,
                                        const MemRegion *Cont) const {
  while (const auto *CBOR = Cont->getAs<CXXBaseObjectRegion>()) {
    Cont = CBOR->getSuperRegion();
  }

  auto State = C.getState();
  auto &SymMgr = C.getSymbolManager();
  auto Sym = SymMgr.conjureSymbol(CE, C.getLocationContext(),
                                  C.getASTContext().LongTy, C.blockCount());
  State = setIteratorPosition(State, RetVal,
                              IteratorPosition::getPosition(Cont, Sym));
  C.addTransition(State);
}
Пример #27
0
void TaintTesterChecker::checkPostStmt(const Expr *E,
                                       CheckerContext &C) const {
  ProgramStateRef State = C.getState();
  if (!State)
    return;

  if (State->isTainted(E, C.getLocationContext())) {
    if (ExplodedNode *N = C.generateNonFatalErrorNode()) {
      initBugType();
      auto report = llvm::make_unique<BugReport>(*BT, "tainted",N);
      report->addRange(E->getSourceRange());
      C.emitReport(std::move(report));
    }
  }
}
Пример #28
0
void TaintTesterChecker::checkPostStmt(const Expr *E,
                                       CheckerContext &C) const {
  ProgramStateRef State = C.getState();
  if (!State)
    return;

  if (State->isTainted(E, C.getLocationContext())) {
    if (ExplodedNode *N = C.addTransition()) {
      initBugType();
      BugReport *report = new BugReport(*BT, "tainted",N);
      report->addRange(E->getSourceRange());
      C.emitReport(report);
    }
  }
}
Пример #29
0
Optional<SVal> GenericTaintChecker::getPointedToSVal(CheckerContext &C,
                                            const Expr* Arg) {
  ProgramStateRef State = C.getState();
  SVal AddrVal = State->getSVal(Arg->IgnoreParens(), C.getLocationContext());
  if (AddrVal.isUnknownOrUndef())
    return None;

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

  const PointerType *ArgTy =
    dyn_cast<PointerType>(Arg->getType().getCanonicalType().getTypePtr());
  return State->getSVal(*AddrLoc, ArgTy ? ArgTy->getPointeeType(): QualType());
}
Пример #30
0
// If argument 0(protocol domain) is network, the return value should get taint.
ProgramStateRef GenericTaintChecker::postSocket(const CallExpr *CE,
                                                CheckerContext &C) const {
  ProgramStateRef State = C.getState();
  if (CE->getNumArgs() < 3)
    return State;

  SourceLocation DomLoc = CE->getArg(0)->getExprLoc();
  StringRef DomName = C.getMacroNameOrSpelling(DomLoc);
  // White list the internal communication protocols.
  if (DomName.equals("AF_SYSTEM") || DomName.equals("AF_LOCAL") ||
      DomName.equals("AF_UNIX") || DomName.equals("AF_RESERVED_36"))
    return State;
  State = State->addTaint(CE, C.getLocationContext());
  return State;
}