Title: [239439] trunk
Revision
239439
Author
[email protected]
Date
2018-12-20 08:06:44 -0800 (Thu, 20 Dec 2018)

Log Message

JSTests:
WTF::String and StringImpl overflow MaxLength
https://bugs.webkit.org/show_bug.cgi?id=192853
<rdar://problem/45726906>

Reviewed by Mark Lam.

* stress/string-16bit-repeat-overflow.js: Added.
(catch):

Source/WTF:
Consistently use MaxLength for all WTF strings
https://bugs.webkit.org/show_bug.cgi?id=192853
<rdar://problem/45726906>

Reviewed by Mark Lam.

MaxLength was introduced to be INT_MAX for WTF::String and StringImpl,
but all the assertions were still done using UINT_MAX. Change it to
use MaxLength for all checks.

* wtf/text/StringImpl.cpp:
(WTF::StringImpl::createUninitializedInternalNonEmpty):
(WTF::StringImpl::reallocateInternal):
(WTF::StringImpl::create):
(WTF::StringImpl::convertToLowercaseWithoutLocale):
(WTF::StringImpl::convertToUppercaseWithoutLocale):
(WTF::StringImpl::convertToLowercaseWithLocale):
(WTF::StringImpl::convertToUppercaseWithLocale):
(WTF::StringImpl::foldCase):
(WTF::StringImpl::find):
(WTF::StringImpl::replace):
(WTF::StringImpl::utf8ForCharacters):
(WTF::StringImpl::tryGetUtf8ForRange const):
* wtf/text/StringImpl.h:
(WTF::lengthOfNullTerminatedString):
(WTF::StringImpl::tryCreateUninitialized):
(WTF::StringImpl::adopt):
(WTF::StringImpl::maxInternalLength):
* wtf/text/WTFString.cpp:
(WTF::String::append):
(WTF::String::insert):
(WTF::String::fromUTF8):
* wtf/text/WTFString.h:
(WTF::String::reverseFind const):

Modified Paths

Added Paths

Diff

Modified: trunk/JSTests/ChangeLog (239438 => 239439)


--- trunk/JSTests/ChangeLog	2018-12-20 11:59:05 UTC (rev 239438)
+++ trunk/JSTests/ChangeLog	2018-12-20 16:06:44 UTC (rev 239439)
@@ -1,3 +1,14 @@
+2018-12-20  Tadeu Zagallo  <[email protected]>
+
+        WTF::String and StringImpl overflow MaxLength
+        https://bugs.webkit.org/show_bug.cgi?id=192853
+        <rdar://problem/45726906>
+
+        Reviewed by Mark Lam.
+
+        * stress/string-16bit-repeat-overflow.js: Added.
+        (catch):
+
 2018-12-19  Ross Kirsling  <[email protected]>
 
         Unreviewed follow-up to r192914.

Added: trunk/JSTests/stress/string-16bit-repeat-overflow.js (0 => 239439)


--- trunk/JSTests/stress/string-16bit-repeat-overflow.js	                        (rev 0)
+++ trunk/JSTests/stress/string-16bit-repeat-overflow.js	2018-12-20 16:06:44 UTC (rev 239439)
@@ -0,0 +1,9 @@
+var exception;
+try {
+    print('\ud000'.repeat(2**30));
+} catch (e) {
+    exception = e;
+}
+
+if (exception != "Error: Out of memory")
+    throw "FAILED";

Modified: trunk/Source/WTF/ChangeLog (239438 => 239439)


--- trunk/Source/WTF/ChangeLog	2018-12-20 11:59:05 UTC (rev 239438)
+++ trunk/Source/WTF/ChangeLog	2018-12-20 16:06:44 UTC (rev 239439)
@@ -1,3 +1,40 @@
+2018-12-20  Tadeu Zagallo  <[email protected]>
+
+        Consistently use MaxLength for all WTF strings
+        https://bugs.webkit.org/show_bug.cgi?id=192853
+        <rdar://problem/45726906>
+
+        Reviewed by Mark Lam.
+
+        MaxLength was introduced to be INT_MAX for WTF::String and StringImpl,
+        but all the assertions were still done using UINT_MAX. Change it to
+        use MaxLength for all checks.
+
+        * wtf/text/StringImpl.cpp:
+        (WTF::StringImpl::createUninitializedInternalNonEmpty):
+        (WTF::StringImpl::reallocateInternal):
+        (WTF::StringImpl::create):
+        (WTF::StringImpl::convertToLowercaseWithoutLocale):
+        (WTF::StringImpl::convertToUppercaseWithoutLocale):
+        (WTF::StringImpl::convertToLowercaseWithLocale):
+        (WTF::StringImpl::convertToUppercaseWithLocale):
+        (WTF::StringImpl::foldCase):
+        (WTF::StringImpl::find):
+        (WTF::StringImpl::replace):
+        (WTF::StringImpl::utf8ForCharacters):
+        (WTF::StringImpl::tryGetUtf8ForRange const):
+        * wtf/text/StringImpl.h:
+        (WTF::lengthOfNullTerminatedString):
+        (WTF::StringImpl::tryCreateUninitialized):
+        (WTF::StringImpl::adopt):
+        (WTF::StringImpl::maxInternalLength):
+        * wtf/text/WTFString.cpp:
+        (WTF::String::append):
+        (WTF::String::insert):
+        (WTF::String::fromUTF8):
+        * wtf/text/WTFString.h:
+        (WTF::String::reverseFind const):
+
 2018-12-19  Chris Dumez  <[email protected]>
 
         wtf/Optional.h: move-constructor and move-assignment operator should disengage the value being moved from

