diff options
Diffstat (limited to 'lib/Analysis')
-rw-r--r-- | lib/Analysis/ArrayBoundChecker.cpp | 4 | ||||
-rw-r--r-- | lib/Analysis/AttrNonNullChecker.cpp | 6 | ||||
-rw-r--r-- | lib/Analysis/BasicObjCFoundationChecks.cpp | 5 | ||||
-rw-r--r-- | lib/Analysis/CastToStructChecker.cpp | 2 | ||||
-rw-r--r-- | lib/Analysis/Checker.cpp | 17 | ||||
-rw-r--r-- | lib/Analysis/DereferenceChecker.cpp | 11 | ||||
-rw-r--r-- | lib/Analysis/DivZeroChecker.cpp | 5 | ||||
-rw-r--r-- | lib/Analysis/FixedAddressChecker.cpp | 2 | ||||
-rw-r--r-- | lib/Analysis/GRExprEngine.cpp | 8 | ||||
-rw-r--r-- | lib/Analysis/MallocChecker.cpp | 14 | ||||
-rw-r--r-- | lib/Analysis/PointerArithChecker.cpp | 2 | ||||
-rw-r--r-- | lib/Analysis/PointerSubChecker.cpp | 2 | ||||
-rw-r--r-- | lib/Analysis/ReturnPointerRangeChecker.cpp | 3 | ||||
-rw-r--r-- | lib/Analysis/ReturnStackAddressChecker.cpp | 2 | ||||
-rw-r--r-- | lib/Analysis/ReturnUndefChecker.cpp | 2 | ||||
-rw-r--r-- | lib/Analysis/UndefinedArgChecker.cpp | 8 | ||||
-rw-r--r-- | lib/Analysis/UndefinedArraySubscriptChecker.cpp | 2 | ||||
-rw-r--r-- | lib/Analysis/UndefinedAssignmentChecker.cpp | 2 | ||||
-rw-r--r-- | lib/Analysis/VLASizeChecker.cpp | 7 |
19 files changed, 55 insertions, 49 deletions
diff --git a/lib/Analysis/ArrayBoundChecker.cpp b/lib/Analysis/ArrayBoundChecker.cpp index 549a22bec1..3d8b3b3d1b 100644 --- a/lib/Analysis/ArrayBoundChecker.cpp +++ b/lib/Analysis/ArrayBoundChecker.cpp @@ -62,8 +62,7 @@ void ArrayBoundChecker::VisitLocation(CheckerContext &C, const Stmt *S, SVal l){ const GRState *StInBound = state->AssumeInBound(Idx, NumElements, true); const GRState *StOutBound = state->AssumeInBound(Idx, NumElements, false); if (StOutBound && !StInBound) { - ExplodedNode *N = C.GenerateNode(S, StOutBound, true); - + ExplodedNode *N = C.GenerateSink(StOutBound); if (!N) return; @@ -80,7 +79,6 @@ void ArrayBoundChecker::VisitLocation(CheckerContext &C, const Stmt *S, SVal l){ new RangedBugReport(*BT, BT->getDescription(), N); report->addRange(S->getSourceRange()); - C.EmitReport(report); } } diff --git a/lib/Analysis/AttrNonNullChecker.cpp b/lib/Analysis/AttrNonNullChecker.cpp index 01e1a1fcf6..8668c75c75 100644 --- a/lib/Analysis/AttrNonNullChecker.cpp +++ b/lib/Analysis/AttrNonNullChecker.cpp @@ -39,7 +39,6 @@ void clang::RegisterAttrNonNullChecker(GRExprEngine &Eng) { void AttrNonNullChecker::PreVisitCallExpr(CheckerContext &C, const CallExpr *CE) { const GRState *state = C.getState(); - const GRState *originalState = state; // Check if the callee has a 'nonnull' attribute. SVal X = state->getSVal(CE->getCallee()); @@ -74,7 +73,7 @@ void AttrNonNullChecker::PreVisitCallExpr(CheckerContext &C, if (stateNull && !stateNotNull) { // Generate an error node. Check for a null node in case // we cache out. - if (ExplodedNode *errorNode = C.GenerateNode(CE, stateNull, true)) { + if (ExplodedNode *errorNode = C.GenerateSink(stateNull)) { // Lazily allocate the BugType object if it hasn't already been // created. Ownership is transferred to the BugReporter object once @@ -109,6 +108,5 @@ void AttrNonNullChecker::PreVisitCallExpr(CheckerContext &C, // If we reach here all of the arguments passed the nonnull check. // If 'state' has been updated generated a new node. - if (state != originalState) - C.addTransition(C.GenerateNode(CE, state)); + C.addTransition(state); } diff --git a/lib/Analysis/BasicObjCFoundationChecks.cpp b/lib/Analysis/BasicObjCFoundationChecks.cpp index 5a88a7af93..424a0b3b25 100644 --- a/lib/Analysis/BasicObjCFoundationChecks.cpp +++ b/lib/Analysis/BasicObjCFoundationChecks.cpp @@ -563,12 +563,11 @@ void ClassReleaseChecker::PreVisitObjCMessageExpr(CheckerContext &C, BT = new APIMisuse("message incorrectly sent to class instead of class " "instance"); - ExplodedNode *N = C.GenerateNode(ME, C.getState(), false); + ExplodedNode *N = C.GenerateNode(); + if (!N) return; - C.addTransition(N); - llvm::SmallString<200> buf; llvm::raw_svector_ostream os(buf); diff --git a/lib/Analysis/CastToStructChecker.cpp b/lib/Analysis/CastToStructChecker.cpp index ccd4a3333e..7c6fc7ed3f 100644 --- a/lib/Analysis/CastToStructChecker.cpp +++ b/lib/Analysis/CastToStructChecker.cpp @@ -59,7 +59,7 @@ void CastToStructChecker::PreVisitCastExpr(CheckerContext &C, // Now the cast-to-type is struct pointer, the original type is not void*. if (!OrigPointeeTy->isRecordType()) { - if (ExplodedNode *N = C.GenerateNode(CE)) { + if (ExplodedNode *N = C.GenerateNode()) { if (!BT) BT = new BuiltinBug("Cast from non-struct type to struct type", "Casting a non-structure type to a structure type " diff --git a/lib/Analysis/Checker.cpp b/lib/Analysis/Checker.cpp index 985b1e0a1d..0d907e5016 100644 --- a/lib/Analysis/Checker.cpp +++ b/lib/Analysis/Checker.cpp @@ -16,3 +16,20 @@ using namespace clang; Checker::~Checker() {} + +CheckerContext::~CheckerContext() { + // Do we need to autotransition? 'Dst' can get populated in a variety of + // ways, including 'addTransition()' adding the predecessor node to Dst + // without actually generated a new node. We also shouldn't autotransition + // if we are building sinks or we generated a node and decided to not + // add it as a transition. + if (Dst.size() == size && !B.BuildSinks && !B.HasGeneratedNode) { + if (state && state != B.GetState(Pred)) { + static int autoTransitionTag = 0; + B.Tag = &autoTransitionTag; + addTransition(state); + } + else + Dst.Add(Pred); + } +} diff --git a/lib/Analysis/DereferenceChecker.cpp b/lib/Analysis/DereferenceChecker.cpp index a8f5af34a7..4c4091cbc2 100644 --- a/lib/Analysis/DereferenceChecker.cpp +++ b/lib/Analysis/DereferenceChecker.cpp @@ -56,8 +56,7 @@ void DereferenceChecker::VisitLocation(CheckerContext &C, const Stmt *S, SVal l) { // Check for dereference of an undefined value. if (l.isUndef()) { - ExplodedNode *N = C.GenerateNode(S, true); - if (N) { + if (ExplodedNode *N = C.GenerateSink()) { if (!BT_undef) BT_undef = new BuiltinBug("Dereference of undefined pointer value"); @@ -84,7 +83,7 @@ void DereferenceChecker::VisitLocation(CheckerContext &C, const Stmt *S, if (nullState) { if (!notNullState) { // Generate an error node. - ExplodedNode *N = C.GenerateNode(S, nullState, true); + ExplodedNode *N = C.GenerateSink(nullState); if (!N) return; @@ -106,13 +105,11 @@ void DereferenceChecker::VisitLocation(CheckerContext &C, const Stmt *S, // 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.GenerateNode(S, nullState, true)) + if (ExplodedNode *N = C.GenerateSink(nullState)) ImplicitNullDerefNodes.push_back(N); } } // From this point forward, we know that the location is not null. - assert(notNullState); - C.addTransition(state != nullState ? C.GenerateNode(S, notNullState) : - C.getPredecessor()); + C.addTransition(notNullState); } diff --git a/lib/Analysis/DivZeroChecker.cpp b/lib/Analysis/DivZeroChecker.cpp index a8630f1008..4052637043 100644 --- a/lib/Analysis/DivZeroChecker.cpp +++ b/lib/Analysis/DivZeroChecker.cpp @@ -63,7 +63,7 @@ void DivZeroChecker::PreVisitBinaryOperator(CheckerContext &C, llvm::tie(stateNotZero, stateZero) = CM.AssumeDual(C.getState(), *DV); if (stateZero && !stateNotZero) { - if (ExplodedNode *N = C.GenerateNode(B, stateZero, true)) { + if (ExplodedNode *N = C.GenerateSink(stateZero)) { if (!BT) BT = new BuiltinBug("Division by zero"); @@ -80,6 +80,5 @@ void DivZeroChecker::PreVisitBinaryOperator(CheckerContext &C, // If we get here, then the denom should not be zero. We abandon the implicit // zero denom case for now. - if (stateNotZero != C.getState()) - C.addTransition(C.GenerateNode(B, stateNotZero)); + C.addTransition(stateNotZero); } diff --git a/lib/Analysis/FixedAddressChecker.cpp b/lib/Analysis/FixedAddressChecker.cpp index 80096dcb70..d8adaafa60 100644 --- a/lib/Analysis/FixedAddressChecker.cpp +++ b/lib/Analysis/FixedAddressChecker.cpp @@ -53,7 +53,7 @@ void FixedAddressChecker::PreVisitBinaryOperator(CheckerContext &C, if (!RV.isConstant() || RV.isZeroConstant()) return; - if (ExplodedNode *N = C.GenerateNode(B)) { + if (ExplodedNode *N = C.GenerateNode()) { if (!BT) BT = new BuiltinBug("Use fixed address", "Using a fixed address is not portable because that " diff --git a/lib/Analysis/GRExprEngine.cpp b/lib/Analysis/GRExprEngine.cpp index 4f3440d88a..f657aebdf6 100644 --- a/lib/Analysis/GRExprEngine.cpp +++ b/lib/Analysis/GRExprEngine.cpp @@ -1292,9 +1292,13 @@ void GRExprEngine::EvalLocation(ExplodedNodeSet &Dst, Stmt *S, Checker *checker = I->second; for (ExplodedNodeSet::iterator NI = PrevSet->begin(), NE = PrevSet->end(); - NI != NE; ++NI) - checker->GR_VisitLocation(*CurrSet, *Builder, *this, S, *NI, state, + NI != NE; ++NI) { + // Use the 'state' argument only when the predecessor node is the + // same as Pred. This allows us to catch updates to the state. + checker->GR_VisitLocation(*CurrSet, *Builder, *this, S, *NI, + *NI == Pred ? state : GetState(*NI), location, tag, isLoad); + } // Update which NodeSet is the current one. PrevSet = CurrSet; diff --git a/lib/Analysis/MallocChecker.cpp b/lib/Analysis/MallocChecker.cpp index 995720b1f8..a16125df77 100644 --- a/lib/Analysis/MallocChecker.cpp +++ b/lib/Analysis/MallocChecker.cpp @@ -112,9 +112,7 @@ void MallocChecker::MallocMem(CheckerContext &C, const CallExpr *CE) { SymbolRef Sym = CallVal.getAsLocSymbol(); assert(Sym); // Set the symbol's state to Allocated. - const GRState *AllocState - = state->set<RegionState>(Sym, RefState::getAllocated(CE)); - C.addTransition(C.GenerateNode(CE, AllocState)); + C.addTransition(state->set<RegionState>(Sym, RefState::getAllocated(CE))); } void MallocChecker::FreeMem(CheckerContext &C, const CallExpr *CE) { @@ -128,7 +126,7 @@ void MallocChecker::FreeMem(CheckerContext &C, const CallExpr *CE) { // Check double free. if (RS->isReleased()) { - ExplodedNode *N = C.GenerateNode(CE, true); + ExplodedNode *N = C.GenerateSink(); if (N) { if (!BT_DoubleFree) BT_DoubleFree = new BuiltinBug("Double free", @@ -144,7 +142,7 @@ void MallocChecker::FreeMem(CheckerContext &C, const CallExpr *CE) { // Normal free. const GRState *FreedState = state->set<RegionState>(Sym, RefState::getReleased(CE)); - C.addTransition(C.GenerateNode(CE, FreedState)); + C.addTransition(FreedState); } void MallocChecker::EvalDeadSymbols(CheckerContext &C, const Stmt *S, @@ -158,7 +156,7 @@ void MallocChecker::EvalDeadSymbols(CheckerContext &C, const Stmt *S, return; if (RS->isAllocated()) { - ExplodedNode *N = C.GenerateNode(S, true); + ExplodedNode *N = C.GenerateSink(); if (N) { if (!BT_Leak) BT_Leak = new BuiltinBug("Memory leak", @@ -213,7 +211,5 @@ void MallocChecker::PreVisitReturnStmt(CheckerContext &C, const ReturnStmt *S) { if (RS->isAllocated()) state = state->set<RegionState>(Sym, RefState::getEscaped(S)); - ExplodedNode *N = C.GenerateNode(S, state); - if (N) - C.addTransition(N); + C.addTransition(state); } diff --git a/lib/Analysis/PointerArithChecker.cpp b/lib/Analysis/PointerArithChecker.cpp index 93823484e1..6bf1a3fc5d 100644 --- a/lib/Analysis/PointerArithChecker.cpp +++ b/lib/Analysis/PointerArithChecker.cpp @@ -53,7 +53,7 @@ void PointerArithChecker::PreVisitBinaryOperator(CheckerContext &C, if (isa<VarRegion>(LR) || isa<CodeTextRegion>(LR) || isa<CompoundLiteralRegion>(LR)) { - if (ExplodedNode *N = C.GenerateNode(B)) { + if (ExplodedNode *N = C.GenerateNode()) { if (!BT) BT = new BuiltinBug("Dangerous pointer arithmetic", "Pointer arithmetic done on non-array variables " diff --git a/lib/Analysis/PointerSubChecker.cpp b/lib/Analysis/PointerSubChecker.cpp index 4c7906f4be..50f502507d 100644 --- a/lib/Analysis/PointerSubChecker.cpp +++ b/lib/Analysis/PointerSubChecker.cpp @@ -61,7 +61,7 @@ void PointerSubChecker::PreVisitBinaryOperator(CheckerContext &C, if (isa<SymbolicRegion>(BaseLR) || isa<SymbolicRegion>(BaseRR)) return; - if (ExplodedNode *N = C.GenerateNode(B)) { + if (ExplodedNode *N = C.GenerateNode()) { if (!BT) BT = new BuiltinBug("Pointer subtraction", "Subtraction of two pointers that do not point to " diff --git a/lib/Analysis/ReturnPointerRangeChecker.cpp b/lib/Analysis/ReturnPointerRangeChecker.cpp index 44887b2625..8a1929464e 100644 --- a/lib/Analysis/ReturnPointerRangeChecker.cpp +++ b/lib/Analysis/ReturnPointerRangeChecker.cpp @@ -70,7 +70,7 @@ void ReturnPointerRangeChecker::PreVisitReturnStmt(CheckerContext &C, const GRState *StInBound = state->AssumeInBound(Idx, NumElements, true); const GRState *StOutBound = state->AssumeInBound(Idx, NumElements, false); if (StOutBound && !StInBound) { - ExplodedNode *N = C.GenerateNode(RS, StOutBound, true); + ExplodedNode *N = C.GenerateSink(StOutBound); if (!N) return; @@ -91,7 +91,6 @@ void ReturnPointerRangeChecker::PreVisitReturnStmt(CheckerContext &C, new RangedBugReport(*BT, BT->getDescription(), N); report->addRange(RetE->getSourceRange()); - C.EmitReport(report); } } diff --git a/lib/Analysis/ReturnStackAddressChecker.cpp b/lib/Analysis/ReturnStackAddressChecker.cpp index e4be8712d0..e8a014af29 100644 --- a/lib/Analysis/ReturnStackAddressChecker.cpp +++ b/lib/Analysis/ReturnStackAddressChecker.cpp @@ -53,7 +53,7 @@ void ReturnStackAddressChecker::PreVisitReturnStmt(CheckerContext &C, if (!R || !R->hasStackStorage()) return; - ExplodedNode *N = C.GenerateNode(RS, C.getState(), true); + ExplodedNode *N = C.GenerateSink(); if (!N) return; diff --git a/lib/Analysis/ReturnUndefChecker.cpp b/lib/Analysis/ReturnUndefChecker.cpp index 796c7608c8..48163b4d86 100644 --- a/lib/Analysis/ReturnUndefChecker.cpp +++ b/lib/Analysis/ReturnUndefChecker.cpp @@ -50,7 +50,7 @@ void ReturnUndefChecker::PreVisitReturnStmt(CheckerContext &C, if (!C.getState()->getSVal(RetE).isUndef()) return; - ExplodedNode *N = C.GenerateNode(RS, C.getState(), true); + ExplodedNode *N = C.GenerateSink(); if (!N) return; diff --git a/lib/Analysis/UndefinedArgChecker.cpp b/lib/Analysis/UndefinedArgChecker.cpp index ea7d971fdb..e717f6bfe2 100644 --- a/lib/Analysis/UndefinedArgChecker.cpp +++ b/lib/Analysis/UndefinedArgChecker.cpp @@ -47,7 +47,7 @@ void clang::RegisterUndefinedArgChecker(GRExprEngine &Eng) { void UndefinedArgChecker::EmitBadCall(BugType *BT, CheckerContext &C, const CallExpr *CE) { - ExplodedNode *N = C.GenerateNode(CE, true); + ExplodedNode *N = C.GenerateSink(); if (!N) return; @@ -81,7 +81,7 @@ void UndefinedArgChecker::PreVisitCallExpr(CheckerContext &C, for (CallExpr::const_arg_iterator I = CE->arg_begin(), E = CE->arg_end(); I != E; ++I) { if (C.getState()->getSVal(*I).isUndef()) { - if (ExplodedNode *N = C.GenerateNode(CE, true)) { + if (ExplodedNode *N = C.GenerateSink()) { if (!BT_call_arg) BT_call_arg = new BuiltinBug("Pass-by-value argument in function call" " is undefined"); @@ -104,7 +104,7 @@ void UndefinedArgChecker::PreVisitObjCMessageExpr(CheckerContext &C, if (const Expr *receiver = ME->getReceiver()) if (state->getSVal(receiver).isUndef()) { - if (ExplodedNode *N = C.GenerateNode(ME, true)) { + if (ExplodedNode *N = C.GenerateSink()) { if (!BT_msg_undef) BT_msg_undef = new BuiltinBug("Receiver in message expression is a garbage value"); @@ -122,7 +122,7 @@ void UndefinedArgChecker::PreVisitObjCMessageExpr(CheckerContext &C, for (ObjCMessageExpr::const_arg_iterator I = ME->arg_begin(), E = ME->arg_end(); I != E; ++I) { if (state->getSVal(*I).isUndef()) { - if (ExplodedNode *N = C.GenerateNode(ME, true)) { + if (ExplodedNode *N = C.GenerateSink()) { if (!BT_msg_arg) BT_msg_arg = new BuiltinBug("Pass-by-value argument in message expression" diff --git a/lib/Analysis/UndefinedArraySubscriptChecker.cpp b/lib/Analysis/UndefinedArraySubscriptChecker.cpp index 887c7755fe..3ae0c579e9 100644 --- a/lib/Analysis/UndefinedArraySubscriptChecker.cpp +++ b/lib/Analysis/UndefinedArraySubscriptChecker.cpp @@ -41,7 +41,7 @@ void UndefinedArraySubscriptChecker::PreVisitArraySubscriptExpr(CheckerContext &C, const ArraySubscriptExpr *A) { if (C.getState()->getSVal(A->getIdx()).isUndef()) { - if (ExplodedNode *N = C.GenerateNode(A, true)) { + if (ExplodedNode *N = C.GenerateSink()) { if (!BT) BT = new BuiltinBug("Array subscript is undefined"); diff --git a/lib/Analysis/UndefinedAssignmentChecker.cpp b/lib/Analysis/UndefinedAssignmentChecker.cpp index 0e911ffab0..1c5b25cd8e 100644 --- a/lib/Analysis/UndefinedAssignmentChecker.cpp +++ b/lib/Analysis/UndefinedAssignmentChecker.cpp @@ -48,7 +48,7 @@ void UndefinedAssignmentChecker::PreVisitBind(CheckerContext &C, if (!val.isUndef()) return; - ExplodedNode *N = C.GenerateNode(StoreE, true); + ExplodedNode *N = C.GenerateSink(); if (!N) return; diff --git a/lib/Analysis/VLASizeChecker.cpp b/lib/Analysis/VLASizeChecker.cpp index 799a73e293..9a3436c4c9 100644 --- a/lib/Analysis/VLASizeChecker.cpp +++ b/lib/Analysis/VLASizeChecker.cpp @@ -55,7 +55,7 @@ void VLASizeChecker::PreVisitDeclStmt(CheckerContext &C, const DeclStmt *DS) { if (sizeV.isUndef()) { // Generate an error node. - ExplodedNode *N = C.GenerateNode(DS, true); + ExplodedNode *N = C.GenerateSink(); if (!N) return; @@ -78,7 +78,7 @@ void VLASizeChecker::PreVisitDeclStmt(CheckerContext &C, const DeclStmt *DS) { llvm::tie(stateNotZero, stateZero) = state->Assume(sizeD); if (stateZero && !stateNotZero) { - ExplodedNode* N = C.GenerateNode(DS, stateZero, true); + ExplodedNode* N = C.GenerateSink(stateZero); if (!BT_zero) BT_zero = new BuiltinBug("Declared variable-length array (VLA) has zero " "size"); @@ -92,6 +92,5 @@ void VLASizeChecker::PreVisitDeclStmt(CheckerContext &C, const DeclStmt *DS) { } // From this point on, assume that the size is not zero. - if (state != stateNotZero) - C.addTransition(C.GenerateNode(DS, stateNotZero)); + C.addTransition(stateNotZero); } |