Author: charusso Date: Wed Jul 17 17:03:55 2019 New Revision: 366391 URL: http://llvm.org/viewvc/llvm-project?rev=366391&view=rev Log: [analyzer] MallocChecker: Prevent Integer Set Library false positives
Summary: Integer Set Library using retain-count based allocation which is not modeled in MallocChecker. Reviewed By: NoQ Tags: #clang Differential Revision: https://reviews.llvm.org/D64680 Added: cfe/trunk/test/Analysis/retain-count-alloc.cpp Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/MallocChecker.cpp Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/MallocChecker.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Checkers/MallocChecker.cpp?rev=366391&r1=366390&r2=366391&view=diff ============================================================================== --- cfe/trunk/lib/StaticAnalyzer/Checkers/MallocChecker.cpp (original) +++ cfe/trunk/lib/StaticAnalyzer/Checkers/MallocChecker.cpp Wed Jul 17 17:03:55 2019 @@ -17,6 +17,7 @@ #include "clang/AST/ParentMap.h" #include "clang/Basic/SourceManager.h" #include "clang/Basic/TargetInfo.h" +#include "clang/Lex/Lexer.h" #include "clang/StaticAnalyzer/Core/BugReporter/BugType.h" #include "clang/StaticAnalyzer/Core/BugReporter/CommonBugCategories.h" #include "clang/StaticAnalyzer/Core/Checker.h" @@ -359,6 +360,11 @@ private: /// Check if the memory associated with this symbol was released. bool isReleased(SymbolRef Sym, CheckerContext &C) const; + /// See if deallocation happens in a suspicious context. If so, escape the + /// pointers that otherwise would have been deallocated and return true. + bool suppressDeallocationsInSuspiciousContexts(const CallExpr *CE, + CheckerContext &C) const; + bool checkUseAfterFree(SymbolRef Sym, CheckerContext &C, const Stmt *S) const; void checkUseZeroAllocated(SymbolRef Sym, CheckerContext &C, @@ -877,6 +883,9 @@ void MallocChecker::checkPostStmt(const State = ProcessZeroAllocation(C, CE, 0, State); State = ProcessZeroAllocation(C, CE, 1, State); } else if (FunI == II_free || FunI == II_g_free || FunI == II_kfree) { + if (suppressDeallocationsInSuspiciousContexts(CE, C)) + return; + State = FreeMemAux(C, CE, State, 0, false, ReleasedAllocatedMemory); } else if (FunI == II_strdup || FunI == II_win_strdup || FunI == II_wcsdup || FunI == II_win_wcsdup) { @@ -2532,6 +2541,35 @@ bool MallocChecker::isReleased(SymbolRef return (RS && RS->isReleased()); } +bool MallocChecker::suppressDeallocationsInSuspiciousContexts( + const CallExpr *CE, CheckerContext &C) const { + if (CE->getNumArgs() == 0) + return false; + + StringRef FunctionStr = ""; + if (const auto *FD = dyn_cast<FunctionDecl>(C.getStackFrame()->getDecl())) + if (const Stmt *Body = FD->getBody()) + if (Body->getBeginLoc().isValid()) + FunctionStr = + Lexer::getSourceText(CharSourceRange::getTokenRange( + {FD->getBeginLoc(), Body->getBeginLoc()}), + C.getSourceManager(), C.getLangOpts()); + + // We do not model the Integer Set Library's retain-count based allocation. + if (!FunctionStr.contains("__isl_")) + return false; + + ProgramStateRef State = C.getState(); + + for (const Expr *Arg : CE->arguments()) + if (SymbolRef Sym = C.getSVal(Arg).getAsSymbol()) + if (const RefState *RS = State->get<RegionState>(Sym)) + State = State->set<RegionState>(Sym, RefState::getEscaped(RS)); + + C.addTransition(State); + return true; +} + bool MallocChecker::checkUseAfterFree(SymbolRef Sym, CheckerContext &C, const Stmt *S) const { @@ -2833,7 +2871,6 @@ ProgramStateRef MallocChecker::checkPoin if (const RefState *RS = State->get<RegionState>(sym)) { if ((RS->isAllocated() || RS->isAllocatedOfSizeZero()) && CheckRefState(RS)) { - State = State->remove<RegionState>(sym); State = State->set<RegionState>(sym, RefState::getEscaped(RS)); } } Added: cfe/trunk/test/Analysis/retain-count-alloc.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/retain-count-alloc.cpp?rev=366391&view=auto ============================================================================== --- cfe/trunk/test/Analysis/retain-count-alloc.cpp (added) +++ cfe/trunk/test/Analysis/retain-count-alloc.cpp Wed Jul 17 17:03:55 2019 @@ -0,0 +1,37 @@ +// RUN: %clang_analyze_cc1 \ +// RUN: -analyzer-checker=core,unix.Malloc \ +// RUN: -verify %s + +// expected-no-diagnostics: We do not model Integer Set Library's retain-count +// based allocation. If any of the parameters has an +// '__isl_' prefixed macro definition we escape every +// of them when we are about to 'free()' something. + +#define __isl_take +#define __isl_keep + +struct Object { int Ref; }; +void free(void *); + +Object *copyObj(__isl_keep Object *O) { + O->Ref++; + return O; +} + +void freeObj(__isl_take Object *O) { + if (--O->Ref > 0) + return; + + free(O); // Here we notice that the parameter contains '__isl_', escape it. +} + +void useAfterFree(__isl_take Object *A) { + if (!A) + return; + + Object *B = copyObj(A); + freeObj(B); + + A->Ref = 13; + // no-warning: 'Use of memory after it is freed' was here. +} _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits