vsk updated this revision to Diff 74606.
vsk added a comment.

- Remove the set of blacklisted object pointers; pass down a flag which 
indicates whether or not the member call check should be skipped.


https://reviews.llvm.org/D25448

Files:
  lib/CodeGen/CGExpr.cpp
  lib/CodeGen/CGExprCXX.cpp
  lib/CodeGen/CodeGenFunction.h
  lib/CodeGen/ItaniumCXXABI.cpp
  test/CodeGenCXX/ubsan-devirtualized-calls.cpp

Index: test/CodeGenCXX/ubsan-devirtualized-calls.cpp
===================================================================
--- /dev/null
+++ test/CodeGenCXX/ubsan-devirtualized-calls.cpp
@@ -0,0 +1,38 @@
+// RUN: %clang_cc1 -std=c++11 -triple %itanium_abi_triple -emit-llvm -fsanitize=vptr %s -o - | FileCheck %s
+
+struct Base1 {
+  virtual int f1() { return 1; }
+};
+
+struct Base2 {
+  virtual int f1() { return 2; }
+};
+
+struct Derived1 final : Base1 {
+  int f1() override { return 3; }
+};
+
+struct Derived2 final : Base1, Base2 {
+  int f1() override { return 3; }
+};
+
+// CHECK-LABEL: define i32 @_Z2t1v
+int t1() {
+  Derived1 d1;
+  return static_cast<Base1 *>(&d1)->f1();
+// CHECK-NOT: !nosanitize
+}
+
+// CHECK-LABEL: define i32 @_Z2t2v
+int t2() {
+  Derived2 d2;
+  return static_cast<Base1 *>(&d2)->f1();
+// CHECK-NOT: !nosanitize
+}
+
+// CHECK-LABEL: define i32 @_Z2t3v
+int t3() {
+  Derived2 d2;
+  return static_cast<Base2 *>(&d2)->f1();
+// CHECK-NOT: !nosanitize
+}
Index: lib/CodeGen/ItaniumCXXABI.cpp
===================================================================
--- lib/CodeGen/ItaniumCXXABI.cpp
+++ lib/CodeGen/ItaniumCXXABI.cpp
@@ -1456,8 +1456,8 @@
     Callee = CGM.getAddrOfCXXStructor(DD, getFromDtorType(Type));
 
   CGF.EmitCXXMemberOrOperatorCall(DD, Callee, ReturnValueSlot(),
-                                  This.getPointer(), VTT, VTTTy,
-                                  nullptr, nullptr);
+                                  This.getPointer(), VTT, VTTTy, nullptr,
+                                  nullptr, /*SkipMemberCallCheck=*/false);
 }
 
 void ItaniumCXXABI::emitVTableDefinitions(CodeGenVTables &CGVT,
@@ -1637,7 +1637,8 @@
 
   CGF.EmitCXXMemberOrOperatorCall(Dtor, Callee, ReturnValueSlot(),
                                   This.getPointer(), /*ImplicitParam=*/nullptr,
-                                  QualType(), CE, nullptr);
+                                  QualType(), CE, nullptr,
+                                  /*SkipMemberCallCheck=*/false);
   return nullptr;
 }
 
Index: lib/CodeGen/CodeGenFunction.h
===================================================================
--- lib/CodeGen/CodeGenFunction.h
+++ lib/CodeGen/CodeGenFunction.h
@@ -2084,7 +2084,8 @@
   /// appropriate size and alignment for an object of type \p Type.
   void EmitTypeCheck(TypeCheckKind TCK, SourceLocation Loc, llvm::Value *V,
                      QualType Type, CharUnits Alignment = CharUnits::Zero(),
-                     bool SkipNullCheck = false);
+                     bool SkipNullCheck = false,
+                     bool SkipMemberCallCheck = false);
 
   /// \brief Emit a check that \p Base points into an array object, which
   /// we can access at index \p Index. \p Accessed should be \c false if we
@@ -2882,7 +2883,7 @@
                               ReturnValueSlot ReturnValue, llvm::Value *This,
                               llvm::Value *ImplicitParam,
                               QualType ImplicitParamTy, const CallExpr *E,
