Title: [232089] trunk
Revision
232089
Author
mark....@apple.com
Date
2018-05-22 16:54:16 -0700 (Tue, 22 May 2018)

Log Message

StringImpl utf8 conversion should not fail silently.
https://bugs.webkit.org/show_bug.cgi?id=185888
<rdar://problem/40464506>

Reviewed by Filip Pizlo.

JSTests:

* stress/regress-185888.js: Added.

Source/_javascript_Core:

* dfg/DFGLazyJSValue.cpp:
(JSC::DFG::LazyJSValue::dumpInContext const):
* runtime/DateConstructor.cpp:
(JSC::constructDate):
(JSC::dateParse):
* runtime/JSDateMath.cpp:
(JSC::parseDate):
* runtime/JSDateMath.h:

Source/WTF:

* WTF.xcodeproj/project.pbxproj:
* wtf/CMakeLists.txt:
* wtf/PrintStream.cpp:
(WTF::printExpectedCStringHelper):
(WTF::printInternal):
* wtf/text/StringImpl.cpp:
(WTF::StringImpl::utf8Impl):
(WTF::StringImpl::utf8ForCharacters):
(WTF::StringImpl::tryUtf8ForRange const):
(WTF::StringImpl::tryUtf8 const):
(WTF::StringImpl::utf8 const):
(WTF::StringImpl::utf8ForRange const): Deleted.
* wtf/text/StringImpl.h:
* wtf/text/StringView.cpp:
(WTF::StringView::tryUtf8 const):
(WTF::StringView::utf8 const):
* wtf/text/StringView.h:
* wtf/text/UTF8ConversionError.h: Added.
* wtf/text/WTFString.cpp:
(WTF::String::tryUtf8 const):
(WTF::String::utf8 const):
* wtf/text/WTFString.h:

Modified Paths

Added Paths

Diff

Modified: trunk/JSTests/ChangeLog (232088 => 232089)


--- trunk/JSTests/ChangeLog	2018-05-22 23:54:04 UTC (rev 232088)
+++ trunk/JSTests/ChangeLog	2018-05-22 23:54:16 UTC (rev 232089)
@@ -1,3 +1,13 @@
+2018-05-22  Mark Lam  <mark....@apple.com>
+
+        StringImpl utf8 conversion should not fail silently.
+        https://bugs.webkit.org/show_bug.cgi?id=185888
+        <rdar://problem/40464506>
+
+        Reviewed by Filip Pizlo.
+
+        * stress/regress-185888.js: Added.
+
 2018-05-22  Keith Miller  <keith_mil...@apple.com>
 
         We should have a CoW storage for NewArrayBuffer arrays.

Added: trunk/JSTests/stress/regress-185888.js (0 => 232089)


--- trunk/JSTests/stress/regress-185888.js	                        (rev 0)
+++ trunk/JSTests/stress/regress-185888.js	2018-05-22 23:54:16 UTC (rev 232089)
@@ -0,0 +1,10 @@
+var exception;
+try {
+    const str = "a".padStart(0x80000000 - 1);
+    new Date(str);
+} catch (e) {
+    exception = e;
+}
+
+if (exception != "Error: Out of memory")
+    throw "FAILED";

Modified: trunk/Source/_javascript_Core/ChangeLog (232088 => 232089)


--- trunk/Source/_javascript_Core/ChangeLog	2018-05-22 23:54:04 UTC (rev 232088)
+++ trunk/Source/_javascript_Core/ChangeLog	2018-05-22 23:54:16 UTC (rev 232089)
@@ -1,3 +1,20 @@
+2018-05-22  Mark Lam  <mark....@apple.com>
+
+        StringImpl utf8 conversion should not fail silently.
+        https://bugs.webkit.org/show_bug.cgi?id=185888
+        <rdar://problem/40464506>
+
+        Reviewed by Filip Pizlo.
+
+        * dfg/DFGLazyJSValue.cpp:
+        (JSC::DFG::LazyJSValue::dumpInContext const):
+        * runtime/DateConstructor.cpp:
+        (JSC::constructDate):
+        (JSC::dateParse):
+        * runtime/JSDateMath.cpp:
+        (JSC::parseDate):
+        * runtime/JSDateMath.h:
+
 2018-05-22  Keith Miller  <keith_mil...@apple.com>
 
         Remove the UnconditionalFinalizer class

