sberg updated this revision to Diff 125152.
sberg added a comment.

(Diff 125121 had accidentally contained a spurious "}". Fixed that now.)


https://reviews.llvm.org/D40720

Files:
  clang/lib/CodeGen/CGExpr.cpp
  compiler-rt/lib/ubsan/ubsan_handlers.cc
  compiler-rt/lib/ubsan/ubsan_handlers.h
  compiler-rt/test/ubsan/TestCases/TypeCheck/Function/function.cpp

Index: compiler-rt/test/ubsan/TestCases/TypeCheck/Function/function.cpp
===================================================================
--- compiler-rt/test/ubsan/TestCases/TypeCheck/Function/function.cpp
+++ compiler-rt/test/ubsan/TestCases/TypeCheck/Function/function.cpp
@@ -1,4 +1,4 @@
-// RUN: %clangxx -fsanitize=function %s -O3 -g -o %t
+// RUN: %clangxx -std=c++17 -fsanitize=function %s -O3 -g -o %t
 // RUN: %run %t 2>&1 | FileCheck %s
 // Verify that we can disable symbolization if needed:
 // RUN: %env_ubsan_opts=symbolize=0 %run %t 2>&1 | FileCheck %s --check-prefix=NOSYM
@@ -23,9 +23,47 @@
   reinterpret_cast<void (*)(int)>(reinterpret_cast<uintptr_t>(f))(42);
 }
 
+void f1(int) {}
+void f2(unsigned int) {}
+void f3(int) noexcept {}
+void f4(unsigned int) noexcept {}
+
+void check_noexcept_calls() {
+  void (*p1)(int);
+  p1 = &f1;
+  p1(0);
+  p1 = reinterpret_cast<void (*)(int)>(&f2);
+  // CHECK: function.cpp:[[@LINE+2]]:3: runtime error: call to function f2(unsigned int) through pointer to incorrect function type 'void (*)(int)'
+  // NOSYM: function.cpp:[[@LINE+1]]:3: runtime error: call to function (unknown) through pointer to incorrect function type 'void (*)(int)'
+  p1(0);
+  p1 = &f3;
+  p1(0);
+  p1 = reinterpret_cast<void (*)(int)>(&f4);
+  // CHECK: function.cpp:[[@LINE+2]]:3: runtime error: call to function f4(unsigned int) through pointer to incorrect function type 'void (*)(int)'
+  // NOSYM: function.cpp:[[@LINE+1]]:3: runtime error: call to function (unknown) through pointer to incorrect function type 'void (*)(int)'
+  p1(0);
+
+  void (*p2)(int) noexcept;
+  p2 = reinterpret_cast<void (*)(int) noexcept>(&f1);
+  // CHECK: function.cpp:[[@LINE+2]]:3: runtime error: call to function f1(int) through pointer to incorrect function type 'void (*)(int) noexcept'
+  // NOSYM: function.cpp:[[@LINE+1]]:3: runtime error: call to function (unknown) through pointer to incorrect function type 'void (*)(int) noexcept'
+  p2(0);
+  p2 = reinterpret_cast<void (*)(int) noexcept>(&f2);
+  // CHECK: function.cpp:[[@LINE+2]]:3: runtime error: call to function f2(unsigned int) through pointer to incorrect function type 'void (*)(int) noexcept'
+  // NOSYM: function.cpp:[[@LINE+1]]:3: runtime error: call to function (unknown) through pointer to incorrect function type 'void (*)(int) noexcept'
+  p2(0);
+  p2 = &f3;
+  p2(0);
+  p2 = reinterpret_cast<void (*)(int) noexcept>(&f4);
+  // CHECK: function.cpp:[[@LINE+2]]:3: runtime error: call to function f4(unsigned int) through pointer to incorrect function type 'void (*)(int) noexcept'
+  // NOSYM: function.cpp:[[@LINE+1]]:3: runtime error: call to function (unknown) through pointer to incorrect function type 'void (*)(int) noexcept'
+  p2(0);
+}
+
 int main(void) {
   make_valid_call();
   make_invalid_call();
+  check_noexcept_calls();
   // Check that no more errors will be printed.
   // CHECK-NOT: runtime error: call to function
   // NOSYM-NOT: runtime error: call to function
Index: compiler-rt/lib/ubsan/ubsan_handlers.h
===================================================================
--- compiler-rt/lib/ubsan/ubsan_handlers.h
+++ compiler-rt/lib/ubsan/ubsan_handlers.h
@@ -140,11 +140,12 @@
 struct FunctionTypeMismatchData {
   SourceLocation Loc;
   const TypeDescriptor &Type;
+  ValueHandle NonNoexceptRTTI;
 };
 
 RECOVERABLE(function_type_mismatch,
             FunctionTypeMismatchData *Data,
-            ValueHandle Val)
+            ValueHandle Val, ValueHandle RTTI)
 
 struct NonNullReturnData {
   SourceLocation AttrLoc;
Index: compiler-rt/lib/ubsan/ubsan_handlers.cc
===================================================================
--- compiler-rt/lib/ubsan/ubsan_handlers.cc
+++ compiler-rt/lib/ubsan/ubsan_handlers.cc
@@ -18,6 +18,9 @@
 
 #include "sanitizer_common/sanitizer_common.h"
 
+#include <cstring>
+#include <typeinfo>
+
 using namespace __sanitizer;
 using namespace __ubsan;
 
@@ -462,14 +465,50 @@
   Die();
 }
 