Modified: trunk/Source/WTF/wtf/text/StringImpl.cpp (239438 => 239439)


--- trunk/Source/WTF/wtf/text/StringImpl.cpp	2018-12-20 11:59:05 UTC (rev 239438)
+++ trunk/Source/WTF/wtf/text/StringImpl.cpp	2018-12-20 16:06:44 UTC (rev 239439)
@@ -193,7 +193,7 @@
     // Allocate a single buffer large enough to contain the StringImpl
     // struct as well as the data which it contains. This removes one
     // heap allocation from this call.
-    if (length > ((std::numeric_limits<unsigned>::max() - sizeof(StringImpl)) / sizeof(CharacterType)))
+    if (length > maxInternalLength<CharacterType>())
         CRASH();
     StringImpl* string = static_cast<StringImpl*>(fastMalloc(allocationSize<CharacterType>(length)));
 
@@ -222,7 +222,7 @@
     }
 
     // Same as createUninitialized() except here we use fastRealloc.
-    if (length > ((std::numeric_limits<unsigned>::max() - sizeof(StringImpl)) / sizeof(CharacterType)))
+    if (length > maxInternalLength<CharacterType>())
         return makeUnexpected(UTF8ConversionError::OutOfMemory);
 
     originalString->~StringImpl();
@@ -307,7 +307,7 @@
     if (!string)
         return *empty();
     size_t length = strlen(reinterpret_cast<const char*>(string));
-    if (length > std::numeric_limits<unsigned>::max())
+    if (length > MaxLength)
         CRASH();
     return create(string, length);
 }
@@ -377,7 +377,7 @@
         return newImpl;
     }
 
-    if (m_length > static_cast<unsigned>(std::numeric_limits<int32_t>::max()))
+    if (m_length > MaxLength)
         CRASH();
     int32_t length = m_length;
 
@@ -429,7 +429,7 @@
     // few actual calls to upper() are no-ops, so it wouldn't be worth
     // the extra time for pre-scanning.
 
-    if (m_length > static_cast<unsigned>(std::numeric_limits<int32_t>::max()))
+    if (m_length > MaxLength)
         CRASH();
     int32_t length = m_length;
 
@@ -541,7 +541,7 @@
     // this last part into a shared function that takes a locale string, since this is
     // just like the end of that function.
 
-    if (m_length > static_cast<unsigned>(std::numeric_limits<int32_t>::max()))
+    if (m_length > MaxLength)
         CRASH();
     int length = m_length;
 
@@ -572,7 +572,7 @@
     if (!needsTurkishCasingRules(localeIdentifier) || find('i') == notFound)
         return convertToUppercaseWithoutLocale();
 
-    if (m_length > static_cast<unsigned>(std::numeric_limits<int32_t>::max()))
+    if (m_length > MaxLength)
         CRASH();
     int length = m_length;
 
@@ -657,7 +657,7 @@
         }
     }
 
-    if (m_length > static_cast<unsigned>(std::numeric_limits<int32_t>::max()))
+    if (m_length > MaxLength)
         CRASH();
 
     auto upconvertedCharacters = StringView(*this).upconvertedCharacters();
@@ -935,7 +935,7 @@
     if (!matchString)
         return notFound;
     size_t matchStringLength = strlen(reinterpret_cast<const char*>(matchString));
-    if (matchStringLength > std::numeric_limits<unsigned>::max())
+    if (matchStringLength > MaxLength)
         CRASH();
     unsigned matchLength = matchStringLength;
     if (!matchLength)
@@ -1307,7 +1307,7 @@
     if (!lengthToReplace && !lengthToInsert)
         return *this;
 