-                              CallArgList *RtlArgs);
+                              CallArgList *RtlArgs, bool SkipMemberCallCheck);
   RValue EmitCXXDestructorCall(const CXXDestructorDecl *DD, llvm::Value *Callee,
                                llvm::Value *This, llvm::Value *ImplicitParam,
                                QualType ImplicitParamTy, const CallExpr *E,
Index: lib/CodeGen/CGExprCXX.cpp
===================================================================
--- lib/CodeGen/CGExprCXX.cpp
+++ lib/CodeGen/CGExprCXX.cpp
@@ -28,7 +28,8 @@
 commonEmitCXXMemberOrOperatorCall(CodeGenFunction &CGF, const CXXMethodDecl *MD,
                                   llvm::Value *This, llvm::Value *ImplicitParam,
                                   QualType ImplicitParamTy, const CallExpr *CE,
-                                  CallArgList &Args, CallArgList *RtlArgs) {
+                                  CallArgList &Args, CallArgList *RtlArgs,
+                                  bool SkipMemberCallCheck) {
   assert(CE == nullptr || isa<CXXMemberCallExpr>(CE) ||
          isa<CXXOperatorCallExpr>(CE));
   assert(MD->isInstance() &&
@@ -44,7 +45,9 @@
   CGF.EmitTypeCheck(isa<CXXConstructorDecl>(MD)
                         ? CodeGenFunction::TCK_ConstructorCall
                         : CodeGenFunction::TCK_MemberCall,
-                    CallLoc, This, C.getRecordType(MD->getParent()));
+                    CallLoc, This, C.getRecordType(MD->getParent()),
+                    /*Alignment=*/CharUnits::Zero(), /*SkipNullCheck=*/false,
+                    SkipMemberCallCheck);
 
   // Push the this ptr.
   const CXXRecordDecl *RD =
@@ -82,11 +85,12 @@
 RValue CodeGenFunction::EmitCXXMemberOrOperatorCall(
     const CXXMethodDecl *MD, llvm::Value *Callee, ReturnValueSlot ReturnValue,
     llvm::Value *This, llvm::Value *ImplicitParam, QualType ImplicitParamTy,
-    const CallExpr *CE, CallArgList *RtlArgs) {
+    const CallExpr *CE, CallArgList *RtlArgs, bool SkipMemberCallCheck) {
   const FunctionProtoType *FPT = MD->getType()->castAs<FunctionProtoType>();
   CallArgList Args;
   RequiredArgs required = commonEmitCXXMemberOrOperatorCall(
-      *this, MD, This, ImplicitParam, ImplicitParamTy, CE, Args, RtlArgs);
+      *this, MD, This, ImplicitParam, ImplicitParamTy, CE, Args, RtlArgs,
+      SkipMemberCallCheck);
   return EmitCall(CGM.getTypes().arrangeCXXMethodCall(Args, FPT, required),
                   Callee, ReturnValue, Args, MD);
 }
@@ -97,7 +101,7 @@
     StructorType Type) {
   CallArgList Args;
   commonEmitCXXMemberOrOperatorCall(*this, DD, This, ImplicitParam,
-                                    ImplicitParamTy, CE, Args, nullptr);
+                                    ImplicitParamTy, CE, Args, nullptr, false);
   return EmitCall(CGM.getTypes().arrangeCXXStructorDeclaration(DD, Type),
                   Callee, ReturnValueSlot(), Args, DD);
 }
@@ -175,6 +179,10 @@
     }
   }
 
+  // If we can devirtualize the method, don't emit instrumentation to check
+  // the dynamic type of the object pointer.
+  bool SkipMemberCallCheck = DevirtualizedMethod != nullptr;
+
   // C++17 demands that we evaluate the RHS of a (possibly-compound) assignment
   // operator before the LHS.
   CallArgList RtlArgStorage;
@@ -270,7 +278,7 @@
       }
       EmitCXXMemberOrOperatorCall(MD, Callee, ReturnValue, This.getPointer(),
                                   /*ImplicitParam=*/nullptr, QualType(), CE,
-                                  nullptr);
+                                  nullptr, SkipMemberCallCheck);
     }
     return RValue::get(nullptr);
   }
@@ -304,7 +312,7 @@
 
   return EmitCXXMemberOrOperatorCall(MD, Callee, ReturnValue, This.getPointer(),
                                      /*ImplicitParam=*/nullptr, QualType(), CE,
-                                     RtlArgs);
+                                     RtlArgs, SkipMemberCallCheck);
 }
 
 RValue
Index: lib/CodeGen/CGExpr.cpp
===================================================================
--- lib/CodeGen/CGExpr.cpp
+++ lib/CodeGen/CGExpr.cpp
@@ -531,7 +531,8 @@
 
 void CodeGenFunction::EmitTypeCheck(TypeCheckKind TCK, SourceLocation Loc,
                                     llvm::Value *Ptr, QualType Ty,
-                                    CharUnits Alignment, bool SkipNullCheck) {
+                                    CharUnits Alignment, bool SkipNullCheck,
+                                    bool SkipMemberCallCheck) {
   if (!sanitizePerformTypeCheck())
     return;
 
@@ -620,7 +621,8 @@
   //       or call a non-static member function
   CXXRecordDecl *RD = Ty->getAsCXXRecordDecl();
   if (SanOpts.has(SanitizerKind::Vptr) &&
-      (TCK == TCK_MemberAccess || TCK == TCK_MemberCall ||
+      (TCK == TCK_MemberAccess ||
+       (TCK == TCK_MemberCall && !SkipMemberCallCheck) ||
        TCK == TCK_DowncastPointer || TCK == TCK_DowncastReference ||
        TCK == TCK_UpcastToVirtualBase) &&
       RD && RD->hasDefinition() && RD->isDynamicClass()) {
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to