-static void handleFunctionTypeMismatch(FunctionTypeMismatchData *Data,
-                                       ValueHandle Function,
+// Check that TI2 represents the same function type as TI1, except that TI2 has
+// "noexcept" and TI1 does not.
+static bool checkForAddedNoexcept(const std::type_info *TI1,
+                                  const std::type_info *TI2) {
+  const char *Mangled1 = TI1->name();
+  const char *Mangled2 = TI2->name();
+
+  // Skip <CV-qualifiers>.
+  if (*Mangled1 == 'V') {
+    if (*Mangled2 != 'V')
+      return false;
+    ++Mangled1;
+    ++Mangled2;
+  }
+  if (*Mangled1 == 'K') {
+    if (*Mangled2 != 'K')
+      return false;
+    ++Mangled1;
+    ++Mangled2;
+  }
+
+  // Check for "Do" <exception-spec>.
+  if (*Mangled2++ != 'D' || *Mangled2++ != 'o')
+    return false;
+
+  // Check remainder is identical.
+  return std::strcmp(Mangled1, Mangled2) == 0;
+}
+
+static bool handleFunctionTypeMismatch(FunctionTypeMismatchData *Data,
+                                       ValueHandle Function, ValueHandle RTTI,
                                        ReportOptions Opts) {
+  if (Data->NonNoexceptRTTI &&
+      checkForAddedNoexcept(
+          reinterpret_cast<std::type_info *>(Data->NonNoexceptRTTI),
+          reinterpret_cast<std::type_info *>(RTTI))) {
+    return false;
+  }
+
   SourceLocation CallLoc = Data->Loc.acquire();
   ErrorType ET = ErrorType::FunctionTypeMismatch;
 
   if (ignoreReport(CallLoc, Opts, ET))
-    return;
+    return true;
 
   ScopedReport R(Opts, CallLoc, ET);
 
@@ -482,20 +521,21 @@
        "call to function %0 through pointer to incorrect function type %1")
       << FName << Data->Type;
   Diag(FLoc, DL_Note, "%0 defined here") << FName;
+  return true;
 }
 
 void
 __ubsan::__ubsan_handle_function_type_mismatch(FunctionTypeMismatchData *Data,
-                                               ValueHandle Function) {
+                                               ValueHandle Function, ValueHandle RTTI) {
   GET_REPORT_OPTIONS(false);
-  handleFunctionTypeMismatch(Data, Function, Opts);
+  handleFunctionTypeMismatch(Data, Function, RTTI, Opts);
 }
 
 void __ubsan::__ubsan_handle_function_type_mismatch_abort(
-    FunctionTypeMismatchData *Data, ValueHandle Function) {
+    FunctionTypeMismatchData *Data, ValueHandle Function, ValueHandle RTTI) {
   GET_REPORT_OPTIONS(true);
-  handleFunctionTypeMismatch(Data, Function, Opts);
-  Die();
+  if (handleFunctionTypeMismatch(Data, Function, RTTI, Opts))
+    Die();
 }
 
 static void handleNonNullReturn(NonNullReturnData *Data, SourceLocation *LocPtr,
Index: clang/lib/CodeGen/CGExpr.cpp
===================================================================
--- clang/lib/CodeGen/CGExpr.cpp
+++ clang/lib/CodeGen/CGExpr.cpp
@@ -4465,10 +4465,14 @@
           Builder.CreateICmpEQ(CalleeRTTI, FTRTTIConst);
       llvm::Constant *StaticData[] = {
         EmitCheckSourceLocation(E->getLocStart()),
-        EmitCheckTypeDescriptor(CalleeType)
+        EmitCheckTypeDescriptor(CalleeType),
+        cast<FunctionProtoType>(FnType)->isNothrow(getContext())
+          ? llvm::Constant::getNullValue(FTRTTIConst->getType())
+          : FTRTTIConst
       };
       EmitCheck(std::make_pair(CalleeRTTIMatch, SanitizerKind::Function),
-                SanitizerHandler::FunctionTypeMismatch, StaticData, CalleePtr);
+                SanitizerHandler::FunctionTypeMismatch, StaticData,
+                {CalleePtr, CalleeRTTI});
 
       Builder.CreateBr(Cont);
       EmitBlock(Cont);
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to