Disable UBSAN on dlsym-loaded function pointer call

Workaround for known false-positive: https://github.com/google/sanitizers/issues/911

Bug: chromium:348087176
Bug: chromium:42251292
Change-Id: I9c41b4608f079bd5eef9373e76c1e5ac218fffc1
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/194343
Reviewed-by: dan sinclair <dsinclair@chromium.org>
Commit-Queue: Antonio Maiorano <amaiorano@google.com>
diff --git a/src/tint/lang/hlsl/validate/validate.cc b/src/tint/lang/hlsl/validate/validate.cc
index 027756f..75f5389 100644
--- a/src/tint/lang/hlsl/validate/validate.cc
+++ b/src/tint/lang/hlsl/validate/validate.cc
@@ -57,6 +57,21 @@
 // the SUCCEEDED and FAILED macros that C-style cast to HRESULT.
 TINT_DISABLE_WARNING_OLD_STYLE_CAST
 
+namespace {
+using PFN_DXC_CREATE_INSTANCE = HRESULT(__stdcall*)(REFCLSID rclsid,
+                                                    REFIID riid,
+                                                    LPVOID* ppCompiler);
+
+// Wrap the call to DxcCreateInstance via the dlsym-loaded function pointer
+// to disable UBSAN on it. This is to workaround a known UBSAN false
+// positive: https://github.com/google/sanitizers/issues/911
+TINT_NO_SANITIZE("undefined")
+HRESULT CallDxcCreateInstance(PFN_DXC_CREATE_INSTANCE dxc_create_instance,
+                              CComPtr<IDxcCompiler3>& dxc_compiler) {
+    return dxc_create_instance(CLSID_DxcCompiler, IID_PPV_ARGS(&dxc_compiler));
+}
+}  // namespace
+
 namespace tint::hlsl::validate {
 
 Result ValidateUsingDXC(const std::string& dxc_path,
@@ -97,8 +112,6 @@
     HRESULT hr;
 
     // Load the dll and get the DxcCreateInstance function
-    using PFN_DXC_CREATE_INSTANCE =
-        HRESULT(__stdcall*)(REFCLSID rclsid, REFIID riid, LPVOID * ppCompiler);
     PFN_DXC_CREATE_INSTANCE dxc_create_instance = nullptr;
 #ifdef _WIN32
     HMODULE dxcLib = LoadLibraryA(dxc_path.c_str());
@@ -136,7 +149,7 @@
     }
 
     CComPtr<IDxcCompiler3> dxc_compiler;
-    hr = dxc_create_instance(CLSID_DxcCompiler, IID_PPV_ARGS(&dxc_compiler));
+    hr = CallDxcCreateInstance(dxc_create_instance, dxc_compiler);
     CHECK_HR(hr, "DxcCreateInstance failed");
 
     for (auto ep : entry_points) {
diff --git a/src/tint/utils/macros/compiler.h b/src/tint/utils/macros/compiler.h
index 6379c92..6a2c818 100644
--- a/src/tint/utils/macros/compiler.h
+++ b/src/tint/utils/macros/compiler.h
@@ -32,6 +32,18 @@
 
 #define TINT_REQUIRE_SEMICOLON static_assert(true)
 
+#if defined(__has_attribute)
+#define TINT_HAS_ATTRIBUTE(x) __has_attribute(x)
+#else
+#define TINT_HAS_ATTRIBUTE(x) 0
+#endif
+
+#if TINT_HAS_ATTRIBUTE(no_sanitize)
+#define TINT_NO_SANITIZE(instrumentation) __attribute__((no_sanitize(instrumentation)))
+#else
+#define TINT_NO_SANITIZE(instrumentation)
+#endif
+
 #if defined(_MSC_VER) && !defined(__clang__)
 ////////////////////////////////////////////////////////////////////////////////
 // MSVC