Bug 1349719 - Share max capacity logic in nsTString. r=froydnj, a=lizzard
authorEric Rahm <erahm@mozilla.com>
Thu, 23 Mar 2017 12:32:53 -0700
changeset 377210 d2a680d1fbd8dbe6b143adae1b74379b40a6ad21
parent 377209 35bf6122572ace2295ed0d0a13c3ba6edd0a3e40
child 377211 e80c1fc7722833bea78fe336870a2b532802d27e
push id7168
push userryanvm@gmail.com
push dateThu, 06 Apr 2017 21:11:01 +0000
treeherdermozilla-beta@65eb65fb5933 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersfroydnj, lizzard
bugs1349719
milestone53.0
Bug 1349719 - Share max capacity logic in nsTString. r=froydnj, a=lizzard This refactors the max capacity logic so that both |MutatePrep| and |Adopt| can share it. MozReview-Commit-ID: CMn4kiAoWub
xpcom/string/nsTSubstring.cpp
xpcom/string/nsTSubstring.h
--- a/xpcom/string/nsTSubstring.cpp
+++ b/xpcom/string/nsTSubstring.cpp
@@ -5,16 +5,21 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "mozilla/CheckedInt.h"
 #include "mozilla/double-conversion.h"
 #include "mozilla/MemoryReporting.h"
 
 using double_conversion::DoubleToStringConverter;
 
+const nsTSubstring_CharT::size_type nsTSubstring_CharT::kMaxCapacity =
+    (nsTSubstring_CharT::size_type(-1) /
+        2 - sizeof(nsStringBuffer)) /
+    sizeof(nsTSubstring_CharT::char_type) - 2;
+
 #ifdef XPCOM_STRING_CONSTRUCTOR_OUT_OF_LINE
 nsTSubstring_CharT::nsTSubstring_CharT(char_type* aData, size_type aLength,
                                        uint32_t aFlags)
   : mData(aData),
     mLength(aLength),
     mFlags(aFlags)
 {
   if (aFlags & F_OWNED) {
@@ -51,23 +56,18 @@ nsTSubstring_CharT::MutatePrep(size_type
 
   size_type curCapacity = Capacity();
 
   // If |aCapacity > kMaxCapacity|, then our doubling algorithm may not be
   // able to allocate it.  Just bail out in cases like that.  We don't want
   // to be allocating 2GB+ strings anyway.
   static_assert((sizeof(nsStringBuffer) & 0x1) == 0,
                 "bad size for nsStringBuffer");
-  const size_type kMaxCapacity =
-    (size_type(-1) / 2 - sizeof(nsStringBuffer)) / sizeof(char_type) - 2;
-  if (aCapacity > kMaxCapacity) {
-    // Also assert for |aCapacity| equal to |size_type(-1)|, since we used to
-    // use that value to flag immutability.
-    NS_ASSERTION(aCapacity != size_type(-1), "Bogus capacity");
-    return false;
+  if (!CheckCapacity(aCapacity)) {
+      return false;
   }
 
   // |curCapacity == 0| means that the buffer is immutable or 0-sized, so we
   // need to allocate a new buffer. We cannot use the existing buffer even
   // though it might be large enough.
 
   if (curCapacity != 0) {
     if (aCapacity <= curCapacity) {
@@ -505,16 +505,18 @@ nsTSubstring_CharT::Adopt(char_type* aDa
 {
   if (aData) {
     ::ReleaseData(mData, mFlags);
 
     if (aLength == size_type(-1)) {
       aLength = char_traits::length(aData);
     }
 
+    MOZ_RELEASE_ASSERT(CheckCapacity(aLength), "adopting a too-long string");
+
     mData = aData;
     mLength = aLength;
     SetDataFlags(F_TERMINATED | F_OWNED);
 
     STRING_STAT_INCREMENT(Adopt);
     // Treat this as construction of a "StringAdopt" object for leak
     // tracking purposes.
     MOZ_LOG_CTOR(mData, "StringAdopt", 1);
--- a/xpcom/string/nsTSubstring.h
+++ b/xpcom/string/nsTSubstring.h
@@ -1025,29 +1025,44 @@ protected:
      *   !(f2.begin >= f1.aEnd || f2.aEnd <= f1.begin)
      *
      * Simplified, that gives us:
      */
     return (aStart < (mData + mLength) && aEnd > mData);
   }
 
   /**
+   * Checks if the given capacity is valid for this string type.
+   */
+  static MOZ_MUST_USE bool CheckCapacity(size_type aCapacity) {
+    if (aCapacity > kMaxCapacity) {
+      // Also assert for |aCapacity| equal to |size_type(-1)|, since we used to
+      // use that value to flag immutability.
+      NS_ASSERTION(aCapacity != size_type(-1), "Bogus capacity");
+      return false;
+    }
+
+    return true;
+  }
+
+  /**
    * this helper function stores the specified dataFlags in mFlags
    */
   void SetDataFlags(uint32_t aDataFlags)
   {
     NS_ASSERTION((aDataFlags & 0xFFFF0000) == 0, "bad flags");
     mFlags = aDataFlags | (mFlags & 0xFFFF0000);
   }
 
   void NS_FASTCALL ReplaceLiteral(index_type aCutStart, size_type aCutLength,
                                   const char_type* aData, size_type aLength);
 
   static int AppendFunc(void* aArg, const char* aStr, uint32_t aLen);
 
+  static const size_type kMaxCapacity;
 public:
 
   // NOTE: this method is declared public _only_ for convenience for
   // callers who don't have access to the original nsLiteralString_CharT.
   void NS_FASTCALL AssignLiteral(const char_type* aData, size_type aLength);
 
   // mFlags is a bitwise combination of the following flags.  the meaning
   // and interpretation of these flags is an implementation detail.