[clang] b30521c - [analyzer] Wrong type cast occurs during pointer dereferencing after type punning

Denys Petrov via cfe-commits cfe-commits at lists.llvm.org
Wed Apr 28 15:03:45 PDT 2021


Author: Denys Petrov
Date: 2021-04-29T01:03:38+03:00
New Revision: b30521c28a4dc1b94d793385e4144ede5822b2c1

URL: https://github.com/llvm/llvm-project/commit/b30521c28a4dc1b94d793385e4144ede5822b2c1
DIFF: https://github.com/llvm/llvm-project/commit/b30521c28a4dc1b94d793385e4144ede5822b2c1.diff

LOG: [analyzer] Wrong type cast occurs during pointer dereferencing after type punning

Summary: During pointer dereferencing CastRetrievedVal uses wrong type from the Store after type punning. Namely, the pointer casts to another type and then assigns with a value of one more another type. It produces NonLoc value when Loc is expected.

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

Fixes:
https://bugs.llvm.org/show_bug.cgi?id=37503
https://bugs.llvm.org/show_bug.cgi?id=49007

Added: 
    

Modified: 
    clang/lib/StaticAnalyzer/Core/SValBuilder.cpp
    clang/test/Analysis/casts.c
    clang/test/Analysis/string.c

Removed: 
    


################################################################################
diff  --git a/clang/lib/StaticAnalyzer/Core/SValBuilder.cpp b/clang/lib/StaticAnalyzer/Core/SValBuilder.cpp
index a49099384d2a..f376922754bf 100644
--- a/clang/lib/StaticAnalyzer/Core/SValBuilder.cpp
+++ b/clang/lib/StaticAnalyzer/Core/SValBuilder.cpp
@@ -748,8 +748,8 @@ SVal SValBuilder::evalCastSubKind(loc::MemRegionVal V, QualType CastTy,
       // pointers as well.
       // FIXME: We really need a single good function to perform casts for us
       // correctly every time we need it.
+      const MemRegion *R = V.getRegion();
       if (CastTy->isPointerType() && !CastTy->isVoidPointerType()) {
-        const MemRegion *R = V.getRegion();
         if (const auto *SR = dyn_cast<SymbolicRegion>(R)) {
           QualType SRTy = SR->getSymbol()->getType();
           if (!hasSameUnqualifiedPointeeType(SRTy, CastTy)) {
@@ -758,6 +758,13 @@ SVal SValBuilder::evalCastSubKind(loc::MemRegionVal V, QualType CastTy,
           }
         }
       }
+      // Next fixes pointer dereference using type 
diff erent from its initial
+      // one. See PR37503 and PR49007 for details.
+      if (const auto *ER = dyn_cast<ElementRegion>(R)) {
+        R = StateMgr.getStoreManager().castRegion(ER, CastTy);
+        return loc::MemRegionVal(R);
+      }
+
       return V;
     }
 

diff  --git a/clang/test/Analysis/casts.c b/clang/test/Analysis/casts.c
index ae7b84641b13..702e53a82f2e 100644
--- a/clang/test/Analysis/casts.c
+++ b/clang/test/Analysis/casts.c
@@ -245,3 +245,8 @@ double no_crash_reinterpret_double_as_sym_ptr(double a, void * b) {
   return a * a;
 }
 
+void no_crash_reinterpret_char_as_uchar(char ***a, int *b) {
+  *(unsigned char **)a = (unsigned char *)b;
+  if (**a == 0) // no-crash
+    ;
+}

diff  --git a/clang/test/Analysis/string.c b/clang/test/Analysis/string.c
index debcea481adb..2bf34ca757e7 100644
--- a/clang/test/Analysis/string.c
+++ b/clang/test/Analysis/string.c
@@ -363,6 +363,20 @@ void strcpy_no_overflow(char *y) {
     strcpy(x, y); // no-warning
 }
 
+// PR37503
+void *get_void_ptr();
+char ***type_punned_ptr;
+void strcpy_no_assertion(char c) {
+  *(unsigned char **)type_punned_ptr = (unsigned char *)(get_void_ptr());
+  strcpy(**type_punned_ptr, &c); // no-crash
+}
+
+// PR49007
+char f(char ***c, int *i) {
+  *(void **)c = i + 1;
+  return (**c)[0]; // no-crash
+}
+
 //===----------------------------------------------------------------------===
 // stpcpy()
 //===----------------------------------------------------------------------===


        


More information about the cfe-commits mailing list