Bug 1448494 - Use NonDereferenceable in DDLogger - r=froydnj draft
authorGerald Squelart <gsquelart@mozilla.com>
Thu, 29 Mar 2018 01:18:08 +1100
changeset 791770 cc802706d1c2c5a60ac692d132038c8418f8dedd
parent 791769 3c4011da64d84f1b19991742b76bafbffa90d590
push id108895
push usergsquelart@mozilla.com
push dateSat, 05 May 2018 04:43:31 +0000
reviewersfroydnj
bugs1448494
milestone61.0a1
Bug 1448494 - Use NonDereferenceable in DDLogger - r=froydnj DecoderDoctorLifeLogger now passes a NonDereferenceable pointer to LogConstruction/LogDestruction, to avoid UBSan errors. It is possible because DDLogger only keeps pointer values for logging (the pointer type is converted to a string), these pointers are never actually dereferenced. Note that the uintptr_t value() is converted to `const void*` because that's what DDLogger uses everywhere; an upcoming bug will make DDLogger use NonDereferenceable everywhere instead. MozReview-Commit-ID: K5wJrGVCub0
dom/media/doctor/DecoderDoctorLogger.h
--- a/dom/media/doctor/DecoderDoctorLogger.h
+++ b/dom/media/doctor/DecoderDoctorLogger.h
@@ -8,16 +8,17 @@
 #define DecoderDoctorLogger_h_
 
 #include "DDLoggedTypeTraits.h"
 #include "DDLogCategory.h"
 #include "DDLogValue.h"
 #include "mozilla/Atomics.h"
 #include "mozilla/DefineEnum.h"
 #include "mozilla/MozPromise.h"
+#include "mozilla/NonDereferenceable.h"
 #include "nsString.h"
 
 namespace mozilla {
 
 // Main class used to capture log messages from the media stack, and to
 // retrieve processed messages associated with an HTMLMediaElement.
 //
 // The logging APIs are designed to work as fast as possible (in most cases
@@ -280,57 +281,70 @@ public:
     Log(aSubjectTypeName,
         aSubjectPointer,
         DDLogCategory::_DerivedConstruction,
         "",
         DDLogValue{ DDLogObject{ DDLoggedTypeTraits<B>::Name(), aBase } });
   }
 
   template<typename Subject>
-  static void
-  LogConstruction(const Subject* aSubject)
+  static void LogConstruction(NonDereferenceable<const Subject> aSubject)
   {
     using Traits = DDLoggedTypeTraits<Subject>;
     if (!Traits::HasBase::value) {
       Log(DDLoggedTypeTraits<Subject>::Name(),
-          aSubject,
+          reinterpret_cast<const void*>(aSubject.value()),
           DDLogCategory::_Construction,
           "",
           DDLogValue{ DDNoValue{} });
     } else {
       Log(DDLoggedTypeTraits<Subject>::Name(),
-          aSubject,
+          reinterpret_cast<const void*>(aSubject.value()),
           DDLogCategory::_DerivedConstruction,
           "",
           DDLogValue{ DDLogObject{
             DDLoggedTypeTraits<typename Traits::BaseType>::Name(),
-            static_cast<const typename Traits::BaseType*>(aSubject) } });
+            reinterpret_cast<const void*>(
+              NonDereferenceable<const typename Traits::BaseType>(aSubject)
+                .value()) } });
     }
   }
 
+  template<typename Subject>
+  static void LogConstruction(const Subject* aSubject)
+  {
+    LogConstruction(NonDereferenceable<const Subject>(aSubject));
+  }
+
   static void LogDestruction(const char* aSubjectTypeName,
                              const void* aSubjectPointer)
   {
     Log(aSubjectTypeName,
         aSubjectPointer,
         DDLogCategory::_Destruction,
         "",
         DDLogValue{ DDNoValue{} });
   }
 
   template<typename Subject>
-  static void LogDestruction(const Subject* aSubject)
+  static void LogDestruction(NonDereferenceable<const Subject> aSubject)
   {
     Log(DDLoggedTypeTraits<Subject>::Name(),
-        aSubject,
+        reinterpret_cast<const void*>(aSubject.value()),
         DDLogCategory::_Destruction,
         "",
         DDLogValue{ DDNoValue{} });
   }
 
+  template<typename Subject>
+  static void LogDestruction(const Subject* aSubject)
+  {
+    LogDestruction(NonDereferenceable<const Subject>(aSubject));
+  }
+
   template<typename P, typename C>
   static void LinkParentAndChild(const P* aParent,
                                  const char* aLinkName,
                                  const C* aChild)
   {
     if (aChild) {
       Log(DDLoggedTypeTraits<P>::Name(),
           aParent,
@@ -474,33 +488,23 @@ private:
 // Base class to automatically record a class lifetime. Usage:
 //   class SomeClass : public DecoderDoctorLifeLogger<SomeClass>
 //   {
 //     ...
 template<typename T>
 class DecoderDoctorLifeLogger
 {
 public:
-#if defined(__clang__)
-  // This constructor is called before the `T` object is fully constructed, and
-  // pointers are not dereferenced anyway, so UBSan shouldn't check vptrs.
-  __attribute__((no_sanitize("vptr")))
-#endif
   DecoderDoctorLifeLogger()
   {
-    DecoderDoctorLogger::LogConstruction(static_cast<const T*>(this));
+    DecoderDoctorLogger::LogConstruction(NonDereferenceable<const T>(this));
   }
-#if defined(__clang__)
-  // This destructor is called after the `T` object is partially destructed, and
-  // pointers are not dereferenced anyway, so UBSan shouldn't check vptrs.
-  __attribute__((no_sanitize("vptr")))
-#endif
   ~DecoderDoctorLifeLogger()
   {
-    DecoderDoctorLogger::LogDestruction(static_cast<const T*>(this));
+    DecoderDoctorLogger::LogDestruction(NonDereferenceable<const T>(this));
   }
 };
 
 // Macros to help lazily-evaluate arguments, only after we have checked that
 // logging is enabled.
 
 // Log a single value; see DDLogValue for allowed types.
 #define DDLOG(_category, _label, _arg)                                         \