]> granicus.if.org Git - clang/commitdiff
[analyzer] Add LocationContext information to SymbolMetadata.
authorArtem Dergachev <artem.dergachev@gmail.com>
Wed, 17 Aug 2016 15:37:52 +0000 (15:37 +0000)
committerArtem Dergachev <artem.dergachev@gmail.com>
Wed, 17 Aug 2016 15:37:52 +0000 (15:37 +0000)
Like SymbolConjured, SymbolMetadata also needs to be uniquely
identified by the moment of its birth.

Such moments are coded by the (Statement, LocationContext, Block count) triples.
Each such triple represents the moment of analyzing a statement with a certain
call backtrace, with corresponding CFG block having been entered a given amount
of times during analysis of the current code body.

The LocationContext information was accidentally omitted for SymbolMetadata,
which leads to reincarnation of SymbolMetadata upon re-entering a code body
with a different backtrace; the new symbol is incorrectly unified with
the old symbol, which leads to unsound assumptions.

Patch by Alexey Sidorin!

Differential Revision: https://reviews.llvm.org/D21978

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@278937 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h
include/clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h
lib/StaticAnalyzer/Checkers/CStringChecker.cpp
lib/StaticAnalyzer/Core/SValBuilder.cpp
lib/StaticAnalyzer/Core/SymbolManager.cpp
test/Analysis/string.c

index e4be349c02633197eb4f8ef079a8e5ce4240d81c..9b55b3cc02ee0788bf06c64eb171b0fdab9e54f1 100644 (file)
@@ -198,9 +198,11 @@ public:
   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);
   
index 087430583e0c22d20a41080bd00f366fa3362876..f00dce568e3ae62162b79da97920fb8ffe1dccb8 100644 (file)
@@ -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 @@ public:
   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<T> support.
@@ -435,7 +439,9 @@ public:
   /// 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,
index 1f13dbad6fdb64afb64307c80454adaaebd85994..7cdbe88e88fd8b9f8bf627399a9b33a1b21bf418 100644 (file)
@@ -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) {
index 72bcdd9ecb06b602d0fd3dfae24977134bb42ab5..fe9a6834f6a047d2fcdb52639486b23f57374c9f 100644 (file)
@@ -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));
index b8b4af1179e52f3ba79ae0539feac5c9e578317b..6b99ca510be72a12b7d6abda21b23f442011b876 100644 (file)
@@ -216,17 +216,18 @@ SymbolManager::getExtentSymbol(const SubRegion *R) {
   return cast<SymbolExtent>(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<SymbolMetadata>();
-    new (SD) SymbolMetadata(SymbolCounter, R, S, T, Count, SymbolTag);
+    new (SD) SymbolMetadata(SymbolCounter, R, S, T, LCtx, Count, SymbolTag);
     DataSet.InsertNode(SD, InsertPos);
     ++SymbolCounter;
   }
index 2803362ba43e9bf8e4ad1b8f1e407a00aa84c7b4..e541219d05a2de20a6ea671caabce339a85c49a2 100644 (file)
@@ -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()
 //===----------------------------------------------------------------------===