Modified: trunk/Source/_javascript_Core/dfg/DFGLazyJSValue.cpp (232088 => 232089)


--- trunk/Source/_javascript_Core/dfg/DFGLazyJSValue.cpp	2018-05-22 23:54:04 UTC (rev 232088)
+++ trunk/Source/_javascript_Core/dfg/DFGLazyJSValue.cpp	2018-05-22 23:54:16 UTC (rev 232089)
@@ -250,7 +250,7 @@
     case SingleCharacterString:
         out.print("Lazy:SingleCharacterString(");
         out.printf("%04X", static_cast<unsigned>(character()));
-        out.print(" / ", StringImpl::utf8ForCharacters(&u.character, 1), ")");
+        out.print(" / ", StringImpl::utf8ForCharacters(&u.character, 1).value(), ")");
         return;
     case KnownStringImpl:
         out.print("Lazy:KnownString(", stringImpl(), ")");

Modified: trunk/Source/_javascript_Core/runtime/DateConstructor.cpp (232088 => 232089)


--- trunk/Source/_javascript_Core/runtime/DateConstructor.cpp	2018-05-22 23:54:04 UTC (rev 232088)
+++ trunk/Source/_javascript_Core/runtime/DateConstructor.cpp	2018-05-22 23:54:16 UTC (rev 232089)
@@ -1,6 +1,6 @@
 /*
  *  Copyright (C) 1999-2000 Harri Porten (por...@kde.org)
- *  Copyright (C) 2004-2008, 2011, 2016 Apple Inc. All rights reserved.
+ *  Copyright (C) 2004-2018 Apple Inc. All rights reserved.
  *
  *  This library is free software; you can redistribute it and/or
  *  modify it under the terms of the GNU Lesser General Public
@@ -136,9 +136,10 @@
         else {
             JSValue primitive = arg0.toPrimitive(exec);
             RETURN_IF_EXCEPTION(scope, nullptr);
-            if (primitive.isString())
-                value = parseDate(vm, asString(primitive)->value(exec));
-            else
+            if (primitive.isString()) {
+                value = parseDate(exec, vm, asString(primitive)->value(exec));
+                RETURN_IF_EXCEPTION(scope, nullptr);
+            } else
                 value = primitive.toNumber(exec);
         }
     } else
@@ -172,7 +173,8 @@
     auto scope = DECLARE_THROW_SCOPE(vm);
     String dateStr = exec->argument(0).toWTFString(exec);
     RETURN_IF_EXCEPTION(scope, encodedJSValue());
-    return JSValue::encode(jsNumber(parseDate(vm, dateStr)));
+    scope.release();
+    return JSValue::encode(jsNumber(parseDate(exec, vm, dateStr)));
 }
 
 EncodedJSValue JSC_HOST_CALL dateNow(ExecState*)

Modified: trunk/Source/_javascript_Core/runtime/JSDateMath.cpp (232088 => 232089)


--- trunk/Source/_javascript_Core/runtime/JSDateMath.cpp	2018-05-22 23:54:04 UTC (rev 232088)
+++ trunk/Source/_javascript_Core/runtime/JSDateMath.cpp	2018-05-22 23:54:16 UTC (rev 232089)
@@ -1,6 +1,6 @@
 /*
  * Copyright (C) 1999-2000 Harri Porten (por...@kde.org)
- * Copyright (C) 2006, 2007, 2012 Apple Inc. All rights reserved.
+ * Copyright (C) 2006-2018 Apple Inc. All rights reserved.
  * Copyright (C) 2009 Google Inc. All rights reserved.
  * Copyright (C) 2007-2009 Torch Mobile, Inc.
  * Copyright (C) 2010 &yet, LLC. (n...@andyet.net)
@@ -235,13 +235,26 @@
     return localTimeMS - (offset * WTF::msPerMinute);
 }
 
-double parseDate(VM& vm, const String& date)
+double parseDate(ExecState* exec, VM& vm, const String& date)
 {
+    auto scope = DECLARE_THROW_SCOPE(vm);
+
     if (date == vm.cachedDateString)
         return vm.cachedDateStringValue;
-    double value = parseES5DateFromNullTerminatedCharacters(date.utf8().data());
+    auto expectedString = date.tryGetUtf8();
+    if (!expectedString) {
+        if (expectedString.error() == UTF8ConversionError::OutOfMemory)
+            throwOutOfMemoryError(exec, scope);
+        // https://tc39.github.io/ecma262/#sec-date-objects section 20.3.3.2 states that:
+        // "Unrecognizable Strings or dates containing illegal element values in the
+        // format String shall cause Date.parse to return NaN."
+        return std::numeric_limits<double>::quiet_NaN();
+    }
+
+    auto dateUtf8 = expectedString.value();
+    double value = parseES5DateFromNullTerminatedCharacters(dateUtf8.data());
     if (std::isnan(value))
-        value = parseDateFromNullTerminatedCharacters(vm, date.utf8().data());
+        value = parseDateFromNullTerminatedCharacters(vm, dateUtf8.data());
     vm.cachedDateString = date;
     vm.cachedDateStringValue = value;
     return value;

Modified: trunk/Source/_javascript_Core/runtime/JSDateMath.h (232088 => 232089)


--- trunk/Source/_javascript_Core/runtime/JSDateMath.h	2018-05-22 23:54:04 UTC (rev 232088)
+++ trunk/Source/_javascript_Core/runtime/JSDateMath.h	2018-05-22 23:54:16 UTC (rev 232089)
@@ -1,6 +1,6 @@
 /*
  * Copyright (C) 1999-2000 Harri Porten (por...@kde.org)
- * Copyright (C) 2006, 2007 Apple Inc. All rights reserved.
+ * Copyright (C) 2006-2018 Apple Inc. All rights reserved.
  * Copyright (C) 2009 Google Inc. All rights reserved.
  * Copyright (C) 2010 Research In Motion Limited. All rights reserved.
  *
@@ -47,6 +47,7 @@
 
 namespace JSC {
 
+class ExecState;
 class VM;
 
 JS_EXPORT_PRIVATE void msToGregorianDateTime(VM&, double, WTF::TimeType outputTimeType, GregorianDateTime&);
@@ -53,6 +54,6 @@
 JS_EXPORT_PRIVATE double gregorianDateTimeToMS(VM&, const GregorianDateTime&, double, WTF::TimeType inputTimeType);
 JS_EXPORT_PRIVATE double getUTCOffset(VM&);
 JS_EXPORT_PRIVATE double parseDateFromNullTerminatedCharacters(VM&, const char* dateString);
-JS_EXPORT_PRIVATE double parseDate(VM&, const WTF::String&);
+JS_EXPORT_PRIVATE double parseDate(ExecState*, VM&, const WTF::String&);
 
 } // namespace JSC

Modified: trunk/Source/WTF/ChangeLog (232088 => 232089)


--- trunk/Source/WTF/ChangeLog	2018-05-22 23:54:04 UTC (rev 232088)
+++ trunk/Source/WTF/ChangeLog	2018-05-22 23:54:16 UTC (rev 232089)
@@ -1,3 +1,34 @@
+2018-05-22  Mark Lam  <mark....@apple.com>
+
+        StringImpl utf8 conversion should not fail silently.
+        https://bugs.webkit.org/show_bug.cgi?id=185888
+        <rdar://problem/40464506>
+
+        Reviewed by Filip Pizlo.
+
+        * WTF.xcodeproj/project.pbxproj:
+        * wtf/CMakeLists.txt:
+        * wtf/PrintStream.cpp:
+        (WTF::printExpectedCStringHelper):
+        (WTF::printInternal):
+        * wtf/text/StringImpl.cpp:
+        (WTF::StringImpl::utf8Impl):
+        (WTF::StringImpl::utf8ForCharacters):
+        (WTF::StringImpl::tryUtf8ForRange const):
+        (WTF::StringImpl::tryUtf8 const):
+        (WTF::StringImpl::utf8 const):
+        (WTF::StringImpl::utf8ForRange const): Deleted.
+        * wtf/text/StringImpl.h:
+        * wtf/text/StringView.cpp:
+        (WTF::StringView::tryUtf8 const):
+        (WTF::StringView::utf8 const):
+        * wtf/text/StringView.h:
+        * wtf/text/UTF8ConversionError.h: Added.
+        * wtf/text/WTFString.cpp:
+        (WTF::String::tryUtf8 const):
+        (WTF::String::utf8 const):
+        * wtf/text/WTFString.h:
+
 2018-05-22  Chris Dumez  <cdu...@apple.com>
 
         Regression(AsyncPolicyDelegates): Box.app login Window is blank

Modified: trunk/Source/WTF/WTF.xcodeproj/project.pbxproj (232088 => 232089)


--- trunk/Source/WTF/WTF.xcodeproj/project.pbxproj	2018-05-22 23:54:04 UTC (rev 232088)
+++ trunk/Source/WTF/WTF.xcodeproj/project.pbxproj	2018-05-22 23:54:16 UTC (rev 232089)
@@ -641,6 +641,7 @@
 		FEB6B035201BE0B600B958C1 /* PointerPreparations.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PointerPreparations.h; sourceTree = "<group>"; };
 		FEDACD3B1630F83F00C69634 /* StackStats.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = StackStats.cpp; sourceTree = "<group>"; };
 		FEDACD3C1630F83F00C69634 /* StackStats.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = StackStats.h; sourceTree = "<group>"; };
+		FEF295BF20B49DCB00CF283A /* UTF8ConversionError.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = UTF8ConversionError.h; sourceTree = "<group>"; };
 		FF0A436588954F3CB07DBECA /* StdList.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = StdList.h; sourceTree = "<group>"; };
 /* End PBXFileReference section */
 
