void ExprEngine::VisitCompoundLiteralExpr(const CompoundLiteralExpr *CL, ExplodedNode *Pred, ExplodedNodeSet &Dst) { StmtNodeBuilder B(Pred, Dst, *currBldrCtx); const InitListExpr *ILE = cast<InitListExpr>(CL->getInitializer()->IgnoreParens()); ProgramStateRef state = Pred->getState(); SVal ILV = state->getSVal(ILE, Pred->getLocationContext()); const LocationContext *LC = Pred->getLocationContext(); state = state->bindCompoundLiteral(CL, LC, ILV); // Compound literal expressions are a GNU extension in C++. // Unlike in C, where CLs are lvalues, in C++ CLs are prvalues, // and like temporary objects created by the functional notation T() // CLs are destroyed at the end of the containing full-expression. // HOWEVER, an rvalue of array type is not something the analyzer can // reason about, since we expect all regions to be wrapped in Locs. // So we treat array CLs as lvalues as well, knowing that they will decay // to pointers as soon as they are used. if (CL->isGLValue() || CL->getType()->isArrayType()) B.generateNode(CL, Pred, state->BindExpr(CL, LC, state->getLValue(CL, LC))); else B.generateNode(CL, Pred, state->BindExpr(CL, LC, ILV)); }
ProgramStateRef ExprEngine::bindReturnValue(const CallEvent &Call, const LocationContext *LCtx, ProgramStateRef State) { const Expr *E = Call.getOriginExpr(); if (!E) return State; // Some method families have known return values. if (const ObjCMethodCall *Msg = dyn_cast<ObjCMethodCall>(&Call)) { switch (Msg->getMethodFamily()) { default: break; case OMF_autorelease: case OMF_retain: case OMF_self: { // These methods return their receivers. return State->BindExpr(E, LCtx, Msg->getReceiverSVal()); } } } else if (const CXXConstructorCall *C = dyn_cast<CXXConstructorCall>(&Call)){ return State->BindExpr(E, LCtx, C->getCXXThisVal()); } // Conjure a symbol if the return value is unknown. QualType ResultTy = Call.getResultType(); SValBuilder &SVB = getSValBuilder(); unsigned Count = currBldrCtx->blockCount(); SVal R = SVB.conjureSymbolVal(0, E, LCtx, ResultTy, Count); return State->BindExpr(E, LCtx, R); }
void CallAndMessageChecker::HandleNilReceiver(CheckerContext &C, ProgramStateRef state, const ObjCMethodCall &Msg) const { ASTContext &Ctx = C.getASTContext(); static CheckerProgramPointTag Tag(this, "NilReceiver"); // Check the return type of the message expression. A message to nil will // return different values depending on the return type and the architecture. QualType RetTy = Msg.getResultType(); CanQualType CanRetTy = Ctx.getCanonicalType(RetTy); const LocationContext *LCtx = C.getLocationContext(); if (CanRetTy->isStructureOrClassType()) { // Structure returns are safe since the compiler zeroes them out. SVal V = C.getSValBuilder().makeZeroVal(RetTy); C.addTransition(state->BindExpr(Msg.getOriginExpr(), LCtx, V), &Tag); return; } // Other cases: check if sizeof(return type) > sizeof(void*) if (CanRetTy != Ctx.VoidTy && C.getLocationContext()->getParentMap() .isConsumedExpr(Msg.getOriginExpr())) { // Compute: sizeof(void *) and sizeof(return type) const uint64_t voidPtrSize = Ctx.getTypeSize(Ctx.VoidPtrTy); const uint64_t returnTypeSize = Ctx.getTypeSize(CanRetTy); if (CanRetTy.getTypePtr()->isReferenceType()|| (voidPtrSize < returnTypeSize && !(supportsNilWithFloatRet(Ctx.getTargetInfo().getTriple()) && (Ctx.FloatTy == CanRetTy || Ctx.DoubleTy == CanRetTy || Ctx.LongDoubleTy == CanRetTy || Ctx.LongLongTy == CanRetTy || Ctx.UnsignedLongLongTy == CanRetTy)))) { if (ExplodedNode *N = C.generateSink(state, nullptr, &Tag)) emitNilReceiverBug(C, Msg, N); return; } // Handle the safe cases where the return value is 0 if the // receiver is nil. // // FIXME: For now take the conservative approach that we only // return null values if we *know* that the receiver is nil. // This is because we can have surprises like: // // ... = [[NSScreens screens] objectAtIndex:0]; // // What can happen is that [... screens] could return nil, but // it most likely isn't nil. We should assume the semantics // of this case unless we have *a lot* more knowledge. // SVal V = C.getSValBuilder().makeZeroVal(RetTy); C.addTransition(state->BindExpr(Msg.getOriginExpr(), LCtx, V), &Tag); return; } C.addTransition(state); }
void ExprEngine::processCallExit(ExplodedNode *Pred) { ProgramStateRef state = Pred->getState(); const StackFrameContext *calleeCtx = Pred->getLocationContext()->getCurrentStackFrame(); const LocationContext *callerCtx = calleeCtx->getParent(); const Stmt *CE = calleeCtx->getCallSite(); // If the callee returns an expression, bind its value to CallExpr. if (const ReturnStmt *RS = getReturnStmt(Pred)) { const LocationContext *LCtx = Pred->getLocationContext(); SVal V = state->getSVal(RS, LCtx); state = state->BindExpr(CE, callerCtx, V); } // Bind the constructed object value to CXXConstructExpr. if (const CXXConstructExpr *CCE = dyn_cast<CXXConstructExpr>(CE)) { const CXXThisRegion *ThisR = getCXXThisRegion(CCE->getConstructor()->getParent(), calleeCtx); SVal ThisV = state->getSVal(ThisR); // Always bind the region to the CXXConstructExpr. state = state->BindExpr(CCE, Pred->getLocationContext(), ThisV); } static SimpleProgramPointTag returnTag("ExprEngine : Call Return"); PostStmt Loc(CE, callerCtx, &returnTag); bool isNew; ExplodedNode *N = G.getNode(Loc, state, false, &isNew); N->addPredecessor(Pred, G); if (!isNew) return; // Perform the post-condition check of the CallExpr. ExplodedNodeSet Dst; NodeBuilderContext Ctx(Engine, calleeCtx->getCallSiteBlock(), N); SaveAndRestore<const NodeBuilderContext*> NBCSave(currentBuilderContext, &Ctx); SaveAndRestore<unsigned> CBISave(currentStmtIdx, calleeCtx->getIndex()); getCheckerManager().runCheckersForPostStmt(Dst, N, CE, *this, /* wasInlined */ true); // Enqueue the next element in the block. for (ExplodedNodeSet::iterator I = Dst.begin(), E = Dst.end(); I != E; ++I) { Engine.getWorkList()->enqueue(*I, calleeCtx->getCallSiteBlock(), calleeCtx->getIndex()+1); } }
ProgramStateRef ExprEngine::bindReturnValue(const CallEvent &Call, const LocationContext *LCtx, ProgramStateRef State) { const Expr *E = Call.getOriginExpr(); if (!E) return State; // Some method families have known return values. if (const ObjCMethodCall *Msg = dyn_cast<ObjCMethodCall>(&Call)) { switch (Msg->getMethodFamily()) { default: break; case OMF_autorelease: case OMF_retain: case OMF_self: { // These methods return their receivers. return State->BindExpr(E, LCtx, Msg->getReceiverSVal()); } } } else if (const CXXConstructorCall *C = dyn_cast<CXXConstructorCall>(&Call)){ SVal ThisV = C->getCXXThisVal(); // If the constructed object is a temporary prvalue, get its bindings. if (isTemporaryPRValue(cast<CXXConstructExpr>(E), ThisV)) ThisV = State->getSVal(ThisV.castAs<Loc>()); return State->BindExpr(E, LCtx, ThisV); } // Conjure a symbol if the return value is unknown. QualType ResultTy = Call.getResultType(); SValBuilder &SVB = getSValBuilder(); unsigned Count = currBldrCtx->blockCount(); // See if we need to conjure a heap pointer instead of // a regular unknown pointer. bool IsHeapPointer = false; if (const auto *CNE = dyn_cast<CXXNewExpr>(E)) if (CNE->getOperatorNew()->isReplaceableGlobalAllocationFunction()) { // FIXME: Delegate this to evalCall in MallocChecker? IsHeapPointer = true; } SVal R = IsHeapPointer ? SVB.getConjuredHeapSymbolVal(E, LCtx, Count) : SVB.conjureSymbolVal(nullptr, E, LCtx, ResultTy, Count); return State->BindExpr(E, LCtx, R); }
bool BuiltinFunctionChecker::evalCall(const CallExpr *CE, CheckerContext &C) const { ProgramStateRef state = C.getState(); const FunctionDecl *FD = C.getCalleeDecl(CE); const LocationContext *LCtx = C.getLocationContext(); if (!FD) return false; unsigned id = FD->getBuiltinID(); if (!id) return false; switch (id) { case Builtin::BI__builtin_expect: { // For __builtin_expect, just return the value of the subexpression. assert (CE->arg_begin() != CE->arg_end()); SVal X = state->getSVal(*(CE->arg_begin()), LCtx); C.addTransition(state->BindExpr(CE, LCtx, X)); return true; } case Builtin::BI__builtin_alloca: { // FIXME: Refactor into StoreManager itself? MemRegionManager& RM = C.getStoreManager().getRegionManager(); const AllocaRegion* R = RM.getAllocaRegion(CE, C.blockCount(), C.getLocationContext()); // Set the extent of the region in bytes. This enables us to use the // SVal of the argument directly. If we save the extent in bits, we // cannot represent values like symbol*8. DefinedOrUnknownSVal Size = state->getSVal(*(CE->arg_begin()), LCtx).castAs<DefinedOrUnknownSVal>(); SValBuilder& svalBuilder = C.getSValBuilder(); DefinedOrUnknownSVal Extent = R->getExtent(svalBuilder); DefinedOrUnknownSVal extentMatchesSizeArg = svalBuilder.evalEQ(state, Extent, Size); state = state->assume(extentMatchesSizeArg, true); assert(state && "The region should not have any previous constraints"); C.addTransition(state->BindExpr(CE, LCtx, loc::MemRegionVal(R))); return true; } } return false; }
void ExprEngine::VisitInitListExpr(const InitListExpr *IE, ExplodedNode *Pred, ExplodedNodeSet &Dst) { StmtNodeBuilder B(Pred, Dst, *currBldrCtx); ProgramStateRef state = Pred->getState(); const LocationContext *LCtx = Pred->getLocationContext(); QualType T = getContext().getCanonicalType(IE->getType()); unsigned NumInitElements = IE->getNumInits(); if (!IE->isGLValue() && (T->isArrayType() || T->isRecordType() || T->isVectorType() || T->isAnyComplexType())) { llvm::ImmutableList<SVal> vals = getBasicVals().getEmptySValList(); // Handle base case where the initializer has no elements. // e.g: static int* myArray[] = {}; if (NumInitElements == 0) { SVal V = svalBuilder.makeCompoundVal(T, vals); B.generateNode(IE, Pred, state->BindExpr(IE, LCtx, V)); return; } for (InitListExpr::const_reverse_iterator it = IE->rbegin(), ei = IE->rend(); it != ei; ++it) { SVal V = state->getSVal(cast<Expr>(*it), LCtx); vals = getBasicVals().prependSVal(V, vals); } B.generateNode(IE, Pred, state->BindExpr(IE, LCtx, svalBuilder.makeCompoundVal(T, vals))); return; } // Handle scalars: int{5} and int{} and GLvalues. // Note, if the InitListExpr is a GLvalue, it means that there is an address // representing it, so it must have a single init element. assert(NumInitElements <= 1); SVal V; if (NumInitElements == 0) V = getSValBuilder().makeZeroVal(T); else V = state->getSVal(IE->getInit(0), LCtx); B.generateNode(IE, Pred, state->BindExpr(IE, LCtx, V)); }
void ExprEngine::defaultEvalCall(ExplodedNodeSet &Dst, ExplodedNode *Pred, const CallEvent &Call) { // Try to inline the call. ProgramStateRef state = 0; const Expr *E = Call.getOriginExpr(); if (E) { state = getInlineFailedState(Pred, E); if (state == 0 && inlineCall(Dst, Call, Pred)) return; } // If we can't inline it, handle the return value and invalidate the regions. StmtNodeBuilder Bldr(Pred, Dst, *currentBuilderContext); // Invalidate any regions touched by the call. unsigned Count = currentBuilderContext->getCurrentBlockCount(); if (state == 0) state = Pred->getState(); state = Call.invalidateRegions(Count, state); // Conjure a symbol value to use as the result. assert(Call.getOriginExpr() && "Must have an expression to bind the result"); QualType ResultTy = Call.getResultType(); SValBuilder &SVB = getSValBuilder(); const LocationContext *LCtx = Pred->getLocationContext(); SVal RetVal = SVB.getConjuredSymbolVal(0, Call.getOriginExpr(), LCtx, ResultTy, Count); // And make the result node. state = state->BindExpr(Call.getOriginExpr(), LCtx, RetVal); Bldr.generateNode(Call.getOriginExpr(), Pred, state); }
void StreamChecker::OpenFileAux(CheckerContext &C, const CallExpr *CE) const { ProgramStateRef state = C.getState(); SValBuilder &svalBuilder = C.getSValBuilder(); const LocationContext *LCtx = C.getPredecessor()->getLocationContext(); DefinedSVal RetVal = svalBuilder.conjureSymbolVal(nullptr, CE, LCtx, C.blockCount()) .castAs<DefinedSVal>(); state = state->BindExpr(CE, C.getLocationContext(), RetVal); ConstraintManager &CM = C.getConstraintManager(); // Bifurcate the state into two: one with a valid FILE* pointer, the other // with a NULL. ProgramStateRef stateNotNull, stateNull; std::tie(stateNotNull, stateNull) = CM.assumeDual(state, RetVal); if (SymbolRef Sym = RetVal.getAsSymbol()) { // if RetVal is not NULL, set the symbol's state to Opened. stateNotNull = stateNotNull->set<StreamMap>(Sym,StreamState::getOpened(CE)); stateNull = stateNull->set<StreamMap>(Sym, StreamState::getOpenFailed(CE)); C.addTransition(stateNotNull); C.addTransition(stateNull); } }
void ExprEngine::defaultEvalCall(ExplodedNodeSet &Dst, ExplodedNode *Pred, const CallEvent &Call) { // Try to inline the call. // The origin expression here is just used as a kind of checksum; // for CallEvents that do not have origin expressions, this should still be // safe. const Expr *E = Call.getOriginExpr(); ProgramStateRef state = getInlineFailedState(Pred, E); if (state == 0 && inlineCall(Dst, Call, Pred)) return; // If we can't inline it, handle the return value and invalidate the regions. NodeBuilder Bldr(Pred, Dst, *currentBuilderContext); // Invalidate any regions touched by the call. unsigned Count = currentBuilderContext->getCurrentBlockCount(); if (state == 0) state = Pred->getState(); state = Call.invalidateRegions(Count, state); // Conjure a symbol value to use as the result. if (E) { QualType ResultTy = Call.getResultType(); SValBuilder &SVB = getSValBuilder(); const LocationContext *LCtx = Pred->getLocationContext(); SVal RetVal = SVB.getConjuredSymbolVal(0, E, LCtx, ResultTy, Count); state = state->BindExpr(E, LCtx, RetVal); } // And make the result node. Bldr.generateNode(Call.getProgramPoint(), state, Pred); }
void ExprEngine::CreateCXXTemporaryObject(const MaterializeTemporaryExpr *ME, ExplodedNode *Pred, ExplodedNodeSet &Dst) { StmtNodeBuilder Bldr(Pred, Dst, *currBldrCtx); const Expr *tempExpr = ME->GetTemporaryExpr()->IgnoreParens(); ProgramStateRef state = Pred->getState(); const LocationContext *LCtx = Pred->getLocationContext(); // Bind the temporary object to the value of the expression. Then bind // the expression to the location of the object. SVal V = state->getSVal(tempExpr, LCtx); // If the value is already a CXXTempObjectRegion, it is fine as it is. // Otherwise, create a new CXXTempObjectRegion, and copy the value into it. const MemRegion *MR = V.getAsRegion(); if (!MR || !isa<CXXTempObjectRegion>(MR)) { const MemRegion *R = svalBuilder.getRegionManager().getCXXTempObjectRegion(ME, LCtx); SVal L = loc::MemRegionVal(R); state = state->bindLoc(L, V); V = L; } Bldr.generateNode(ME, Pred, state->BindExpr(ME, LCtx, V)); }
void ExprEngine:: VisitUnaryExprOrTypeTraitExpr(const UnaryExprOrTypeTraitExpr *Ex, ExplodedNode *Pred, ExplodedNodeSet &Dst) { StmtNodeBuilder Bldr(Pred, Dst, *currBldrCtx); QualType T = Ex->getTypeOfArgument(); if (Ex->getKind() == UETT_SizeOf) { if (!T->isIncompleteType() && !T->isConstantSizeType()) { assert(T->isVariableArrayType() && "Unknown non-constant-sized type."); // FIXME: Add support for VLA type arguments and VLA expressions. // When that happens, we should probably refactor VLASizeChecker's code. return; } else if (T->getAs<ObjCObjectType>()) { // Some code tries to take the sizeof an ObjCObjectType, relying that // the compiler has laid out its representation. Just report Unknown // for these. return; } } APSInt Value = Ex->EvaluateKnownConstInt(getContext()); CharUnits amt = CharUnits::fromQuantity(Value.getZExtValue()); ProgramStateRef state = Pred->getState(); state = state->BindExpr(Ex, Pred->getLocationContext(), svalBuilder.makeIntVal(amt.getQuantity(), Ex->getType())); Bldr.generateNode(Ex, Pred, state); }
void ExprEngine::CreateCXXTemporaryObject(const MaterializeTemporaryExpr *ME, ExplodedNode *Pred, ExplodedNodeSet &Dst) { StmtNodeBuilder Bldr(Pred, Dst, *currBldrCtx); const Expr *tempExpr = ME->GetTemporaryExpr()->IgnoreParens(); ProgramStateRef state = Pred->getState(); const LocationContext *LCtx = Pred->getLocationContext(); // Bind the temporary object to the value of the expression. Then bind // the expression to the location of the object. SVal V = state->getSVal(tempExpr, LCtx); // If the object is a record, the constructor will have already created // a temporary object region. If it is not, we need to copy the value over. if (!ME->getType()->isRecordType()) { const MemRegion *R = svalBuilder.getRegionManager().getCXXTempObjectRegion(ME, LCtx); SVal L = loc::MemRegionVal(R); state = state->bindLoc(L, V); V = L; } Bldr.generateNode(ME, Pred, state->BindExpr(ME, LCtx, V)); }
void ExprEngine::VisitCompoundLiteralExpr(const CompoundLiteralExpr *CL, ExplodedNode *Pred, ExplodedNodeSet &Dst) { StmtNodeBuilder B(Pred, Dst, *currBldrCtx); ProgramStateRef State = Pred->getState(); const LocationContext *LCtx = Pred->getLocationContext(); const Expr *Init = CL->getInitializer(); SVal V = State->getSVal(CL->getInitializer(), LCtx); if (isa<CXXConstructExpr>(Init)) { // No work needed. Just pass the value up to this expression. } else { assert(isa<InitListExpr>(Init)); Loc CLLoc = State->getLValue(CL, LCtx); State = State->bindLoc(CLLoc, V); // Compound literal expressions are a GNU extension in C++. // Unlike in C, where CLs are lvalues, in C++ CLs are prvalues, // and like temporary objects created by the functional notation T() // CLs are destroyed at the end of the containing full-expression. // HOWEVER, an rvalue of array type is not something the analyzer can // reason about, since we expect all regions to be wrapped in Locs. // So we treat array CLs as lvalues as well, knowing that they will decay // to pointers as soon as they are used. if (CL->isGLValue() || CL->getType()->isArrayType()) V = CLLoc; } B.generateNode(CL, Pred, State->BindExpr(CL, LCtx, V)); }
void ExprEngine::VisitGuardedExpr(const Expr *Ex, const Expr *L, const Expr *R, ExplodedNode *Pred, ExplodedNodeSet &Dst) { assert(L && R); StmtNodeBuilder B(Pred, Dst, *currBldrCtx); ProgramStateRef state = Pred->getState(); const LocationContext *LCtx = Pred->getLocationContext(); const CFGBlock *SrcBlock = 0; // Find the predecessor block. ProgramStateRef SrcState = state; for (const ExplodedNode *N = Pred ; N ; N = *N->pred_begin()) { ProgramPoint PP = N->getLocation(); if (PP.getAs<PreStmtPurgeDeadSymbols>() || PP.getAs<BlockEntrance>()) { assert(N->pred_size() == 1); continue; } SrcBlock = PP.castAs<BlockEdge>().getSrc(); SrcState = N->getState(); break; } assert(SrcBlock && "missing function entry"); // Find the last expression in the predecessor block. That is the // expression that is used for the value of the ternary expression. bool hasValue = false; SVal V; for (CFGBlock::const_reverse_iterator I = SrcBlock->rbegin(), E = SrcBlock->rend(); I != E; ++I) { CFGElement CE = *I; if (Optional<CFGStmt> CS = CE.getAs<CFGStmt>()) { const Expr *ValEx = cast<Expr>(CS->getStmt()); ValEx = ValEx->IgnoreParens(); // For GNU extension '?:' operator, the left hand side will be an // OpaqueValueExpr, so get the underlying expression. if (const OpaqueValueExpr *OpaqueEx = dyn_cast<OpaqueValueExpr>(L)) L = OpaqueEx->getSourceExpr(); // If the last expression in the predecessor block matches true or false // subexpression, get its the value. if (ValEx == L->IgnoreParens() || ValEx == R->IgnoreParens()) { hasValue = true; V = SrcState->getSVal(ValEx, LCtx); } break; } } if (!hasValue) V = svalBuilder.conjureSymbolVal(0, Ex, LCtx, currBldrCtx->blockCount()); // Generate a new node with the binding from the appropriate path. B.generateNode(Ex, Pred, state->BindExpr(Ex, LCtx, V, true)); }
void ExprEngine::VisitInitListExpr(const InitListExpr *IE, ExplodedNode *Pred, ExplodedNodeSet &Dst) { StmtNodeBuilder B(Pred, Dst, *currBldrCtx); ProgramStateRef state = Pred->getState(); const LocationContext *LCtx = Pred->getLocationContext(); QualType T = getContext().getCanonicalType(IE->getType()); unsigned NumInitElements = IE->getNumInits(); if (T->isArrayType() || T->isRecordType() || T->isVectorType() || T->isAnyComplexType()) { llvm::ImmutableList<SVal> vals = getBasicVals().getEmptySValList(); // Handle base case where the initializer has no elements. // e.g: static int* myArray[] = {}; if (NumInitElements == 0) { SVal V = svalBuilder.makeCompoundVal(T, vals); B.generateNode(IE, Pred, state->BindExpr(IE, LCtx, V)); return; } for (InitListExpr::const_reverse_iterator it = IE->rbegin(), ei = IE->rend(); it != ei; ++it) { SVal V = state->getSVal(cast<Expr>(*it), LCtx); if (dyn_cast_or_null<CXXTempObjectRegion>(V.getAsRegion())) V = UnknownVal(); vals = getBasicVals().consVals(V, vals); } B.generateNode(IE, Pred, state->BindExpr(IE, LCtx, svalBuilder.makeCompoundVal(T, vals))); return; } // Handle scalars: int{5} and int{}. assert(NumInitElements <= 1); SVal V; if (NumInitElements == 0) V = getSValBuilder().makeZeroVal(T); else V = state->getSVal(IE->getInit(0), LCtx); B.generateNode(IE, Pred, state->BindExpr(IE, LCtx, V)); }
void ExprEngine::VisitCXXNewExpr(const CXXNewExpr *CNE, ExplodedNode *Pred, ExplodedNodeSet &Dst) { // FIXME: Much of this should eventually migrate to CXXAllocatorCall. // Also, we need to decide how allocators actually work -- they're not // really part of the CXXNewExpr because they happen BEFORE the // CXXConstructExpr subexpression. See PR12014 for some discussion. StmtNodeBuilder Bldr(Pred, Dst, *currentBuilderContext); unsigned blockCount = currentBuilderContext->getCurrentBlockCount(); const LocationContext *LCtx = Pred->getLocationContext(); DefinedOrUnknownSVal symVal = svalBuilder.getConjuredSymbolVal(0, CNE, LCtx, CNE->getType(), blockCount); ProgramStateRef State = Pred->getState(); // Invalidate placement args. CXXAllocatorCall Call(CNE, State, LCtx); State = Call.invalidateRegions(blockCount); if (CNE->isArray()) { // FIXME: allocating an array requires simulating the constructors. // For now, just return a symbolicated region. const MemRegion *NewReg = cast<loc::MemRegionVal>(symVal).getRegion(); QualType ObjTy = CNE->getType()->getAs<PointerType>()->getPointeeType(); const ElementRegion *EleReg = getStoreManager().GetElementZeroRegion(NewReg, ObjTy); State = State->BindExpr(CNE, Pred->getLocationContext(), loc::MemRegionVal(EleReg)); Bldr.generateNode(CNE, Pred, State); return; } // FIXME: Once we have proper support for CXXConstructExprs inside // CXXNewExpr, we need to make sure that the constructed object is not // immediately invalidated here. (The placement call should happen before // the constructor call anyway.) FunctionDecl *FD = CNE->getOperatorNew(); if (FD && FD->isReservedGlobalPlacementOperator()) { // Non-array placement new should always return the placement location. SVal PlacementLoc = State->getSVal(CNE->getPlacementArg(0), LCtx); State = State->BindExpr(CNE, LCtx, PlacementLoc); } else { State = State->BindExpr(CNE, LCtx, symVal); } Bldr.generateNode(CNE, Pred, State); }
// FIXME: This is the sort of code that should eventually live in a Core // checker rather than as a special case in ExprEngine. void ExprEngine::performTrivialCopy(NodeBuilder &Bldr, ExplodedNode *Pred, const CallEvent &Call) { SVal ThisVal; bool AlwaysReturnsLValue; const CXXRecordDecl *ThisRD = nullptr; if (const CXXConstructorCall *Ctor = dyn_cast<CXXConstructorCall>(&Call)) { assert(Ctor->getDecl()->isTrivial()); assert(Ctor->getDecl()->isCopyOrMoveConstructor()); ThisVal = Ctor->getCXXThisVal(); ThisRD = Ctor->getDecl()->getParent(); AlwaysReturnsLValue = false; } else { assert(cast<CXXMethodDecl>(Call.getDecl())->isTrivial()); assert(cast<CXXMethodDecl>(Call.getDecl())->getOverloadedOperator() == OO_Equal); ThisVal = cast<CXXInstanceCall>(Call).getCXXThisVal(); ThisRD = cast<CXXMethodDecl>(Call.getDecl())->getParent(); AlwaysReturnsLValue = true; } assert(ThisRD); if (ThisRD->isEmpty()) { // Do nothing for empty classes. Otherwise it'd retrieve an UnknownVal // and bind it and RegionStore would think that the actual value // in this region at this offset is unknown. return; } const LocationContext *LCtx = Pred->getLocationContext(); ExplodedNodeSet Dst; Bldr.takeNodes(Pred); SVal V = Call.getArgSVal(0); // If the value being copied is not unknown, load from its location to get // an aggregate rvalue. if (Optional<Loc> L = V.getAs<Loc>()) V = Pred->getState()->getSVal(*L); else assert(V.isUnknownOrUndef()); const Expr *CallExpr = Call.getOriginExpr(); evalBind(Dst, CallExpr, Pred, ThisVal, V, true); PostStmt PS(CallExpr, LCtx); for (ExplodedNodeSet::iterator I = Dst.begin(), E = Dst.end(); I != E; ++I) { ProgramStateRef State = (*I)->getState(); if (AlwaysReturnsLValue) State = State->BindExpr(CallExpr, LCtx, ThisVal); else State = bindReturnValue(Call, LCtx, State); Bldr.generateNode(PS, State, *I); } }
void ExprEngine::VisitLambdaExpr(const LambdaExpr *LE, ExplodedNode *Pred, ExplodedNodeSet &Dst) { const LocationContext *LocCtxt = Pred->getLocationContext(); // Get the region of the lambda itself. const MemRegion *R = svalBuilder.getRegionManager().getCXXTempObjectRegion( LE, LocCtxt); SVal V = loc::MemRegionVal(R); ProgramStateRef State = Pred->getState(); // If we created a new MemRegion for the lambda, we should explicitly bind // the captures. CXXRecordDecl::field_iterator CurField = LE->getLambdaClass()->field_begin(); for (LambdaExpr::const_capture_init_iterator i = LE->capture_init_begin(), e = LE->capture_init_end(); i != e; ++i, ++CurField) { FieldDecl *FieldForCapture = *CurField; SVal FieldLoc = State->getLValue(FieldForCapture, V); SVal InitVal; if (!FieldForCapture->hasCapturedVLAType()) { Expr *InitExpr = *i; assert(InitExpr && "Capture missing initialization expression"); InitVal = State->getSVal(InitExpr, LocCtxt); } else { // The field stores the length of a captured variable-length array. // These captures don't have initialization expressions; instead we // get the length from the VLAType size expression. Expr *SizeExpr = FieldForCapture->getCapturedVLAType()->getSizeExpr(); InitVal = State->getSVal(SizeExpr, LocCtxt); } State = State->bindLoc(FieldLoc, InitVal); } // Decay the Loc into an RValue, because there might be a // MaterializeTemporaryExpr node above this one which expects the bound value // to be an RValue. SVal LambdaRVal = State->getSVal(R); ExplodedNodeSet Tmp; StmtNodeBuilder Bldr(Pred, Tmp, *currBldrCtx); // FIXME: is this the right program point kind? Bldr.generateNode(LE, Pred, State->BindExpr(LE, LocCtxt, LambdaRVal), nullptr, ProgramPoint::PostLValueKind); // FIXME: Move all post/pre visits to ::Visit(). getCheckerManager().runCheckersForPostStmt(Dst, Tmp, LE, *this); }
ProgramStateRef ExprEngine::handleLVectorSplat( ProgramStateRef state, const LocationContext* LCtx, const CastExpr* CastE, StmtNodeBuilder &Bldr, ExplodedNode* Pred) { // Recover some path sensitivity by conjuring a new value. QualType resultType = CastE->getType(); if (CastE->isGLValue()) resultType = getContext().getPointerType(resultType); SVal result = svalBuilder.conjureSymbolVal(nullptr, CastE, LCtx, resultType, currBldrCtx->blockCount()); state = state->BindExpr(CastE, LCtx, result); Bldr.generateNode(CastE, Pred, state); return state; }
void ExprEngine::VisitCXXThisExpr(const CXXThisExpr *TE, ExplodedNode *Pred, ExplodedNodeSet &Dst) { StmtNodeBuilder Bldr(Pred, Dst, *currBldrCtx); // Get the this object region from StoreManager. const LocationContext *LCtx = Pred->getLocationContext(); const MemRegion *R = svalBuilder.getRegionManager().getCXXThisRegion( getContext().getCanonicalType(TE->getType()), LCtx); ProgramStateRef state = Pred->getState(); SVal V = state->getSVal(loc::MemRegionVal(R)); Bldr.generateNode(TE, Pred, state->BindExpr(TE, LCtx, V)); }
ProgramStateRef ExprEngine::handleLValueBitCast( ProgramStateRef state, const Expr* Ex, const LocationContext* LCtx, QualType T, QualType ExTy, const CastExpr* CastE, StmtNodeBuilder& Bldr, ExplodedNode* Pred) { // Delegate to SValBuilder to process. SVal V = state->getSVal(Ex, LCtx); V = svalBuilder.evalCast(V, T, ExTy); // Negate the result if we're treating the boolean as a signed i1 if (CastE->getCastKind() == CK_BooleanToSignedIntegral) V = evalMinus(V); state = state->BindExpr(CastE, LCtx, V); Bldr.generateNode(CastE, Pred, state); return state; }
void ExprEngine::VisitLvalObjCIvarRefExpr(const ObjCIvarRefExpr *Ex, ExplodedNode *Pred, ExplodedNodeSet &Dst) { ProgramStateRef state = Pred->getState(); const LocationContext *LCtx = Pred->getLocationContext(); SVal baseVal = state->getSVal(Ex->getBase(), LCtx); SVal location = state->getLValue(Ex->getDecl(), baseVal); ExplodedNodeSet dstIvar; StmtNodeBuilder Bldr(Pred, dstIvar, *currentBuilderContext); Bldr.generateNode(Ex, Pred, state->BindExpr(Ex, LCtx, location)); // Perform the post-condition check of the ObjCIvarRefExpr and store // the created nodes in 'Dst'. getCheckerManager().runCheckersForPostStmt(Dst, dstIvar, Ex, *this); }
void ExprEngine::handleUOExtension(ExplodedNodeSet::iterator I, const UnaryOperator *U, StmtNodeBuilder &Bldr) { // FIXME: We can probably just have some magic in Environment::getSVal() // that propagates values, instead of creating a new node here. // // Unary "+" is a no-op, similar to a parentheses. We still have places // where it may be a block-level expression, so we need to // generate an extra node that just propagates the value of the // subexpression. const Expr *Ex = U->getSubExpr()->IgnoreParens(); ProgramStateRef state = (*I)->getState(); const LocationContext *LCtx = (*I)->getLocationContext(); Bldr.generateNode(U, *I, state->BindExpr(U, LCtx, state->getSVal(Ex, LCtx))); }
void ExprEngine::VisitLogicalExpr(const BinaryOperator* B, ExplodedNode *Pred, ExplodedNodeSet &Dst) { assert(B->getOpcode() == BO_LAnd || B->getOpcode() == BO_LOr); StmtNodeBuilder Bldr(Pred, Dst, *currentBuilderContext); ProgramStateRef state = Pred->getState(); ExplodedNode *N = Pred; while (!isa<BlockEntrance>(N->getLocation())) { ProgramPoint P = N->getLocation(); assert(isa<PreStmt>(P)|| isa<PreStmtPurgeDeadSymbols>(P)); (void) P; assert(N->pred_size() == 1); N = *N->pred_begin(); } assert(N->pred_size() == 1); N = *N->pred_begin(); BlockEdge BE = cast<BlockEdge>(N->getLocation()); SVal X; // Determine the value of the expression by introspecting how we // got this location in the CFG. This requires looking at the previous // block we were in and what kind of control-flow transfer was involved. const CFGBlock *SrcBlock = BE.getSrc(); // The only terminator (if there is one) that makes sense is a logical op. CFGTerminator T = SrcBlock->getTerminator(); if (const BinaryOperator *Term = cast_or_null<BinaryOperator>(T.getStmt())) { (void) Term; assert(Term->isLogicalOp()); assert(SrcBlock->succ_size() == 2); // Did we take the true or false branch? unsigned constant = (*SrcBlock->succ_begin() == BE.getDst()) ? 1 : 0; X = svalBuilder.makeIntVal(constant, B->getType()); } else { // If there is no terminator, by construction the last statement // in SrcBlock is the value of the enclosing expression. assert(!SrcBlock->empty()); CFGStmt Elem = cast<CFGStmt>(*SrcBlock->rbegin()); const Stmt *S = Elem.getStmt(); X = N->getState()->getSVal(S, Pred->getLocationContext()); } Bldr.generateNode(B, Pred, state->BindExpr(B, Pred->getLocationContext(), X)); }
// FIXME: This is the sort of code that should eventually live in a Core // checker rather than as a special case in ExprEngine. void ExprEngine::performTrivialCopy(NodeBuilder &Bldr, ExplodedNode *Pred, const CallEvent &Call) { SVal ThisVal; bool AlwaysReturnsLValue; if (const CXXConstructorCall *Ctor = dyn_cast<CXXConstructorCall>(&Call)) { assert(Ctor->getDecl()->isTrivial()); assert(Ctor->getDecl()->isCopyOrMoveConstructor()); ThisVal = Ctor->getCXXThisVal(); AlwaysReturnsLValue = false; } else { assert(cast<CXXMethodDecl>(Call.getDecl())->isTrivial()); assert(cast<CXXMethodDecl>(Call.getDecl())->getOverloadedOperator() == OO_Equal); ThisVal = cast<CXXInstanceCall>(Call).getCXXThisVal(); AlwaysReturnsLValue = true; } const LocationContext *LCtx = Pred->getLocationContext(); ExplodedNodeSet Dst; Bldr.takeNodes(Pred); SVal V = Call.getArgSVal(0); // If the value being copied is not unknown, load from its location to get // an aggregate rvalue. if (Optional<Loc> L = V.getAs<Loc>()) V = Pred->getState()->getSVal(*L); else assert(V.isUnknown()); const Expr *CallExpr = Call.getOriginExpr(); evalBind(Dst, CallExpr, Pred, ThisVal, V, true); PostStmt PS(CallExpr, LCtx); for (ExplodedNodeSet::iterator I = Dst.begin(), E = Dst.end(); I != E; ++I) { ProgramStateRef State = (*I)->getState(); if (AlwaysReturnsLValue) State = State->BindExpr(CallExpr, LCtx, ThisVal); else State = bindReturnValue(Call, LCtx, State); Bldr.generateNode(PS, State, *I); } }
void ExprEngine::CreateCXXTemporaryObject(const MaterializeTemporaryExpr *ME, ExplodedNode *Pred, ExplodedNodeSet &Dst) { StmtNodeBuilder Bldr(Pred, Dst, *currentBuilderContext); const Expr *tempExpr = ME->GetTemporaryExpr()->IgnoreParens(); ProgramStateRef state = Pred->getState(); const LocationContext *LCtx = Pred->getLocationContext(); // Bind the temporary object to the value of the expression. Then bind // the expression to the location of the object. SVal V = state->getSVal(tempExpr, Pred->getLocationContext()); const MemRegion *R = svalBuilder.getRegionManager().getCXXTempObjectRegion(ME, LCtx); state = state->bindLoc(loc::MemRegionVal(R), V); Bldr.generateNode(ME, Pred, state->BindExpr(ME, LCtx, loc::MemRegionVal(R))); }
void ExprEngine::VisitGuardedExpr(const Expr *Ex, const Expr *L, const Expr *R, ExplodedNode *Pred, ExplodedNodeSet &Dst) { StmtNodeBuilder B(Pred, Dst, *currBldrCtx); ProgramStateRef state = Pred->getState(); const LocationContext *LCtx = Pred->getLocationContext(); const CFGBlock *SrcBlock = 0; for (const ExplodedNode *N = Pred ; N ; N = *N->pred_begin()) { ProgramPoint PP = N->getLocation(); if (PP.getAs<PreStmtPurgeDeadSymbols>() || PP.getAs<BlockEntrance>()) { assert(N->pred_size() == 1); continue; } SrcBlock = PP.castAs<BlockEdge>().getSrc(); break; } assert(SrcBlock && "missing function entry"); // Find the last expression in the predecessor block. That is the // expression that is used for the value of the ternary expression. bool hasValue = false; SVal V; for (CFGBlock::const_reverse_iterator I = SrcBlock->rbegin(), E = SrcBlock->rend(); I != E; ++I) { CFGElement CE = *I; if (Optional<CFGStmt> CS = CE.getAs<CFGStmt>()) { const Expr *ValEx = cast<Expr>(CS->getStmt()); hasValue = true; V = state->getSVal(ValEx, LCtx); break; } } assert(hasValue); (void) hasValue; // Generate a new node with the binding from the appropriate path. B.generateNode(Ex, Pred, state->BindExpr(Ex, LCtx, V, true)); }
virtual void expandGraph(ExplodedNodeSet &Dst, ExplodedNode *Pred) { ProgramStateRef state = getReplayWithoutInliningState(Pred, CE); // First, try to inline the call. if (state == 0 && Eng.InlineCall(Dst, CE, Pred)) return; // First handle the return value. StmtNodeBuilder Bldr(Pred, Dst, *Eng.currentBuilderContext); // Get the callee. const Expr *Callee = CE->getCallee()->IgnoreParens(); if (state == 0) state = Pred->getState(); SVal L = state->getSVal(Callee, Pred->getLocationContext()); // Figure out the result type. We do this dance to handle references. QualType ResultTy; if (const FunctionDecl *FD = L.getAsFunctionDecl()) ResultTy = FD->getResultType(); else ResultTy = CE->getType(); if (CE->isLValue()) ResultTy = Eng.getContext().getPointerType(ResultTy); // Conjure a symbol value to use as the result. SValBuilder &SVB = Eng.getSValBuilder(); unsigned Count = Eng.currentBuilderContext->getCurrentBlockCount(); const LocationContext *LCtx = Pred->getLocationContext(); SVal RetVal = SVB.getConjuredSymbolVal(0, CE, LCtx, ResultTy, Count); // Generate a new state with the return value set. state = state->BindExpr(CE, LCtx, RetVal); // Invalidate the arguments. state = Eng.invalidateArguments(state, CallOrObjCMessage(CE, state, LCtx), LCtx); // And make the result node. Bldr.generateNode(CE, Pred, state); }
void ExprEngine:: VisitUnaryExprOrTypeTraitExpr(const UnaryExprOrTypeTraitExpr *Ex, ExplodedNode *Pred, ExplodedNodeSet &Dst) { // FIXME: Prechecks eventually go in ::Visit(). ExplodedNodeSet CheckedSet; getCheckerManager().runCheckersForPreStmt(CheckedSet, Pred, Ex, *this); ExplodedNodeSet EvalSet; StmtNodeBuilder Bldr(CheckedSet, EvalSet, *currBldrCtx); QualType T = Ex->getTypeOfArgument(); for (ExplodedNodeSet::iterator I = CheckedSet.begin(), E = CheckedSet.end(); I != E; ++I) { if (Ex->getKind() == UETT_SizeOf) { if (!T->isIncompleteType() && !T->isConstantSizeType()) { assert(T->isVariableArrayType() && "Unknown non-constant-sized type."); // FIXME: Add support for VLA type arguments and VLA expressions. // When that happens, we should probably refactor VLASizeChecker's code. continue; } else if (T->getAs<ObjCObjectType>()) { // Some code tries to take the sizeof an ObjCObjectType, relying that // the compiler has laid out its representation. Just report Unknown // for these. continue; } } APSInt Value = Ex->EvaluateKnownConstInt(getContext()); CharUnits amt = CharUnits::fromQuantity(Value.getZExtValue()); ProgramStateRef state = (*I)->getState(); state = state->BindExpr(Ex, (*I)->getLocationContext(), svalBuilder.makeIntVal(amt.getQuantity(), Ex->getType())); Bldr.generateNode(Ex, *I, state); } getCheckerManager().runCheckersForPostStmt(Dst, EvalSet, Ex, *this); }