diff options
author | Dimitry Andric <dim@FreeBSD.org> | 2011-02-20 13:06:31 +0000 |
---|---|---|
committer | Dimitry Andric <dim@FreeBSD.org> | 2011-02-20 13:06:31 +0000 |
commit | bca07a4524feb4edec581062d631a13116320a24 (patch) | |
tree | a9243275843fbeaa590afc07ee888e006b8d54ea /lib/StaticAnalyzer/Checkers/UndefBranchChecker.cpp | |
parent | 998bc5802ecdd65ce3b270f6c69a8ae8557f0a10 (diff) | |
download | src-bca07a4524feb4edec581062d631a13116320a24.tar.gz src-bca07a4524feb4edec581062d631a13116320a24.zip |
Vendor import of clang trunk r126079:vendor/clang/clang-r126079
Notes
Notes:
svn path=/vendor/clang/dist/; revision=218887
svn path=/vendor/clang/clang-r126079/; revision=218888; tag=vendor/clang/clang-r126079
Diffstat (limited to 'lib/StaticAnalyzer/Checkers/UndefBranchChecker.cpp')
-rw-r--r-- | lib/StaticAnalyzer/Checkers/UndefBranchChecker.cpp | 120 |
1 files changed, 120 insertions, 0 deletions
diff --git a/lib/StaticAnalyzer/Checkers/UndefBranchChecker.cpp b/lib/StaticAnalyzer/Checkers/UndefBranchChecker.cpp new file mode 100644 index 000000000000..14ae9edc7b7e --- /dev/null +++ b/lib/StaticAnalyzer/Checkers/UndefBranchChecker.cpp @@ -0,0 +1,120 @@ +//=== UndefBranchChecker.cpp -----------------------------------*- C++ -*--===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines UndefBranchChecker, which checks for undefined branch +// condition. +// +//===----------------------------------------------------------------------===// + +#include "InternalChecks.h" +#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h" +#include "clang/StaticAnalyzer/Core/PathSensitive/Checker.h" + +using namespace clang; +using namespace ento; + +namespace { + +class UndefBranchChecker : public Checker { + BuiltinBug *BT; + + struct FindUndefExpr { + GRStateManager& VM; + const GRState* St; + + FindUndefExpr(GRStateManager& V, const GRState* S) : VM(V), St(S) {} + + const Expr* FindExpr(const Expr* Ex) { + if (!MatchesCriteria(Ex)) + return 0; + + for (Stmt::const_child_iterator I = Ex->child_begin(), + E = Ex->child_end();I!=E;++I) + if (const Expr* ExI = dyn_cast_or_null<Expr>(*I)) { + const Expr* E2 = FindExpr(ExI); + if (E2) return E2; + } + + return Ex; + } + + bool MatchesCriteria(const Expr* Ex) { return St->getSVal(Ex).isUndef(); } + }; + +public: + UndefBranchChecker() : BT(0) {} + static void *getTag(); + void VisitBranchCondition(BranchNodeBuilder &Builder, ExprEngine &Eng, + const Stmt *Condition, void *tag); +}; + +} + +void ento::RegisterUndefBranchChecker(ExprEngine &Eng) { + Eng.registerCheck(new UndefBranchChecker()); +} + +void *UndefBranchChecker::getTag() { + static int x; + return &x; +} + +void UndefBranchChecker::VisitBranchCondition(BranchNodeBuilder &Builder, + ExprEngine &Eng, + const Stmt *Condition, void *tag){ + const GRState *state = Builder.getState(); + SVal X = state->getSVal(Condition); + if (X.isUndef()) { + ExplodedNode *N = Builder.generateNode(state, true); + if (N) { + N->markAsSink(); + if (!BT) + BT = new BuiltinBug("Branch condition evaluates to a garbage value"); + + // What's going on here: we want to highlight the subexpression of the + // condition that is the most likely source of the "uninitialized + // branch condition." We do a recursive walk of the condition's + // subexpressions and roughly look for the most nested subexpression + // that binds to Undefined. We then highlight that expression's range. + BlockEdge B = cast<BlockEdge>(N->getLocation()); + const Expr* Ex = cast<Expr>(B.getSrc()->getTerminatorCondition()); + assert (Ex && "Block must have a terminator."); + + // Get the predecessor node and check if is a PostStmt with the Stmt + // being the terminator condition. We want to inspect the state + // of that node instead because it will contain main information about + // the subexpressions. + assert (!N->pred_empty()); + + // Note: any predecessor will do. They should have identical state, + // since all the BlockEdge did was act as an error sink since the value + // had to already be undefined. + ExplodedNode *PrevN = *N->pred_begin(); + ProgramPoint P = PrevN->getLocation(); + const GRState* St = N->getState(); + + if (PostStmt* PS = dyn_cast<PostStmt>(&P)) + if (PS->getStmt() == Ex) + St = PrevN->getState(); + + FindUndefExpr FindIt(Eng.getStateManager(), St); + Ex = FindIt.FindExpr(Ex); + + // Emit the bug report. + EnhancedBugReport *R = new EnhancedBugReport(*BT, BT->getDescription(),N); + R->addVisitorCreator(bugreporter::registerTrackNullOrUndefValue, Ex); + R->addRange(Ex->getSourceRange()); + + Eng.getBugReporter().EmitReport(R); + } + + Builder.markInfeasible(true); + Builder.markInfeasible(false); + } +} |