From: George Karpenkov Date: Fri, 3 Aug 2018 23:19:07 +0000 (+0000) Subject: [analyzer] Do not crash in NoStoreFuncVisitor notes if an unexpected region is found. X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=b319a856c2fb1c61915ab0185fa0e416a3910182;p=clang [analyzer] Do not crash in NoStoreFuncVisitor notes if an unexpected region is found. Just do not generate the note at all in that case. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@338935 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp b/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp index 8793755ad3..f6957e064b 100644 --- a/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp +++ b/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp @@ -351,10 +351,7 @@ public: ArrayRef parameters = getCallParameters(Call); for (unsigned I = 0; I < Call->getNumArgs() && I < parameters.size(); ++I) { - Optional AdjustedIdx = Call->getAdjustedParameterIndex(I); - if (!AdjustedIdx) - continue; - const ParmVarDecl *PVD = parameters[*AdjustedIdx]; + const ParmVarDecl *PVD = parameters[I]; SVal S = Call->getArgSVal(I); bool ParamIsReferenceType = PVD->getType()->isReferenceType(); std::string ParamName = PVD->getNameAsString(); @@ -565,15 +562,19 @@ private: SmallString<256> sbuf; llvm::raw_svector_ostream os(sbuf); os << "Returning without writing to '"; - prettyPrintRegionName(FirstElement, FirstIsReferenceType, MatchedRegion, - FieldChain, IndirectionLevel, os); + + // Do not generate the note if failed to pretty-print. + if (!prettyPrintRegionName(FirstElement, FirstIsReferenceType, + MatchedRegion, FieldChain, IndirectionLevel, os)) + return nullptr; os << "'"; return std::make_shared(L, os.str()); } /// Pretty-print region \p MatchedRegion to \p os. - void prettyPrintRegionName(StringRef FirstElement, bool FirstIsReferenceType, + /// \return Whether printing succeeded. + bool prettyPrintRegionName(StringRef FirstElement, bool FirstIsReferenceType, const MemRegion *MatchedRegion, const RegionVector &FieldChain, int IndirectionLevel, @@ -598,6 +599,7 @@ private: for (const MemRegion *R : RegionSequence) { // Just keep going up to the base region. + // Element regions may appear due to casts. if (isa(R) || isa(R)) continue; @@ -608,6 +610,10 @@ private: os << Sep; + // Can only reasonably pretty-print DeclRegions. + if (!isa(R)) + return false; + const auto *DR = cast(R); Sep = DR->getValueType()->isAnyPointerType() ? "->" : "."; DR->getDecl()->getDeclName().print(os, PP); @@ -617,6 +623,7 @@ private: prettyPrintFirstElement(FirstElement, /*MoreItemsExpected=*/false, IndirectionLevel, os); + return true; } /// Print first item in the chain, return new separator. diff --git a/test/Analysis/diagnostics/no-store-func-path-notes.cpp b/test/Analysis/diagnostics/no-store-func-path-notes.cpp index 3d7003ead2..b869f81b6d 100644 --- a/test/Analysis/diagnostics/no-store-func-path-notes.cpp +++ b/test/Analysis/diagnostics/no-store-func-path-notes.cpp @@ -333,3 +333,27 @@ int useMaybeInitializeIndirectlyWithPointer() { return z; // expected-warning{{Undefined or garbage value returned to caller}} // expected-note@-1{{Undefined or garbage value returned to caller}} } + +//////// + +struct HasFieldA { + int x; +}; + +struct HasFieldB { + int x; +}; + +void maybeInitializeHasField(HasFieldA *b) { + if (coin()) // expected-note{{Assuming the condition is false}} + // expected-note@-1{{Taking false branch}} + ((HasFieldB*)b)->x = 120; +} + +int forceElementRegionApperence() { + HasFieldA a; + maybeInitializeHasField(&a); // expected-note{{Calling 'maybeInitializeHasField'}} + // expected-note@-1{{Returning from 'maybeInitializeHasField'}} + return ((HasFieldB*)&a)->x; // expected-warning{{Undefined or garbage value returned to caller}} + // expected-note@-1{{Undefined or garbage value returned to caller}} +}