Bug 1317545 - Check new length in ReplaceSubstring. r=froydnj
authorEric Rahm <erahm@mozilla.com>
Mon, 28 Nov 2016 13:29:04 -0800
changeset 324489 fdcc35477bd0d4c6a13875c5cdb7e1a6c8ca98c6
parent 324488 3fa64db7e2ff51f6608364003119469a94b9363d
child 324490 30798ceb7d632bbb8ec8a0a6901e55a1ef473024
push id24
push usermaklebus@msu.edu
push dateTue, 20 Dec 2016 03:11:33 +0000
reviewersfroydnj
bugs1317545
milestone53.0a1
Bug 1317545 - Check new length in ReplaceSubstring. r=froydnj MozReview-Commit-ID: 5Qvusd3twhM
xpcom/string/nsTStringObsolete.cpp
--- a/xpcom/string/nsTStringObsolete.cpp
+++ b/xpcom/string/nsTStringObsolete.cpp
@@ -1,15 +1,16 @@
 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "nsTArray.h"
+#include "mozilla/CheckedInt.h"
 
 /**
  * nsTString::Find
  *
  * aOffset specifies starting index
  * aCount specifies number of string compares (iterations)
  */
 
@@ -488,17 +489,17 @@ nsTString_CharT::ReplaceSubstring(const 
                                   const fallible_t&)
 {
   if (aTarget.Length() == 0)
     return true;
 
   // Remember all of the non-matching parts.
   AutoTArray<Segment, 16> nonMatching;
   uint32_t i = 0;
-  uint32_t newLength = 0;
+  mozilla::CheckedUint32 newLength;
   while (true)
   {
     int32_t r = FindSubstring(mData + i, mLength - i, static_cast<const char_type*>(aTarget.Data()), aTarget.Length(), false);
     int32_t until = (r == kNotFound) ? mLength - i : r;
     nonMatching.AppendElement(Segment(i, until));
     newLength += until;
     if (r == kNotFound) {
       break;
@@ -509,31 +510,35 @@ nsTString_CharT::ReplaceSubstring(const 
     if (i >= mLength) {
       // Add an auxiliary entry at the end of the list to help as an edge case
       // for the algorithms below.
       nonMatching.AppendElement(Segment(mLength, 0));
       break;
     }
   }
 
+  if (!newLength.isValid()) {
+    return false;
+  }
+
   // If there's only one non-matching segment, then the target string was not
   // found, and there's nothing to do.
   if (nonMatching.Length() == 1) {
     MOZ_ASSERT(nonMatching[0].mBegin == 0 && nonMatching[0].mLength == mLength,
                "We should have the correct non-matching segment.");
     return true;
   }
 
   // Make sure that we can mutate our buffer.
   // Note that we always allocate at least an mLength sized buffer, because the
   // rest of the algorithm relies on having access to all of the original
   // string.  In other words, we over-allocate in the shrinking case.
   char_type* oldData;
   uint32_t oldFlags;
-  if (!MutatePrep(XPCOM_MAX(mLength, newLength), &oldData, &oldFlags))
+  if (!MutatePrep(XPCOM_MAX(mLength, newLength.value()), &oldData, &oldFlags))
     return false;
   if (oldData) {
     // Copy all of the old data to the new buffer.
     char_traits::copy(mData, oldData, mLength);
     ::ReleaseData(oldData, oldFlags);
   }
 
   if (aTarget.Length() >= aNewValue.Length()) {
@@ -566,17 +571,17 @@ nsTString_CharT::ReplaceSubstring(const 
       // Write the i'th replacement immediately before the new i'th non-matching
       // segment.
       char_traits::copy(destinationSegmentPtr - aNewValue.Length(),
                         aNewValue.Data(), aNewValue.Length());
     }
   }
 
   // Adjust the length and make sure the string is null terminated.
-  mLength = newLength;
+  mLength = newLength.value();
   mData[mLength] = char_type(0);
 
   return true;
 }
 
 /**
  * nsTString::Trim
  */