diff options
| author | Zhongxing Xu <xuzhongxing@gmail.com> | 2010-03-10 04:58:55 +0000 |
|---|---|---|
| committer | Zhongxing Xu <xuzhongxing@gmail.com> | 2010-03-10 04:58:55 +0000 |
| commit | 1bb6a1a593ffafd36f10ff8af84c077b1f10fcfa (patch) | |
| tree | 91bf524d4fcc7ae1109469037a79361bb92deb25 /clang/lib | |
| parent | 6cf3f3c75efdf24456ee084e4b8d55ecbd3809d0 (diff) | |
| download | bcm5719-llvm-1bb6a1a593ffafd36f10ff8af84c077b1f10fcfa.tar.gz bcm5719-llvm-1bb6a1a593ffafd36f10ff8af84c077b1f10fcfa.zip | |
Add use-after-free check to MallocChecker.
llvm-svn: 98136
Diffstat (limited to 'clang/lib')
| -rw-r--r-- | clang/lib/Checker/MallocChecker.cpp | 24 | ||||
| -rw-r--r-- | clang/lib/Checker/SVals.cpp | 19 |
2 files changed, 42 insertions, 1 deletions
diff --git a/clang/lib/Checker/MallocChecker.cpp b/clang/lib/Checker/MallocChecker.cpp index 4ff98642e1c..a08afc4b795 100644 --- a/clang/lib/Checker/MallocChecker.cpp +++ b/clang/lib/Checker/MallocChecker.cpp @@ -57,17 +57,20 @@ class RegionState {}; class MallocChecker : public CheckerVisitor<MallocChecker> { BuiltinBug *BT_DoubleFree; BuiltinBug *BT_Leak; + BuiltinBug *BT_UseFree; IdentifierInfo *II_malloc, *II_free, *II_realloc; public: MallocChecker() - : BT_DoubleFree(0), BT_Leak(0), II_malloc(0), II_free(0), II_realloc(0) {} + : BT_DoubleFree(0), BT_Leak(0), BT_UseFree(0), + II_malloc(0), II_free(0), II_realloc(0) {} static void *getTag(); bool EvalCallExpr(CheckerContext &C, const CallExpr *CE); void EvalDeadSymbols(CheckerContext &C,const Stmt *S,SymbolReaper &SymReaper); void EvalEndPath(GREndPathNodeBuilder &B, void *tag, GRExprEngine &Eng); void PreVisitReturnStmt(CheckerContext &C, const ReturnStmt *S); const GRState *EvalAssume(const GRState *state, SVal Cond, bool Assumption); + void VisitLocation(CheckerContext &C, const Stmt *S, SVal l); private: void MallocMem(CheckerContext &C, const CallExpr *CE); @@ -339,3 +342,22 @@ const GRState *MallocChecker::EvalAssume(const GRState *state, SVal Cond, return state; } + +// Check if the location is a freed symbolic region. +void MallocChecker::VisitLocation(CheckerContext &C, const Stmt *S, SVal l) { + SymbolRef Sym = l.getLocSymbolInBase(); + if (Sym) { + const RefState *RS = C.getState()->get<RegionState>(Sym); + if (RS) + if (RS->isReleased()) { + ExplodedNode *N = C.GenerateSink(); + if (!BT_UseFree) + BT_UseFree = new BuiltinBug("Use dynamically allocated memory after" + " it is freed."); + + BugReport *R = new BugReport(*BT_UseFree, BT_UseFree->getDescription(), + N); + C.EmitReport(R); + } + } +} diff --git a/clang/lib/Checker/SVals.cpp b/clang/lib/Checker/SVals.cpp index 28b3fce050b..4bfa2cdafb4 100644 --- a/clang/lib/Checker/SVals.cpp +++ b/clang/lib/Checker/SVals.cpp @@ -70,6 +70,25 @@ SymbolRef SVal::getAsLocSymbol() const { return NULL; } +/// Get the symbol in the SVal or its base region. +SymbolRef SVal::getLocSymbolInBase() const { + const loc::MemRegionVal *X = dyn_cast<loc::MemRegionVal>(this); + + if (!X) + return 0; + + const MemRegion *R = X->getRegion(); + + while (const SubRegion *SR = dyn_cast<SubRegion>(R)) { + if (const SymbolicRegion *SymR = dyn_cast<SymbolicRegion>(SR)) + return SymR->getSymbol(); + else + R = SR->getSuperRegion(); + } + + return 0; +} + /// getAsSymbol - If this Sval wraps a symbol return that SymbolRef. /// Otherwise return 0. // FIXME: should we consider SymbolRef wrapped in CodeTextRegion? |