@@ -1218,6 +1219,7 @@
 				A8A4732C151A825B004123FF /* TextPosition.h */,
 				A3E4DD911F3A803400DED0B4 /* TextStream.cpp */,
 				A3E4DD921F3A803400DED0B4 /* TextStream.h */,
+				FEF295BF20B49DCB00CF283A /* UTF8ConversionError.h */,
 				70ECA60C1B02426800449739 /* UniquedStringImpl.h */,
 				A3AB6E6A1F3E1AD6009C14B1 /* ValueToString.h */,
 				A8A4732D151A825B004123FF /* WTFString.cpp */,

Modified: trunk/Source/WTF/wtf/CMakeLists.txt (232088 => 232089)


--- trunk/Source/WTF/wtf/CMakeLists.txt	2018-05-22 23:54:04 UTC (rev 232088)
+++ trunk/Source/WTF/wtf/CMakeLists.txt	2018-05-22 23:54:16 UTC (rev 232089)
@@ -305,6 +305,7 @@
     text/TextBreakIteratorInternalICU.h
     text/TextPosition.h
     text/TextStream.h
+    text/UTF8ConversionError.h
     text/UniquedStringImpl.h
     text/ValueToString.h
     text/WTFString.h

Modified: trunk/Source/WTF/wtf/PrintStream.cpp (232088 => 232089)


