r254806 - [analyzer] Fix MemRegion crash casting non-struct to derived struct (PR25426).

Devin Coughlin via cfe-commits cfe-commits at lists.llvm.org
Fri Dec 4 16:22:36 PST 2015


Author: dcoughlin
Date: Fri Dec  4 18:22:36 2015
New Revision: 254806

URL: http://llvm.org/viewvc/llvm-project?rev=254806&view=rev
Log:
[analyzer] Fix MemRegion crash casting non-struct to derived struct (PR25426).

This commit prevents MemRegion::getAsOffset() from crashing when the analyzed
program casts a symbolic region of a non-record type to some derived type and
then attempts to access a field of the base type.

rdar://problem/23458069

Modified:
    cfe/trunk/lib/StaticAnalyzer/Core/MemRegion.cpp
    cfe/trunk/test/Analysis/reinterpret-cast.cpp

Modified: cfe/trunk/lib/StaticAnalyzer/Core/MemRegion.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Core/MemRegion.cpp?rev=254806&r1=254805&r2=254806&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Core/MemRegion.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Core/MemRegion.cpp Fri Dec  4 18:22:36 2015
@@ -1177,6 +1177,7 @@ RegionRawOffset ElementRegion::getAsArra
 /// Returns true if \p Base is an immediate base class of \p Child
 static bool isImmediateBase(const CXXRecordDecl *Child,
                             const CXXRecordDecl *Base) {
+  assert(Child && "Child must not be null");
   // Note that we do NOT canonicalize the base class here, because
   // ASTRecordLayout doesn't either. If that leads us down the wrong path,
   // so be it; at least we won't crash.
@@ -1256,18 +1257,18 @@ RegionOffset MemRegion::getAsOffset() co
       if (!Child) {
         // We cannot compute the offset of the base class.
         SymbolicOffsetBase = R;
-      }
-
-      if (RootIsSymbolic) {
-        // Base layers on symbolic regions may not be type-correct.
-        // Double-check the inheritance here, and revert to a symbolic offset
-        // if it's invalid (e.g. due to a reinterpret_cast).
-        if (BOR->isVirtual()) {
-          if (!Child->isVirtuallyDerivedFrom(BOR->getDecl()))
-            SymbolicOffsetBase = R;
-        } else {
-          if (!isImmediateBase(Child, BOR->getDecl()))
-            SymbolicOffsetBase = R;
+      } else {
+        if (RootIsSymbolic) {
+          // Base layers on symbolic regions may not be type-correct.
+          // Double-check the inheritance here, and revert to a symbolic offset
+          // if it's invalid (e.g. due to a reinterpret_cast).
+          if (BOR->isVirtual()) {
+            if (!Child->isVirtuallyDerivedFrom(BOR->getDecl()))
+              SymbolicOffsetBase = R;
+          } else {
+            if (!isImmediateBase(Child, BOR->getDecl()))
+              SymbolicOffsetBase = R;
+          }
         }
       }
 

Modified: cfe/trunk/test/Analysis/reinterpret-cast.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/reinterpret-cast.cpp?rev=254806&r1=254805&r2=254806&view=diff
==============================================================================
--- cfe/trunk/test/Analysis/reinterpret-cast.cpp (original)
+++ cfe/trunk/test/Analysis/reinterpret-cast.cpp Fri Dec  4 18:22:36 2015
@@ -102,4 +102,17 @@ int radar_13146953(void) {
   set_x1(x);
   set_x2((void *&)y);
   return *x + *y; // no warning
-}
\ No newline at end of file
+}
+
+namespace PR25426 {
+  struct Base {
+    int field;
+  };
+
+  struct Derived : Base { };
+
+  void foo(int &p) {
+    Derived &d = (Derived &)(p);
+    d.field = 2;
+  }
+}




More information about the cfe-commits mailing list