Bug 1381080 patch 4 - Assert that strings whose static type requires a null-terminated buffer aren't assign a non-null-terminated buffer. r=erahm
authorL. David Baron <dbaron@dbaron.org>
Thu, 20 Jul 2017 15:46:59 -0700
changeset 418721 9b76213c99cfcb05a53d381edd272cbc29e6fadf
parent 418720 235ac09dfdb2412295ac98834fb111e9198b0474
child 418722 5a663e876c3c2d76703368581b033f28495c10e1
push id7566
push usermtabara@mozilla.com
push dateWed, 02 Aug 2017 08:25:16 +0000
treeherdermozilla-beta@86913f512c3c [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerserahm
bugs1381080
milestone56.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1381080 patch 4 - Assert that strings whose static type requires a null-terminated buffer aren't assign a non-null-terminated buffer. r=erahm I actually couldn't figure out a way to trigger this assertion with the current string code without doing invalid casts, but there are things we may want to add to the string code in the future that might risk hitting this (e.g., move constructors, promoting various rebind methods to nsA[C]String), so I think it's worth asserting. MozReview-Commit-ID: 4R0dYuTfrFW
xpcom/string/nsTSubstring.cpp
xpcom/string/nsTSubstring.h
--- a/xpcom/string/nsTSubstring.cpp
+++ b/xpcom/string/nsTSubstring.cpp
@@ -18,16 +18,17 @@ const nsTSubstring_CharT::size_type nsTS
     sizeof(nsTSubstring_CharT::char_type) - 2;
 
 #ifdef XPCOM_STRING_CONSTRUCTOR_OUT_OF_LINE
 nsTSubstring_CharT::nsTSubstring_CharT(char_type* aData, size_type aLength,
                                        DataFlags aDataFlags,
                                        ClassFlags aClassFlags)
   : nsTStringRepr_CharT(aData, aLength, aDataFlags, aClassFlags)
 {
+  AssertValid();
   MOZ_RELEASE_ASSERT(CheckCapacity(aLength), "String is too large.");
 
   if (aDataFlags & DataFlags::OWNED) {
     STRING_STAT_INCREMENT(Adopt);
     MOZ_LOG_CTOR(mData, "StringAdopt", 1);
   }
 }
 #endif /* XPCOM_STRING_CONSTRUCTOR_OUT_OF_LINE */
--- a/xpcom/string/nsTSubstring.h
+++ b/xpcom/string/nsTSubstring.h
@@ -992,25 +992,35 @@ public:
    */
   void ForgetSharedBuffer()
   {
     if (mDataFlags & DataFlags::SHARED) {
       SetToEmptyBuffer();
     }
   }
 
+protected:
+  void AssertValid()
+  {
+    MOZ_ASSERT(!(mClassFlags & ClassFlags::NULL_TERMINATED) ||
+               (mDataFlags & DataFlags::TERMINATED),
+               "String classes whose static type guarantees a null-terminated "
+               "buffer must not be assigned a non-null-terminated buffer.");
+  }
+
 public:
 
   /**
    * this is public to support automatic conversion of tuple to string
    * base type, which helps avoid converting to nsTAString.
    */
   MOZ_IMPLICIT nsTSubstring_CharT(const substring_tuple_type& aTuple)
     : nsTStringRepr_CharT(nullptr, 0, DataFlags(0), ClassFlags(0))
   {
+    AssertValid();
     Assign(aTuple);
   }
 
   size_t SizeOfExcludingThisIfUnshared(mozilla::MallocSizeOf aMallocSizeOf)
   const;
   size_t SizeOfIncludingThisIfUnshared(mozilla::MallocSizeOf aMallocSizeOf)
   const;
 
@@ -1041,63 +1051,69 @@ public:
 
 protected:
 
   // default initialization
   nsTSubstring_CharT()
     : nsTStringRepr_CharT(char_traits::sEmptyBuffer, 0, DataFlags::TERMINATED,
                           ClassFlags(0))
   {
+    AssertValid();
   }
 
   // copy-constructor, constructs as dependent on given object
   // (NOTE: this is for internal use only)
   nsTSubstring_CharT(const self_type& aStr)
     : nsTStringRepr_CharT(aStr.mData, aStr.mLength,
                           aStr.mDataFlags & (DataFlags::TERMINATED | DataFlags::VOIDED),
                           ClassFlags(0))
   {
+    AssertValid();
   }
 
   // initialization with ClassFlags
   explicit nsTSubstring_CharT(ClassFlags aClassFlags)
     : nsTStringRepr_CharT(char_traits::sEmptyBuffer, 0, DataFlags::TERMINATED,
                           aClassFlags)
   {
+    AssertValid();
   }
 
  /**
    * allows for direct initialization of a nsTSubstring object.
    */
   nsTSubstring_CharT(char_type* aData, size_type aLength,
                      DataFlags aDataFlags, ClassFlags aClassFlags)
 // XXXbz or can I just include nscore.h and use NS_BUILD_REFCNT_LOGGING?
 #if defined(DEBUG) || defined(FORCE_BUILD_REFCNT_LOGGING)
 #define XPCOM_STRING_CONSTRUCTOR_OUT_OF_LINE
     ;
 #else
 #undef XPCOM_STRING_CONSTRUCTOR_OUT_OF_LINE
     : nsTStringRepr_CharT(aData, aLength, aDataFlags, aClassFlags)
   {
+    AssertValid();
     MOZ_RELEASE_ASSERT(CheckCapacity(aLength), "String is too large.");
   }
 #endif /* DEBUG || FORCE_BUILD_REFCNT_LOGGING */
 
   void SetToEmptyBuffer()
   {
     mData = char_traits::sEmptyBuffer;
     mLength = 0;
     mDataFlags = DataFlags::TERMINATED;
+    AssertValid();
   }
 
   void SetData(char_type* aData, size_type aLength, DataFlags aDataFlags)
   {
     mData = aData;
     mLength = aLength;
     mDataFlags = aDataFlags;
+    AssertValid();
   }
 
   /**
    * this function releases mData and does not change the value of
    * any of its member variables.  in other words, this function acts
    * like a destructor.
    */
   void NS_FASTCALL Finalize();