--- trunk/Source/WTF/wtf/PrintStream.cpp	2018-05-22 23:54:04 UTC (rev 232088)
+++ trunk/Source/WTF/wtf/PrintStream.cpp	2018-05-22 23:54:16 UTC (rev 232089)
@@ -82,9 +82,21 @@
     out.printf("%s", string);
 }
 
+static void printExpectedCStringHelper(PrintStream& out, const char* type, Expected<CString, UTF8ConversionError> expectedCString)
+{
+    if (UNLIKELY(!expectedCString)) {
+        if (expectedCString.error() == UTF8ConversionError::OutOfMemory)
+            out.print("(Out of memory while converting ", type, " to utf8)");
+        else
+            out.print("(failed to convert ", type, " to utf8)");
+        return;
+    }
+    out.print(expectedCString.value());
+}
+
 void printInternal(PrintStream& out, const StringView& string)
 {
-    out.print(string.utf8());
+    printExpectedCStringHelper(out, "StringView", string.tryGetUtf8());
 }
 
 void printInternal(PrintStream& out, const CString& string)
@@ -94,7 +106,7 @@
 
 void printInternal(PrintStream& out, const String& string)
 {
-    out.print(string.utf8());
+    printExpectedCStringHelper(out, "String", string.tryGetUtf8());
 }
 
 void printInternal(PrintStream& out, const StringImpl* string)
@@ -103,7 +115,7 @@
         out.print("(null StringImpl*)");
         return;
     }
-    out.print(string->utf8());
+    printExpectedCStringHelper(out, "StringImpl*", string->tryGetUtf8());
 }
 
 void printInternal(PrintStream& out, bool value)

Modified: trunk/Source/WTF/wtf/text/StringImpl.cpp (232088 => 232089)


