Bug 1340581 - Add some release-grade assertions to mozilla::Tokenizer to catch string overflows. r=froydnj
authorHonza Bambas <honzab.moz@firemni.cz>
Wed, 22 Feb 2017 06:53:00 -0500
changeset 373422 ec3487e17b2f04d247601d1019c219c762c1318f
parent 373421 bc0798e58200e0dbfd862a9ff8bda3e13848b046
child 373423 8128e71288af4e1455db51ff32962b4bff73edba
push id10863
push userjlorenzo@mozilla.com
push dateMon, 06 Mar 2017 23:02:23 +0000
treeherdermozilla-aurora@0931190cd725 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersfroydnj
bugs1340581
milestone54.0a1
Bug 1340581 - Add some release-grade assertions to mozilla::Tokenizer to catch string overflows. r=froydnj
xpcom/ds/Tokenizer.cpp
--- a/xpcom/ds/Tokenizer.cpp
+++ b/xpcom/ds/Tokenizer.cpp
@@ -267,16 +267,18 @@ Tokenizer::Claim(nsACString& aResult, Cl
 }
 
 void
 Tokenizer::Claim(nsDependentCSubstring& aResult, ClaimInclusion aInclusion)
 {
   nsACString::const_char_iterator close = aInclusion == EXCLUDE_LAST
     ? mRollback
     : mCursor;
+
+  MOZ_RELEASE_ASSERT(close >= mRecord, "Overflow!");
   aResult.Rebind(mRecord, close - mRecord);
 }
 
 // TokenizerBase
 
 TokenizerBase::TokenizerBase(const char* aWhitespaces,
                              const char* aAdditionalWordChars)
   : mPastEof(false)
@@ -371,16 +373,17 @@ TokenizerBase::Parse(Token& aToken) cons
     if (!mInputFinished) {
       return mCursor;
     }
 
     aToken = Token::EndOfFile();
     return mEnd;
   }
 
+  MOZ_RELEASE_ASSERT(mEnd >= mCursor, "Overflow!");
   nsACString::size_type available = mEnd - mCursor;
 
   uint32_t longestCustom = 0;
   for (UniquePtr<Token> const& custom : mCustomTokens) {
     if (IsCustom(mCursor, *custom, &longestCustom)) {
       aToken = *custom;
       return mCursor + custom->mCustom.Length();
     }
@@ -558,16 +561,20 @@ TokenizerBase::IsCustom(const nsACString
   if (!aCustomToken.mCustomEnabled) {
     return false;
   }
 
   if (aLongest) {
     *aLongest = std::max(*aLongest, aCustomToken.mCustom.Length());
   }
 
+  // This is not very likely to happen according to how we call this method
+  // and since it's on a hot path, it's just a diagnostic assert, 
+  // not a release assert.
+  MOZ_DIAGNOSTIC_ASSERT(mEnd >= caret, "Overflow?");
   uint32_t inputLength = mEnd - caret;
   if (aCustomToken.mCustom.Length() > inputLength) {
     return false;
   }
 
   nsDependentCSubstring inputFragment(caret, aCustomToken.mCustom.Length());
   if (aCustomToken.mCustomCaseInsensitivity == CASE_INSENSITIVE) {
     return inputFragment.Equals(aCustomToken.mCustom, nsCaseInsensitiveUTF8StringComparator());
@@ -618,16 +625,17 @@ TokenizerBase::Token::operator=(const To
   mCustomEnabled = aOther.mCustomEnabled;
   return *this;
 }
 
 void
 TokenizerBase::Token::AssignFragment(nsACString::const_char_iterator begin,
                                      nsACString::const_char_iterator end)
 {
+  MOZ_RELEASE_ASSERT(end >= begin, "Overflow!");
   mFragment.Rebind(begin, end - begin);
 }
 
 // static
 TokenizerBase::Token
 TokenizerBase::Token::Raw()
 {
   Token t;