diff --git a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h index e4be349c02633..9b55b3cc02ee0 100644 --- a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h +++ b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h @@ -198,9 +198,11 @@ class SValBuilder { DefinedOrUnknownSVal getDerivedRegionValueSymbolVal( SymbolRef parentSymbol, const TypedValueRegion *region); - DefinedSVal getMetadataSymbolVal( - const void *symbolTag, const MemRegion *region, - const Expr *expr, QualType type, unsigned count); + DefinedSVal getMetadataSymbolVal(const void *symbolTag, + const MemRegion *region, + const Expr *expr, QualType type, + const LocationContext *LCtx, + unsigned count); DefinedSVal getFunctionPointer(const FunctionDecl *func); diff --git a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h index 087430583e0c2..f00dce568e3ae 100644 --- a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h +++ b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h @@ -186,15 +186,18 @@ class SymbolMetadata : public SymbolData { const MemRegion* R; const Stmt *S; QualType T; + const LocationContext *LCtx; unsigned Count; const void *Tag; public: SymbolMetadata(SymbolID sym, const MemRegion* r, const Stmt *s, QualType t, - unsigned count, const void *tag) - : SymbolData(SymbolMetadataKind, sym), R(r), S(s), T(t), Count(count), Tag(tag) {} + const LocationContext *LCtx, unsigned count, const void *tag) + : SymbolData(SymbolMetadataKind, sym), R(r), S(s), T(t), LCtx(LCtx), + Count(count), Tag(tag) {} const MemRegion *getRegion() const { return R; } const Stmt *getStmt() const { return S; } + const LocationContext *getLocationContext() const { return LCtx; } unsigned getCount() const { return Count; } const void *getTag() const { return Tag; } @@ -203,18 +206,19 @@ class SymbolMetadata : public SymbolData { void dumpToStream(raw_ostream &os) const override; static void Profile(llvm::FoldingSetNodeID& profile, const MemRegion *R, - const Stmt *S, QualType T, unsigned Count, - const void *Tag) { + const Stmt *S, QualType T, const LocationContext *LCtx, + unsigned Count, const void *Tag) { profile.AddInteger((unsigned) SymbolMetadataKind); profile.AddPointer(R); profile.AddPointer(S); profile.Add(T); + profile.AddPointer(LCtx); profile.AddInteger(Count); profile.AddPointer(Tag); } void Profile(llvm::FoldingSetNodeID& profile) override { - Profile(profile, R, S, T, Count, Tag); + Profile(profile, R, S, T, LCtx, Count, Tag); } // Implement isa support. @@ -435,7 +439,9 @@ class SymbolManager { /// VisitCount can be used to differentiate regions corresponding to /// different loop iterations, thus, making the symbol path-dependent. const SymbolMetadata *getMetadataSymbol(const MemRegion *R, const Stmt *S, - QualType T, unsigned VisitCount, + QualType T, + const LocationContext *LCtx, + unsigned VisitCount, const void *SymbolTag = nullptr); const SymbolCast* getCastSymbol(const SymExpr *Operand, diff --git a/clang/lib/StaticAnalyzer/Checkers/CStringChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/CStringChecker.cpp index 1f13dbad6fdb6..7cdbe88e88fd8 100644 --- a/clang/lib/StaticAnalyzer/Checkers/CStringChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/CStringChecker.cpp @@ -685,6 +685,7 @@ SVal CStringChecker::getCStringLengthForRegion(CheckerContext &C, QualType sizeTy = svalBuilder.getContext().getSizeType(); SVal strLength = svalBuilder.getMetadataSymbolVal(CStringChecker::getTag(), MR, Ex, sizeTy, + C.getLocationContext(), C.blockCount()); if (!hypothetical) { diff --git a/clang/lib/StaticAnalyzer/Core/SValBuilder.cpp b/clang/lib/StaticAnalyzer/Core/SValBuilder.cpp index 72bcdd9ecb06b..fe9a6834f6a04 100644 --- a/clang/lib/StaticAnalyzer/Core/SValBuilder.cpp +++ b/clang/lib/StaticAnalyzer/Core/SValBuilder.cpp @@ -182,11 +182,12 @@ SValBuilder::getConjuredHeapSymbolVal(const Expr *E, DefinedSVal SValBuilder::getMetadataSymbolVal(const void *symbolTag, const MemRegion *region, const Expr *expr, QualType type, + const LocationContext *LCtx, unsigned count) { assert(SymbolManager::canSymbolicate(type) && "Invalid metadata symbol type"); SymbolRef sym = - SymMgr.getMetadataSymbol(region, expr, type, count, symbolTag); + SymMgr.getMetadataSymbol(region, expr, type, LCtx, count, symbolTag); if (Loc::isLocType(type)) return loc::MemRegionVal(MemMgr.getSymbolicRegion(sym)); diff --git a/clang/lib/StaticAnalyzer/Core/SymbolManager.cpp b/clang/lib/StaticAnalyzer/Core/SymbolManager.cpp index b8b4af1179e52..6b99ca510be72 100644 --- a/clang/lib/StaticAnalyzer/Core/SymbolManager.cpp +++ b/clang/lib/StaticAnalyzer/Core/SymbolManager.cpp @@ -216,17 +216,18 @@ SymbolManager::getExtentSymbol(const SubRegion *R) { return cast(SD); } -const SymbolMetadata* +const SymbolMetadata * SymbolManager::getMetadataSymbol(const MemRegion* R, const Stmt *S, QualType T, + const LocationContext *LCtx, unsigned Count, const void *SymbolTag) { llvm::FoldingSetNodeID profile; - SymbolMetadata::Profile(profile, R, S, T, Count, SymbolTag); + SymbolMetadata::Profile(profile, R, S, T, LCtx, Count, SymbolTag); void *InsertPos; SymExpr *SD = DataSet.FindNodeOrInsertPos(profile, InsertPos); if (!SD) { SD = (SymExpr*) BPAlloc.Allocate(); - new (SD) SymbolMetadata(SymbolCounter, R, S, T, Count, SymbolTag); + new (SD) SymbolMetadata(SymbolCounter, R, S, T, LCtx, Count, SymbolTag); DataSet.InsertNode(SD, InsertPos); ++SymbolCounter; } diff --git a/clang/test/Analysis/string.c b/clang/test/Analysis/string.c index 2803362ba43e9..e541219d05a2d 100644 --- a/clang/test/Analysis/string.c +++ b/clang/test/Analysis/string.c @@ -154,6 +154,23 @@ void strlen_liveness(const char *x) { clang_analyzer_eval(strlen(x) < 5); // expected-warning{{FALSE}} } + +size_t strlenWrapper(const char *str) { + return strlen(str); +} + +extern void invalidate(char *s); + +void testStrlenCallee() { + char str[42]; + invalidate(str); + size_t lenBefore = strlenWrapper(str); + invalidate(str); + size_t lenAfter = strlenWrapper(str); + clang_analyzer_eval(lenBefore == lenAfter); // expected-warning{{UNKNOWN}} +} + + //===----------------------------------------------------------------------=== // strnlen() //===----------------------------------------------------------------------===