--- trunk/Source/WTF/wtf/text/StringImpl.cpp	2018-05-22 23:54:04 UTC (rev 232088)
+++ trunk/Source/WTF/wtf/text/StringImpl.cpp	2018-05-22 23:54:16 UTC (rev 232089)
@@ -1726,7 +1726,7 @@
     *buffer++ = static_cast<char>((character & 0x3F) | 0x80);
 }
 
-bool StringImpl::utf8Impl(const UChar* characters, unsigned length, char*& buffer, size_t bufferSize, ConversionMode mode)
+UTF8ConversionError StringImpl::utf8Impl(const UChar* characters, unsigned length, char*& buffer, size_t bufferSize, ConversionMode mode)
 {
     if (mode == StrictConversionReplacingUnpairedSurrogatesWithFFFD) {
         const UChar* charactersEnd = characters + length;
@@ -1754,13 +1754,13 @@
         // Only produced from strict conversion.
         if (result == sourceIllegal) {
             ASSERT(strict);
-            return false;
+            return UTF8ConversionError::IllegalSource;
         }
 
         // Check for an unconverted high surrogate.
         if (result == sourceExhausted) {
             if (strict)
-                return false;
+                return UTF8ConversionError::SourceExhausted;
             // This should be one unpaired high surrogate. Treat it the same
             // was as an unpaired high surrogate would have been handled in
             // the middle of a string with non-strict conversion - which is
@@ -1774,15 +1774,15 @@
         }
     }
     
-    return true;
+    return UTF8ConversionError::None;
 }
 
-CString StringImpl::utf8ForCharacters(const LChar* characters, unsigned length)
+Expected<CString, UTF8ConversionError> StringImpl::utf8ForCharacters(const LChar* characters, unsigned length)
 {
     if (!length)
         return CString("", 0);
     if (length > std::numeric_limits<unsigned>::max() / 3)
-        return CString();
+        return makeUnexpected(UTF8ConversionError::OutOfMemory);
     Vector<char, 1024> bufferVector(length * 3);
     char* buffer = bufferVector.data();
     const LChar* source = characters;
@@ -1791,20 +1791,21 @@
     return CString(bufferVector.data(), buffer - bufferVector.data());
 }
 
-CString StringImpl::utf8ForCharacters(const UChar* characters, unsigned length, ConversionMode mode)
+Expected<CString, UTF8ConversionError> StringImpl::utf8ForCharacters(const UChar* characters, unsigned length, ConversionMode mode)
 {
     if (!length)
         return CString("", 0);
     if (length > std::numeric_limits<unsigned>::max() / 3)
-        return CString();
+        return makeUnexpected(UTF8ConversionError::OutOfMemory);
     Vector<char, 1024> bufferVector(length * 3);
     char* buffer = bufferVector.data();
-    if (!utf8Impl(characters, length, buffer, bufferVector.size(), mode))
-        return CString();
+    UTF8ConversionError error = utf8Impl(characters, length, buffer, bufferVector.size(), mode);
+    if (error != UTF8ConversionError::None)
+        return makeUnexpected(error);
     return CString(bufferVector.data(), buffer - bufferVector.data());
 }
 
-CString StringImpl::utf8ForRange(unsigned offset, unsigned length, ConversionMode mode) const
+Expected<CString, UTF8ConversionError> StringImpl::tryGetUtf8ForRange(unsigned offset, unsigned length, ConversionMode mode) const
 {
     ASSERT(offset <= this->length());
     ASSERT(offset + length <= this->length());
@@ -1823,7 +1824,7 @@
     //    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)
-        return CString();
+        return makeUnexpected(UTF8ConversionError::OutOfMemory);
     Vector<char, 1024> bufferVector(length * 3);
 
     char* buffer = bufferVector.data();
@@ -1834,16 +1835,24 @@
         ConversionResult result = convertLatin1ToUTF8(&characters, characters + length, &buffer, buffer + bufferVector.size());
         ASSERT_UNUSED(result, result != targetExhausted); // (length * 3) should be sufficient for any conversion
     } else {
-        if (!utf8Impl(this->characters16() + offset, length, buffer, bufferVector.size(), mode))
-            return CString();
+        UTF8ConversionError error = utf8Impl(this->characters16() + offset, length, buffer, bufferVector.size(), mode);
+        if (error != UTF8ConversionError::None)
+            return makeUnexpected(error);
     }
 
     return CString(bufferVector.data(), buffer - bufferVector.data());
 }
 
