diff options
| author | 2017-01-24 08:32:59 +0000 | |
|---|---|---|
| committer | 2017-01-24 08:32:59 +0000 | |
| commit | 53d771aafdbe5b919f264f53cba3788e2c4cffd2 (patch) | |
| tree | 7eca39498be0ff1e3a6daf583cd9ca5886bb2636 /gnu/llvm/tools/clang/lib/StaticAnalyzer/Checkers/MallocChecker.cpp | |
| parent | In preparation of compiling our kernels with -ffreestanding, explicitly map (diff) | |
| download | wireguard-openbsd-53d771aafdbe5b919f264f53cba3788e2c4cffd2.tar.xz wireguard-openbsd-53d771aafdbe5b919f264f53cba3788e2c4cffd2.zip | |
Import LLVM 4.0.0 rc1 including clang and lld to help the current
development effort on OpenBSD/arm64.
Diffstat (limited to 'gnu/llvm/tools/clang/lib/StaticAnalyzer/Checkers/MallocChecker.cpp')
| -rw-r--r-- | gnu/llvm/tools/clang/lib/StaticAnalyzer/Checkers/MallocChecker.cpp | 105 |
1 files changed, 72 insertions, 33 deletions
diff --git a/gnu/llvm/tools/clang/lib/StaticAnalyzer/Checkers/MallocChecker.cpp b/gnu/llvm/tools/clang/lib/StaticAnalyzer/Checkers/MallocChecker.cpp index e06662b1693..8e839a1d28f 100644 --- a/gnu/llvm/tools/clang/lib/StaticAnalyzer/Checkers/MallocChecker.cpp +++ b/gnu/llvm/tools/clang/lib/StaticAnalyzer/Checkers/MallocChecker.cpp @@ -26,7 +26,6 @@ #include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h" #include "clang/StaticAnalyzer/Core/PathSensitive/ProgramStateTrait.h" #include "clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h" -#include "llvm/ADT/ImmutableMap.h" #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/SmallString.h" #include "llvm/ADT/StringExtras.h" @@ -288,6 +287,9 @@ private: ProgramStateRef State, AllocationFamily Family = AF_Malloc); + static ProgramStateRef addExtentSize(CheckerContext &C, const CXXNewExpr *NE, + ProgramStateRef State); + // Check if this malloc() for special flags. At present that means M_ZERO or // __GFP_ZERO (in which case, treat it like calloc). llvm::Optional<ProgramStateRef> @@ -461,10 +463,10 @@ private: SPrev->isAllocatedOfSizeZero()))); } - PathDiagnosticPiece *VisitNode(const ExplodedNode *N, - const ExplodedNode *PrevN, - BugReporterContext &BRC, - BugReport &BR) override; + std::shared_ptr<PathDiagnosticPiece> VisitNode(const ExplodedNode *N, + const ExplodedNode *PrevN, + BugReporterContext &BRC, + BugReport &BR) override; std::unique_ptr<PathDiagnosticPiece> getEndPath(BugReporterContext &BRC, const ExplodedNode *EndPathNode, @@ -776,6 +778,8 @@ void MallocChecker::checkPostStmt(const CallExpr *CE, CheckerContext &C) const { State = MallocMemAux(C, CE, CE->getArg(0), UndefinedVal(), State); } } else if (FunI == II_kmalloc) { + if (CE->getNumArgs() < 1) + return; llvm::Optional<ProgramStateRef> MaybeState = performKernelMalloc(CE, C, State); if (MaybeState.hasValue()) @@ -805,6 +809,8 @@ void MallocChecker::checkPostStmt(const CallExpr *CE, CheckerContext &C) const { } else if (FunI == II_strndup) { State = MallocUpdateRefState(C, CE, State); } else if (FunI == II_alloca || FunI == II_win_alloca) { + if (CE->getNumArgs() < 1) + return; State = MallocMemAux(C, CE, CE->getArg(0), UndefinedVal(), State, AF_Alloca); State = ProcessZeroAllocation(C, CE, 0, State); @@ -982,10 +988,58 @@ void MallocChecker::checkPostStmt(const CXXNewExpr *NE, // existing binding. State = MallocUpdateRefState(C, NE, State, NE->isArray() ? AF_CXXNewArray : AF_CXXNew); + State = addExtentSize(C, NE, State); State = ProcessZeroAllocation(C, NE, 0, State); C.addTransition(State); } +// Sets the extent value of the MemRegion allocated by +// new expression NE to its size in Bytes. +// +ProgramStateRef MallocChecker::addExtentSize(CheckerContext &C, + const CXXNewExpr *NE, + ProgramStateRef State) { + if (!State) + return nullptr; + SValBuilder &svalBuilder = C.getSValBuilder(); + SVal ElementCount; + const LocationContext *LCtx = C.getLocationContext(); + const SubRegion *Region; + if (NE->isArray()) { + const Expr *SizeExpr = NE->getArraySize(); + ElementCount = State->getSVal(SizeExpr, C.getLocationContext()); + // Store the extent size for the (symbolic)region + // containing the elements. + Region = (State->getSVal(NE, LCtx)) + .getAsRegion() + ->getAs<SubRegion>() + ->getSuperRegion() + ->getAs<SubRegion>(); + } else { + ElementCount = svalBuilder.makeIntVal(1, true); + Region = (State->getSVal(NE, LCtx)).getAsRegion()->getAs<SubRegion>(); + } + assert(Region); + + // Set the region's extent equal to the Size in Bytes. + QualType ElementType = NE->getAllocatedType(); + ASTContext &AstContext = C.getASTContext(); + CharUnits TypeSize = AstContext.getTypeSizeInChars(ElementType); + + if (ElementCount.getAs<NonLoc>()) { + DefinedOrUnknownSVal Extent = Region->getExtent(svalBuilder); + // size in Bytes = ElementCount*TypeSize + SVal SizeInBytes = svalBuilder.evalBinOpNN( + State, BO_Mul, ElementCount.castAs<NonLoc>(), + svalBuilder.makeArrayIndex(TypeSize.getQuantity()), + svalBuilder.getArrayIndexType()); + DefinedOrUnknownSVal extentMatchesSize = svalBuilder.evalEQ( + State, Extent, SizeInBytes.castAs<DefinedOrUnknownSVal>()); + State = State->assume(extentMatchesSize, true); + } + return State; +} + void MallocChecker::checkPreStmt(const CXXDeleteExpr *DE, CheckerContext &C) const { @@ -2095,12 +2149,7 @@ void MallocChecker::reportLeak(SymbolRef Sym, ExplodedNode *N, const MemRegion *Region = nullptr; std::tie(AllocNode, Region) = getAllocationSite(N, Sym, C); - ProgramPoint P = AllocNode->getLocation(); - const Stmt *AllocationStmt = nullptr; - if (Optional<CallExitEnd> Exit = P.getAs<CallExitEnd>()) - AllocationStmt = Exit->getCalleeContext()->getCallSite(); - else if (Optional<StmtPoint> SP = P.getAs<StmtPoint>()) - AllocationStmt = SP->getStmt(); + const Stmt *AllocationStmt = PathDiagnosticLocation::getStmt(AllocNode); if (AllocationStmt) LocUsedForUniqueing = PathDiagnosticLocation::createBegin(AllocationStmt, C.getSourceManager(), @@ -2529,6 +2578,11 @@ bool MallocChecker::mayFreeAnyEscapedMemoryOrIsModeledExplicitly( return true; } + if (FName == "connectImpl" && + FD->getQualifiedNameAsString() == "QObject::connectImpl") { + return true; + } + // Handle cases where we know a buffer's /address/ can escape. // Note that the above checks handle some special cases where we know that // even though the address escapes, it's still our responsibility to free the @@ -2614,11 +2668,9 @@ static SymbolRef findFailedReallocSymbol(ProgramStateRef currState, return nullptr; } -PathDiagnosticPiece * -MallocChecker::MallocBugVisitor::VisitNode(const ExplodedNode *N, - const ExplodedNode *PrevN, - BugReporterContext &BRC, - BugReport &BR) { +std::shared_ptr<PathDiagnosticPiece> MallocChecker::MallocBugVisitor::VisitNode( + const ExplodedNode *N, const ExplodedNode *PrevN, BugReporterContext &BRC, + BugReport &BR) { ProgramStateRef state = N->getState(); ProgramStateRef statePrev = PrevN->getState(); @@ -2627,22 +2679,7 @@ MallocChecker::MallocBugVisitor::VisitNode(const ExplodedNode *N, if (!RS) return nullptr; - const Stmt *S = nullptr; - const char *Msg = nullptr; - StackHintGeneratorForSymbol *StackHint = nullptr; - - // Retrieve the associated statement. - ProgramPoint ProgLoc = N->getLocation(); - if (Optional<StmtPoint> SP = ProgLoc.getAs<StmtPoint>()) { - S = SP->getStmt(); - } else if (Optional<CallExitEnd> Exit = ProgLoc.getAs<CallExitEnd>()) { - S = Exit->getCalleeContext()->getCallSite(); - } else if (Optional<BlockEdge> Edge = ProgLoc.getAs<BlockEdge>()) { - // If an assumption was made on a branch, it should be caught - // here by looking at the state transition. - S = Edge->getSrc()->getTerminator(); - } - + const Stmt *S = PathDiagnosticLocation::getStmt(N); if (!S) return nullptr; @@ -2650,6 +2687,8 @@ MallocChecker::MallocBugVisitor::VisitNode(const ExplodedNode *N, // (__attribute__((cleanup))). // Find out if this is an interesting point and what is the kind. + const char *Msg = nullptr; + StackHintGeneratorForSymbol *StackHint = nullptr; if (Mode == Normal) { if (isAllocated(RS, RSPrev, S)) { Msg = "Memory is allocated"; @@ -2699,7 +2738,7 @@ MallocChecker::MallocBugVisitor::VisitNode(const ExplodedNode *N, // Generate the extra diagnostic. PathDiagnosticLocation Pos(S, BRC.getSourceManager(), N->getLocationContext()); - return new PathDiagnosticEventPiece(Pos, Msg, true, StackHint); + return std::make_shared<PathDiagnosticEventPiece>(Pos, Msg, true, StackHint); } void MallocChecker::printState(raw_ostream &Out, ProgramStateRef State, |