-    if ((length() - lengthToReplace) >= (std::numeric_limits<unsigned>::max() - lengthToInsert))
+    if ((length() - lengthToReplace) >= (MaxLength - lengthToInsert))
         CRASH();
 
     if (is8Bit() && (!string || string->is8Bit())) {
@@ -1364,12 +1364,12 @@
     if (!matchCount)
         return *this;
 
-    if (repStrLength && matchCount > std::numeric_limits<unsigned>::max() / repStrLength)
+    if (repStrLength && matchCount > MaxLength / repStrLength)
         CRASH();
 
     unsigned replaceSize = matchCount * repStrLength;
     unsigned newSize = m_length - matchCount;
-    if (newSize >= (std::numeric_limits<unsigned>::max() - replaceSize))
+    if (newSize >= (MaxLength - replaceSize))
         CRASH();
 
     newSize += replaceSize;
@@ -1440,12 +1440,12 @@
     if (!matchCount)
         return *this;
 
-    if (repStrLength && matchCount > std::numeric_limits<unsigned>::max() / repStrLength)
+    if (repStrLength && matchCount > MaxLength / repStrLength)
         CRASH();
 
     unsigned replaceSize = matchCount * repStrLength;
     unsigned newSize = m_length - matchCount;
-    if (newSize >= (std::numeric_limits<unsigned>::max() - replaceSize))
+    if (newSize >= (MaxLength - replaceSize))
         CRASH();
 
     newSize += replaceSize;
@@ -1525,10 +1525,10 @@
         return *this;
     
     unsigned newSize = m_length - matchCount * patternLength;
-    if (repStrLength && matchCount > std::numeric_limits<unsigned>::max() / repStrLength)
+    if (repStrLength && matchCount > MaxLength / repStrLength)
         CRASH();
 
-    if (newSize > (std::numeric_limits<unsigned>::max() - matchCount * repStrLength))
+    if (newSize > (MaxLength - matchCount * repStrLength))
         CRASH();
 
     newSize += matchCount * repStrLength;
@@ -1804,7 +1804,7 @@
 {
     if (!length)
         return CString("", 0);
-    if (length > std::numeric_limits<unsigned>::max() / 3)
+    if (length > MaxLength / 3)
         return makeUnexpected(UTF8ConversionError::OutOfMemory);
     Vector<char, 1024> bufferVector(length * 3);
     char* buffer = bufferVector.data();
@@ -1818,7 +1818,7 @@
 {
     if (!length)
         return CString("", 0);
-    if (length > std::numeric_limits<unsigned>::max() / 3)
+    if (length > MaxLength / 3)
         return makeUnexpected(UTF8ConversionError::OutOfMemory);
     Vector<char, 1024> bufferVector(length * 3);
     char* buffer = bufferVector.data();
@@ -1846,7 +1846,7 @@
     //  * We could allocate a CStringBuffer with an appropriate size to
     //    have a good chance of being able to write the string into the
     //    buffer without reallocing (say, 1.5 x length).
-    if (length > std::numeric_limits<unsigned>::max() / 3)
+    if (length > MaxLength / 3)
         return makeUnexpected(UTF8ConversionError::OutOfMemory);
     Vector<char, 1024> bufferVector(length * 3);
 

Modified: trunk/Source/WTF/wtf/text/StringImpl.h (239438 => 239439)


--- trunk/Source/WTF/wtf/text/StringImpl.h	2018-12-20 11:59:05 UTC (rev 239438)
+++ trunk/Source/WTF/wtf/text/StringImpl.h	2018-12-20 16:06:44 UTC (rev 239439)
@@ -379,7 +379,7 @@
     // its own copy of the string.
     Ref<StringImpl> isolatedCopy() const;
 
-    WTF_EXPORT_PRIVATE Ref<StringImpl> substring(unsigned position, unsigned length = std::numeric_limits<unsigned>::max());
+    WTF_EXPORT_PRIVATE Ref<StringImpl> substring(unsigned position, unsigned length = MaxLength);
 
     UChar at(unsigned) const;
     UChar operator[](unsigned i) const { return at(i); }
@@ -437,8 +437,8 @@
     WTF_EXPORT_PRIVATE size_t findIgnoringASCIICase(const StringImpl*) const;
     WTF_EXPORT_PRIVATE size_t findIgnoringASCIICase(const StringImpl*, unsigned startOffset) const;
 
-    WTF_EXPORT_PRIVATE size_t reverseFind(UChar, unsigned index = std::numeric_limits<unsigned>::max());
-    WTF_EXPORT_PRIVATE size_t reverseFind(StringImpl*, unsigned index = std::numeric_limits<unsigned>::max());
+    WTF_EXPORT_PRIVATE size_t reverseFind(UChar, unsigned index = MaxLength);
+    WTF_EXPORT_PRIVATE size_t reverseFind(StringImpl*, unsigned index = MaxLength);
 
     WTF_EXPORT_PRIVATE bool startsWith(const StringImpl*) const;
     WTF_EXPORT_PRIVATE bool startsWith(const StringImpl&) const;
@@ -495,6 +495,7 @@
 
 private:
     template<typename> static size_t allocationSize(Checked<size_t> tailElementCount);
+    template<typename> static size_t maxInternalLength();
     template<typename> static size_t tailOffset();
 
     bool requiresCopy() const;
@@ -569,10 +570,10 @@
 size_t find(const LChar*, unsigned length, CodeUnitMatchFunction, unsigned index = 0);
 size_t find(const UChar*, unsigned length, CodeUnitMatchFunction, unsigned index = 0);
 
-template<typename CharacterType> size_t reverseFindLineTerminator(const CharacterType*, unsigned length, unsigned index = std::numeric_limits<unsigned>::max());
-template<typename CharacterType> size_t reverseFind(const CharacterType*, unsigned length, CharacterType matchCharacter, unsigned index = std::numeric_limits<unsigned>::max());
-size_t reverseFind(const UChar*, unsigned length, LChar matchCharacter, unsigned index = std::numeric_limits<unsigned>::max());
-size_t reverseFind(const LChar*, unsigned length, UChar matchCharacter, unsigned index = std::numeric_limits<unsigned>::max());
+template<typename CharacterType> size_t reverseFindLineTerminator(const CharacterType*, unsigned length, unsigned index = StringImpl::MaxLength);
+template<typename CharacterType> size_t reverseFind(const CharacterType*, unsigned length, CharacterType matchCharacter, unsigned index = StringImpl::MaxLength);
+size_t reverseFind(const UChar*, unsigned length, LChar matchCharacter, unsigned index = StringImpl::MaxLength);
+size_t reverseFind(const LChar*, unsigned length, UChar matchCharacter, unsigned index = StringImpl::MaxLength);
 
 template<size_t inlineCapacity> bool equalIgnoringNullity(const Vector<UChar, inlineCapacity>&, StringImpl*);
 
@@ -755,7 +756,7 @@
     while (string[length])
         ++length;
 
-    RELEASE_ASSERT(length < std::numeric_limits<unsigned>::max());
+    RELEASE_ASSERT(length < StringImpl::MaxLength);
     return static_cast<unsigned>(length);
 }
 
@@ -954,7 +955,7 @@
         return empty();
     }
 
-    if (length > ((std::numeric_limits<unsigned>::max() - sizeof(StringImpl)) / sizeof(CharacterType))) {
+    if (length > maxInternalLength<CharacterType>()) {
         output = nullptr;
         return nullptr;
     }
@@ -973,7 +974,7 @@
 {
     if (size_t size = vector.size()) {
         ASSERT(vector.data());
-        if (size > std::numeric_limits<unsigned>::max())
+        if (size > MaxLength)
             CRASH();
         return adoptRef(*new StringImpl(vector.releaseBuffer(), size));
     }
@@ -1112,6 +1113,13 @@
     return (tailOffset<T>() + tailElementCount * sizeof(T)).unsafeGet();
 }
 
+template<typename CharacterType>
+inline size_t StringImpl::maxInternalLength()
+{
+    // In order to not overflow the unsigned length, the check for (std::numeric_limits<unsigned>::max() - sizeof(StringImpl)) is needed when sizeof(CharacterType) == 2.
+    return std::min(static_cast<size_t>(MaxLength), (std::numeric_limits<unsigned>::max() - sizeof(StringImpl)) / sizeof(CharacterType));
+}
+
 template<typename T> inline size_t StringImpl::tailOffset()
 {
 #if COMPILER(MSVC)

Modified: trunk/Source/WTF/wtf/text/WTFString.cpp (239438 => 239439)


--- trunk/Source/WTF/wtf/text/WTFString.cpp	2018-12-20 11:59:05 UTC (rev 239438)
+++ trunk/Source/WTF/wtf/text/WTFString.cpp	2018-12-20 16:06:44 UTC (rev 239439)
@@ -99,7 +99,7 @@
 
     auto length = m_impl->length();
     auto otherLength = otherString.m_impl->length();
-    if (otherLength > std::numeric_limits<unsigned>::max() - length)
+    if (otherLength > MaxLength - length)
         CRASH();
 
     if (m_impl->is8Bit() && otherString.m_impl->is8Bit()) {
@@ -129,7 +129,7 @@
         append(static_cast<UChar>(character));
         return;
     }
-    if (m_impl->length() >= std::numeric_limits<unsigned>::max())
+    if (m_impl->length() >= MaxLength)
         CRASH();
     LChar* data;
     auto newImpl = StringImpl::createUninitialized(m_impl->length() + 1, data);
@@ -150,7 +150,7 @@
         append(static_cast<LChar>(character));
         return;
     }
-    if (m_impl->length() >= std::numeric_limits<unsigned>::max())
+    if (m_impl->length() >= MaxLength)
         CRASH();
     UChar* data;
     auto newImpl = StringImpl::createUninitialized(m_impl->length() + 1, data);
@@ -183,7 +183,7 @@
         return;
     }
 
-    if (lengthToInsert > std::numeric_limits<unsigned>::max() - length())
+    if (lengthToInsert > MaxLength - length())
         CRASH();
 
     if (is8Bit() && string.is8Bit()) {
@@ -222,7 +222,7 @@
     unsigned strLength = m_impl->length();
 
     if (m_impl->is8Bit()) {
-        if (lengthToAppend > std::numeric_limits<unsigned>::max() - strLength)
+        if (lengthToAppend > MaxLength - strLength)
             CRASH();
         LChar* data;
         auto newImpl = StringImpl::createUninitialized(strLength + lengthToAppend, data);
@@ -232,7 +232,7 @@
         return;
     }
 
-    if (lengthToAppend > std::numeric_limits<unsigned>::max() - strLength)
+    if (lengthToAppend > MaxLength - strLength)
         CRASH();
     UChar* data;
     auto newImpl = StringImpl::createUninitialized(length() + lengthToAppend, data);
@@ -258,7 +258,7 @@
     unsigned strLength = m_impl->length();
     
     ASSERT(charactersToAppend);
-    if (lengthToAppend > std::numeric_limits<unsigned>::max() - strLength)
+    if (lengthToAppend > MaxLength - strLength)
         CRASH();
     UChar* data;
     auto newImpl = StringImpl::createUninitialized(strLength + lengthToAppend, data);
@@ -885,7 +885,7 @@
 
 String String::fromUTF8(const LChar* stringStart, size_t length)
 {
-    if (length > std::numeric_limits<unsigned>::max())
+    if (length > MaxLength)
         CRASH();
 
     if (!stringStart)

Modified: trunk/Source/WTF/wtf/text/WTFString.h (239438 => 239439)


--- trunk/Source/WTF/wtf/text/WTFString.h	2018-12-20 11:59:05 UTC (rev 239438)
+++ trunk/Source/WTF/wtf/text/WTFString.h	2018-12-20 16:06:44 UTC (rev 239439)
@@ -194,8 +194,8 @@
     size_t find(const LChar* string, unsigned start = 0) const { return m_impl ? m_impl->find(string, start) : notFound; }
 
     // Find the last instance of a single character or string.
-    size_t reverseFind(UChar character, unsigned start = std::numeric_limits<unsigned>::max()) const { return m_impl ? m_impl->reverseFind(character, start) : notFound; }
-    size_t reverseFind(const String& string, unsigned start = std::numeric_limits<unsigned>::max()) const { return m_impl ? m_impl->reverseFind(string.impl(), start) : notFound; }
+    size_t reverseFind(UChar character, unsigned start = MaxLength) const { return m_impl ? m_impl->reverseFind(character, start) : notFound; }
+    size_t reverseFind(const String& string, unsigned start = MaxLength) const { return m_impl ? m_impl->reverseFind(string.impl(), start) : notFound; }
 
     WTF_EXPORT_PRIVATE Vector<UChar> charactersWithNullTermination() const;
 
@@ -237,8 +237,8 @@
     WTF_EXPORT_PRIVATE void truncate(unsigned length);
     WTF_EXPORT_PRIVATE void remove(unsigned position, unsigned length = 1);
 
-    WTF_EXPORT_PRIVATE String substring(unsigned position, unsigned length = std::numeric_limits<unsigned>::max()) const;
-    WTF_EXPORT_PRIVATE String substringSharingImpl(unsigned position, unsigned length = std::numeric_limits<unsigned>::max()) const;
+    WTF_EXPORT_PRIVATE String substring(unsigned position, unsigned length = MaxLength) const;
+    WTF_EXPORT_PRIVATE String substringSharingImpl(unsigned position, unsigned length = MaxLength) const;
     String left(unsigned length) const { return substring(0, length); }
     String right(unsigned length) const { return substring(this->length() - length, length); }
 
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to