+Expected<CString, UTF8ConversionError> StringImpl::tryGetUtf8(ConversionMode mode) const
+{
+    return tryGetUtf8ForRange(0, length(), mode);
+}
+
 CString StringImpl::utf8(ConversionMode mode) const
 {
-    return utf8ForRange(0, length(), mode);
+    auto expectedString = tryGetUtf8ForRange(0, length(), mode);
+    RELEASE_ASSERT(expectedString);
+    return expectedString.value();
 }
 
 NEVER_INLINE unsigned StringImpl::hashSlowCase() const

Modified: trunk/Source/WTF/wtf/text/StringImpl.h (232088 => 232089)


--- trunk/Source/WTF/wtf/text/StringImpl.h	2018-05-22 23:54:04 UTC (rev 232088)
+++ trunk/Source/WTF/wtf/text/StringImpl.h	2018-05-22 23:54:16 UTC (rev 232089)
@@ -27,6 +27,7 @@
 #include <unicode/ustring.h>
 #include <wtf/ASCIICType.h>
 #include <wtf/CheckedArithmetic.h>
+#include <wtf/Expected.h>
 #include <wtf/MathExtras.h>
 #include <wtf/StdLibExtras.h>
 #include <wtf/Vector.h>
@@ -34,6 +35,7 @@
 #include <wtf/text/ConversionMode.h>
 #include <wtf/text/StringCommon.h>
 #include <wtf/text/StringHasher.h>
+#include <wtf/text/UTF8ConversionError.h>
 
 #if USE(CF)
 typedef const struct __CFString * CFStringRef;
@@ -284,13 +286,15 @@
     bool isSubString() const { return bufferOwnership() == BufferSubstring; }
 #endif
 
-    static WTF_EXPORT_PRIVATE CString utf8ForCharacters(const LChar* characters, unsigned length);
-    static WTF_EXPORT_PRIVATE CString utf8ForCharacters(const UChar* characters, unsigned length, ConversionMode = LenientConversion);
-    WTF_EXPORT_PRIVATE CString utf8ForRange(unsigned offset, unsigned length, ConversionMode = LenientConversion) const;
+    static WTF_EXPORT_PRIVATE Expected<CString, UTF8ConversionError> utf8ForCharacters(const LChar* characters, unsigned length);
+    static WTF_EXPORT_PRIVATE Expected<CString, UTF8ConversionError> utf8ForCharacters(const UChar* characters, unsigned length, ConversionMode = LenientConversion);
+
+    WTF_EXPORT_PRIVATE Expected<CString, UTF8ConversionError> tryGetUtf8ForRange(unsigned offset, unsigned length, ConversionMode = LenientConversion) const;
+    WTF_EXPORT_PRIVATE Expected<CString, UTF8ConversionError> tryGetUtf8(ConversionMode = LenientConversion) const;
     WTF_EXPORT_PRIVATE CString utf8(ConversionMode = LenientConversion) const;
 
 private:
-    static WTF_EXPORT_PRIVATE bool utf8Impl(const UChar* characters, unsigned length, char*& buffer, size_t bufferSize, ConversionMode);
+    static WTF_EXPORT_PRIVATE UTF8ConversionError utf8Impl(const UChar* characters, unsigned length, char*& buffer, size_t bufferSize, ConversionMode);
     
     // The high bits of 'hash' are always empty, but we prefer to store our flags
     // in the low bits because it makes them slightly more efficient to access.
@@ -1202,8 +1206,8 @@
 
 } // namespace WTF
 
+using WTF::StaticStringImpl;
 using WTF::StringImpl;
-using WTF::StaticStringImpl;
 using WTF::equal;
 
 #endif

Modified: trunk/Source/WTF/wtf/text/StringView.cpp (232088 => 232089)


--- trunk/Source/WTF/wtf/text/StringView.cpp	2018-05-22 23:54:04 UTC (rev 232088)
+++ trunk/Source/WTF/wtf/text/StringView.cpp	2018-05-22 23:54:16 UTC (rev 232089)
@@ -80,7 +80,7 @@
     return ::WTF::endsWithIgnoringASCIICase(*this, suffix);
 }
 
-CString StringView::utf8(ConversionMode mode) const
+Expected<CString, UTF8ConversionError> StringView::tryGetUtf8(ConversionMode mode) const
 {
     if (isNull())
         return CString("", 0);
@@ -89,6 +89,13 @@
     return StringImpl::utf8ForCharacters(characters16(), length(), mode);
 }
 
