[PATCH] D52189: [analyzer] Fix a crash regression on casting opaque symbolic pointers from unrelated base classes to derived classes.

Artem Dergachev via Phabricator via cfe-commits cfe-commits at lists.llvm.org
Mon Sep 17 13:33:14 PDT 2018


NoQ created this revision.
NoQ added reviewers: dcoughlin, xazax.hun, a.sidorin, george.karpenkov, szepet, rnkovacs.
Herald added subscribers: cfe-commits, Szelethus, mikhail.ramalho, baloghadamsoftware.

Commit https://reviews.llvm.org/D51191 causes a crash when a pointer to a completely unrelated type `UnrelatedT` (eg., opaque struct pattern) is being casted from base class `BaseT` to derived class `DerivedT`, which results in an ill-formed region `Derived{SymRegion{$<UnrelatedT x>}, DerivedT}`.

I guess we should prevent these from appearing somehow.


Repository:
  rC Clang

https://reviews.llvm.org/D52189

Files:
  lib/StaticAnalyzer/Core/Store.cpp
  test/Analysis/casts.cpp


Index: test/Analysis/casts.cpp
===================================================================
--- test/Analysis/casts.cpp
+++ test/Analysis/casts.cpp
@@ -70,5 +70,30 @@
   clang_analyzer_eval(c->x); // expected-warning{{UNKNOWN}}
   clang_analyzer_eval(c->y); // expected-warning{{TRUE}}
 }
+} // namespace base_to_derived_double_inheritance
+
+namespace base_to_derived_opaque_class {
+class NotInt {
+public:
+  operator int() { return !x; } // no-crash
+  int x;
+};
+
+typedef struct Opaque *OpaqueRef;
+
+class Transparent {
+public:
+  int getNotInt() { return NI; }
+  NotInt NI;
+};
+
+class SubTransparent : public Transparent {};
+
+SubTransparent *castToDerived(Transparent *TRef) {
+  return (SubTransparent *)TRef;
 }
 
+void counterValue(OpaqueRef ORef) {
+  castToDerived(reinterpret_cast<Transparent *>(ORef))->getNotInt();
+}
+} // namespace base_to_derived_opaque_class
Index: lib/StaticAnalyzer/Core/Store.cpp
===================================================================
--- lib/StaticAnalyzer/Core/Store.cpp
+++ lib/StaticAnalyzer/Core/Store.cpp
@@ -375,8 +375,17 @@
     MR = Uncasted;
   }
 
+  // If we're casting a symbolic base pointer to a derived class, use
+  // CXXDerivedObjectRegion to represent the cast. If it's a pointer to an
+  // unrelated type, it must be a weird reinterpret_cast and we have to
+  // be fine with ElementRegion.
   if (const auto *SR = dyn_cast<SymbolicRegion>(MR)) {
-    return loc::MemRegionVal(MRMgr.getCXXDerivedObjectRegion(TargetClass, SR));
+    QualType T = SR->getSymbol()->getType();
+    const CXXRecordDecl *SourceClass = T->getPointeeCXXRecordDecl();
+    if (TargetClass->isDerivedFrom(SourceClass))
+      return loc::MemRegionVal(
+          MRMgr.getCXXDerivedObjectRegion(TargetClass, SR));
+    return loc::MemRegionVal(GetElementZeroRegion(SR, TargetType));
   }
 
   // We failed if the region we ended up with has perfect type info.


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D52189.165816.patch
Type: text/x-patch
Size: 1924 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20180917/34611d73/attachment.bin>


More information about the cfe-commits mailing list