rtc::MsanUninitialized to mark a trivially copiable object as uninitialized

Setting a default value for a class members prevents memory sanitizer
to behave correctly and may confuse the reader.
Instead, one should use rtc::MsanUninitialized, which creates an object of
a given type and marks its memory as uninitialized.
This prevents issues in production (due to uninitialized memory) and
allows MemorySantizier to catch invalid access patterns.

Bug: webrtc:8762
Change-Id: I74c79caa9c19ea85708e89e24bc5516c4d9d12a1
Reviewed-on: https://webrtc-review.googlesource.com/52342
Commit-Queue: Alessio Bazzica <alessiob@webrtc.org>
Reviewed-by: Karl Wiberg <kwiberg@webrtc.org>
Reviewed-by: Alessio Bazzica <alessiob@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#22773}
diff --git a/rtc_base/sanitizer.h b/rtc_base/sanitizer.h
index 1b94e1e..23a748f 100644
--- a/rtc_base/sanitizer.h
+++ b/rtc_base/sanitizer.h
@@ -11,7 +11,11 @@
 #ifndef RTC_BASE_SANITIZER_H_
 #define RTC_BASE_SANITIZER_H_
 
-#include <stddef.h>  // for size_t
+#include <stddef.h>  // For size_t.
+
+#ifdef __cplusplus
+#include <type_traits>
+#endif
 
 #if defined(__has_feature)
 #if __has_feature(address_sanitizer)
@@ -90,6 +94,17 @@
 #ifdef __cplusplus
 
 namespace rtc {
+namespace sanitizer_impl {
+
+template <typename T>
+constexpr bool IsTriviallyCopyable() {
+  return static_cast<bool>(std::is_trivially_copy_constructible<T>::value &&
+                           (std::is_trivially_copy_assignable<T>::value ||
+                            !std::is_copy_assignable<T>::value) &&
+                           std::is_trivially_destructible<T>::value);
+}
+
+}  // namespace sanitizer_impl
 
 template <typename T>
 inline void AsanPoison(const T& mem) {
@@ -107,6 +122,15 @@
 }
 
 template <typename T>
+inline T MsanUninitialized(T t) {
+  // TODO(bugs.webrtc.org/8762): Switch to std::is_trivially_copyable when it
+  // becomes available in downstream projects.
+  static_assert(sanitizer_impl::IsTriviallyCopyable<T>(), "");
+  rtc_MsanMarkUninitialized(&t, sizeof(T), 1);
+  return t;
+}
+
+template <typename T>
 inline void MsanCheckInitialized(const T& mem) {
   rtc_MsanCheckInitialized(mem.data(), sizeof(mem.data()[0]), mem.size());
 }