+CString StringView::utf8(ConversionMode mode) const
+{
+    auto expectedString = tryGetUtf8(mode);
+    RELEASE_ASSERT(expectedString);
+    return expectedString.value();
+}
+
 size_t StringView::find(StringView matchString, unsigned start) const
 {
     return findCommon(*this, matchString, start);

Modified: trunk/Source/WTF/wtf/text/StringView.h (232088 => 232089)


--- trunk/Source/WTF/wtf/text/StringView.h	2018-05-22 23:54:04 UTC (rev 232088)
+++ trunk/Source/WTF/wtf/text/StringView.h	2018-05-22 23:54:16 UTC (rev 232089)
@@ -36,6 +36,7 @@
 #include <wtf/text/ConversionMode.h>
 #include <wtf/text/LChar.h>
 #include <wtf/text/StringCommon.h>
+#include <wtf/text/UTF8ConversionError.h>
 
 // FIXME: Enabling the StringView lifetime checking causes the MSVC build to fail. Figure out why.
 #if defined(NDEBUG) || COMPILER(MSVC)
@@ -106,6 +107,7 @@
     WTF_EXPORT_PRIVATE RetainPtr<NSString> createNSStringWithoutCopying() const;
 #endif
 
+    WTF_EXPORT_PRIVATE Expected<CString, UTF8ConversionError> tryGetUtf8(ConversionMode = LenientConversion) const;
     WTF_EXPORT_PRIVATE CString utf8(ConversionMode = LenientConversion) const;
 
     class UpconvertedCharacters;

Added: trunk/Source/WTF/wtf/text/UTF8ConversionError.h (0 => 232089)


--- trunk/Source/WTF/wtf/text/UTF8ConversionError.h	                        (rev 0)
+++ trunk/Source/WTF/wtf/text/UTF8ConversionError.h	2018-05-22 23:54:16 UTC (rev 232089)
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2018 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+
+namespace WTF {
+
+enum class UTF8ConversionError {
+    None,
+    OutOfMemory,
+    IllegalSource,
+    SourceExhausted
+};
+
+} // namespace WTF
+
+using WTF::UTF8ConversionError;

Modified: trunk/Source/WTF/wtf/text/WTFString.cpp (232088 => 232089)


--- trunk/Source/WTF/wtf/text/WTFString.cpp	2018-05-22 23:54:04 UTC (rev 232088)
+++ trunk/Source/WTF/wtf/text/WTFString.cpp	2018-05-22 23:54:16 UTC (rev 232089)
@@ -804,9 +804,21 @@
     return result;
 }
 
+Expected<CString, UTF8ConversionError> String::tryGetUtf8(ConversionMode mode) const
+{
+    return m_impl ? m_impl->tryGetUtf8(mode) : CString { "", 0 };
+}
+
+Expected<CString, UTF8ConversionError> String::tryGetUtf8() const
+{
+    return tryGetUtf8(LenientConversion);
+}
+
 CString String::utf8(ConversionMode mode) const
 {
-    return m_impl ? m_impl->utf8(mode) : CString { "", 0 };
+    Expected<CString, UTF8ConversionError> expectedString = tryGetUtf8(mode);
+    RELEASE_ASSERT(expectedString);
+    return expectedString.value();
 }
 
 CString String::utf8() const

Modified: trunk/Source/WTF/wtf/text/WTFString.h (232088 => 232089)


--- trunk/Source/WTF/wtf/text/WTFString.h	2018-05-22 23:54:04 UTC (rev 232088)
+++ trunk/Source/WTF/wtf/text/WTFString.h	2018-05-22 23:54:16 UTC (rev 232089)
@@ -165,6 +165,9 @@
     WTF_EXPORT_PRIVATE CString utf8(ConversionMode) const;
     WTF_EXPORT_PRIVATE CString utf8() const;
 
+    WTF_EXPORT_PRIVATE Expected<CString, UTF8ConversionError> tryGetUtf8(ConversionMode) const;
+    WTF_EXPORT_PRIVATE Expected<CString, UTF8ConversionError> tryGetUtf8() const;
+
     UChar characterAt(unsigned index) const;
     UChar operator[](unsigned index) const { return characterAt(index); }
 
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to