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; + } +} _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits