Title: [260882] trunk/Source
Revision
260882
Author
[email protected]
Date
2020-04-29 00:15:18 -0700 (Wed, 29 Apr 2020)

Log Message

U_STRING_NOT_TERMINATED_WARNING ICU must be handled when using the output buffer as a C string
https://bugs.webkit.org/show_bug.cgi?id=211142
<rdar://problem/62530860>

Reviewed by Darin Adler.

Source/_javascript_Core:

* runtime/IntlDateTimeFormat.cpp:
(JSC::defaultTimeZone):
(JSC::canonicalizeTimeZoneName):
(JSC::IntlDateTimeFormat::initializeDateTimeFormat):
(JSC::IntlDateTimeFormat::format):
(JSC::IntlDateTimeFormat::formatToParts):
* runtime/IntlNumberFormat.cpp:
(JSC::IntlNumberFormat::format):
(JSC::IntlNumberFormat::formatToParts):
* runtime/IntlObject.cpp:
(JSC::convertICULocaleToBCP47LanguageTag):
(JSC::canonicalizeLanguageTag):
* runtime/IntlRelativeTimeFormat.cpp:
(JSC::IntlRelativeTimeFormat::formatInternal):
(JSC::IntlRelativeTimeFormat::formatToParts):
* runtime/StringPrototype.cpp:
(JSC::toLocaleCase):
(JSC::normalize):

Source/WebCore:

* editing/TextIterator.cpp:
(WebCore::normalizeCharacters):
* platform/text/LocaleICU.cpp:
(WebCore::LocaleICU::decimalSymbol):
(WebCore::LocaleICU::decimalTextAttribute):
(WebCore::getDateFormatPattern):
(WebCore::LocaleICU::createLabelVector):
(WebCore::getFormatForSkeleton):
* platform/text/LocaleToScriptMappingICU.cpp:
(WebCore::localeToScriptCodeForFontSelection):
* platform/text/TextCodecICU.cpp:
(WebCore::TextCodecICU::decode):
(WebCore::TextCodecICU::encode):

Source/WTF:

Most of our uses of ICU require us to produce a buffer of the correct
length. We often test if the first call to ICU API succeeds, and if it
doesn't, we grow to the required buffer size, and try again. However,
there are a few APIs that we use like this, except that they write their
output to a C string instead of a buffer.

In a couple scenarios when we were producing C strings, we were only testing
for the U_BUFFER_OVERFLOW_ERROR, instead of both U_BUFFER_OVERFLOW_ERROR and
U_STRING_NOT_TERMINATED_WARNING. This patch fixes those bugs. It also
introduces two new helper methods for testing error codes returned by ICU.

- The first is needsToGrowToProduceBuffer, which returns true if we need to
grow the buffer and re-call into ICU to get the result.
- The second is needsToGrowToProduceCString, which returns true if we need to
grow the buffer and re-call into ICU to produce a valid C string.

I've audited all uses of U_BUFFER_OVERFLOW_ERROR and converted them to use one
of the above helper methods instead.

The issues in our handling of U_STRING_NOT_TERMINATED_WARNING were caught on iOS JSC
tests in JSTests/stress/intl-datetimeformat.js

* WTF.xcodeproj/project.pbxproj:
* wtf/CMakeLists.txt:
* wtf/text/LineBreakIteratorPoolICU.h:
(WTF::LineBreakIteratorPool::makeLocaleWithBreakKeyword):
* wtf/text/StringView.cpp:
(WTF::normalizedNFC):
* wtf/unicode/icu/ICUHelpers.h: Added.
(WTF::needsToGrowToProduceCString):
(WTF::needsToGrowToProduceBuffer):

Modified Paths

Added Paths

Diff

Modified: trunk/Source/_javascript_Core/ChangeLog (260881 => 260882)


--- trunk/Source/_javascript_Core/ChangeLog	2020-04-29 07:09:44 UTC (rev 260881)
+++ trunk/Source/_javascript_Core/ChangeLog	2020-04-29 07:15:18 UTC (rev 260882)
@@ -1,3 +1,30 @@
+2020-04-29  Saam Barati  <[email protected]>
+
+        U_STRING_NOT_TERMINATED_WARNING ICU must be handled when using the output buffer as a C string
+        https://bugs.webkit.org/show_bug.cgi?id=211142
+        <rdar://problem/62530860>
+
+        Reviewed by Darin Adler.
+
+        * runtime/IntlDateTimeFormat.cpp:
+        (JSC::defaultTimeZone):
+        (JSC::canonicalizeTimeZoneName):
+        (JSC::IntlDateTimeFormat::initializeDateTimeFormat):
+        (JSC::IntlDateTimeFormat::format):
+        (JSC::IntlDateTimeFormat::formatToParts):
+        * runtime/IntlNumberFormat.cpp:
+        (JSC::IntlNumberFormat::format):
+        (JSC::IntlNumberFormat::formatToParts):
+        * runtime/IntlObject.cpp:
+        (JSC::convertICULocaleToBCP47LanguageTag):
+        (JSC::canonicalizeLanguageTag):
+        * runtime/IntlRelativeTimeFormat.cpp:
+        (JSC::IntlRelativeTimeFormat::formatInternal):
+        (JSC::IntlRelativeTimeFormat::formatToParts):
+        * runtime/StringPrototype.cpp:
+        (JSC::toLocaleCase):
+        (JSC::normalize):
+
 2020-04-28  Saam Barati  <[email protected]>
 
         Unreviewed. Fix 32-bit build.

Modified: trunk/Source/_javascript_Core/runtime/IntlDateTimeFormat.cpp (260881 => 260882)


--- trunk/Source/_javascript_Core/runtime/IntlDateTimeFormat.cpp	2020-04-29 07:09:44 UTC (rev 260881)
+++ trunk/Source/_javascript_Core/runtime/IntlDateTimeFormat.cpp	2020-04-29 07:15:18 UTC (rev 260882)
@@ -39,6 +39,7 @@
 #include <unicode/uenum.h>
 #include <unicode/ufieldpositer.h>
 #include <wtf/text/StringBuilder.h>
+#include <wtf/unicode/icu/ICUHelpers.h>
 
 namespace JSC {
 
@@ -119,7 +120,7 @@
 
     Vector<UChar, 32> buffer(32);
     auto bufferLength = ucal_getDefaultTimeZone(buffer.data(), buffer.size(), &status);
-    if (status == U_BUFFER_OVERFLOW_ERROR) {
+    if (needsToGrowToProduceBuffer(status)) {
         status = U_ZERO_ERROR;
         buffer.grow(bufferLength);
         ucal_getDefaultTimeZone(buffer.data(), bufferLength, &status);
@@ -128,7 +129,7 @@
         status = U_ZERO_ERROR;
         Vector<UChar, 32> canonicalBuffer(32);
         auto canonicalLength = ucal_getCanonicalTimeZoneID(buffer.data(), bufferLength, canonicalBuffer.data(), canonicalBuffer.size(), nullptr, &status);
-        if (status == U_BUFFER_OVERFLOW_ERROR) {
+        if (needsToGrowToProduceBuffer(status)) {
             status = U_ZERO_ERROR;
             canonicalBuffer.grow(canonicalLength);
             ucal_getCanonicalTimeZoneID(buffer.data(), bufferLength, canonicalBuffer.data(), canonicalLength, nullptr, &status);
@@ -175,7 +176,7 @@
         Vector<UChar, 32> buffer(ianaTimeZoneLength);
         status = U_ZERO_ERROR;
         auto canonicalLength = ucal_getCanonicalTimeZoneID(ianaTimeZone, ianaTimeZoneLength, buffer.data(), ianaTimeZoneLength, nullptr, &status);
-        if (status == U_BUFFER_OVERFLOW_ERROR) {
+        if (needsToGrowToProduceBuffer(status)) {
             buffer.grow(canonicalLength);
             status = U_ZERO_ERROR;
             ucal_getCanonicalTimeZoneID(ianaTimeZone, ianaTimeZoneLength, buffer.data(), canonicalLength, nullptr, &status);
@@ -650,7 +651,7 @@
     Vector<UChar, 32> patternBuffer(32);
     status = U_ZERO_ERROR;
     auto patternLength = udatpg_getBestPatternWithOptions(generator, skeletonView.upconvertedCharacters(), skeletonView.length(), UDATPG_MATCH_HOUR_FIELD_LENGTH, patternBuffer.data(), patternBuffer.size(), &status);
-    if (status == U_BUFFER_OVERFLOW_ERROR) {
+    if (needsToGrowToProduceBuffer(status)) {
         status = U_ZERO_ERROR;
         patternBuffer.grow(patternLength);
         udatpg_getBestPattern(generator, skeletonView.upconvertedCharacters(), skeletonView.length(), patternBuffer.data(), patternLength, &status);
@@ -908,7 +909,7 @@
     UErrorCode status = U_ZERO_ERROR;
     Vector<UChar, 32> result(32);
     auto resultLength = udat_format(m_dateFormat.get(), value, result.data(), result.size(), nullptr, &status);
-    if (status == U_BUFFER_OVERFLOW_ERROR) {
+    if (needsToGrowToProduceBuffer(status)) {
         status = U_ZERO_ERROR;
         result.grow(resultLength);
         udat_format(m_dateFormat.get(), value, result.data(), resultLength, nullptr, &status);
@@ -1000,7 +1001,7 @@
     status = U_ZERO_ERROR;
     Vector<UChar, 32> result(32);
     auto resultLength = udat_formatForFields(m_dateFormat.get(), value, result.data(), result.size(), fields.get(), &status);
-    if (status == U_BUFFER_OVERFLOW_ERROR) {
+    if (needsToGrowToProduceBuffer(status)) {
         status = U_ZERO_ERROR;
         result.grow(resultLength);
         udat_formatForFields(m_dateFormat.get(), value, result.data(), resultLength, fields.get(), &status);

Modified: trunk/Source/_javascript_Core/runtime/IntlNumberFormat.cpp (260881 => 260882)


--- trunk/Source/_javascript_Core/runtime/IntlNumberFormat.cpp	2020-04-29 07:09:44 UTC (rev 260881)
+++ trunk/Source/_javascript_Core/runtime/IntlNumberFormat.cpp	2020-04-29 07:15:18 UTC (rev 260882)
@@ -37,6 +37,7 @@
 #include "JSCInlines.h"
 #include "ObjectConstructor.h"
 #include <unicode/ufieldpositer.h>
+#include <wtf/unicode/icu/ICUHelpers.h>
 
 namespace JSC {
 
@@ -361,7 +362,7 @@
     UErrorCode status = U_ZERO_ERROR;
     Vector<UChar, 32> buffer(32);
     auto length = unum_formatDouble(m_numberFormat.get(), value, buffer.data(), buffer.size(), nullptr, &status);
-    if (status == U_BUFFER_OVERFLOW_ERROR) {
+    if (needsToGrowToProduceBuffer(status)) {
         buffer.grow(length);
         status = U_ZERO_ERROR;
         unum_formatDouble(m_numberFormat.get(), value, buffer.data(), length, nullptr, &status);
@@ -389,7 +390,7 @@
     UErrorCode status = U_ZERO_ERROR;
     Vector<UChar, 32> buffer(32);
     auto length = unum_formatDecimal(m_numberFormat.get(), rawString, string.length(), buffer.data(), buffer.size(), nullptr, &status);
-    if (status == U_BUFFER_OVERFLOW_ERROR) {
+    if (needsToGrowToProduceBuffer(status)) {
         buffer.grow(length);
         status = U_ZERO_ERROR;
         unum_formatDecimal(m_numberFormat.get(), rawString, string.length(), buffer.data(), length, nullptr, &status);
@@ -552,7 +553,7 @@
 
     Vector<UChar, 32> result(32);
     auto resultLength = unum_formatDoubleForFields(m_numberFormat.get(), value, result.data(), result.size(), fieldItr.get(), &status);
-    if (status == U_BUFFER_OVERFLOW_ERROR) {
+    if (needsToGrowToProduceBuffer(status)) {
         status = U_ZERO_ERROR;
         result.grow(resultLength);
         unum_formatDoubleForFields(m_numberFormat.get(), value, result.data(), resultLength, fieldItr.get(), &status);

Modified: trunk/Source/_javascript_Core/runtime/IntlObject.cpp (260881 => 260882)


--- trunk/Source/_javascript_Core/runtime/IntlObject.cpp	2020-04-29 07:09:44 UTC (rev 260881)
+++ trunk/Source/_javascript_Core/runtime/IntlObject.cpp	2020-04-29 07:15:18 UTC (rev 260882)
@@ -54,6 +54,7 @@
 #include <wtf/NeverDestroyed.h>
 #include <wtf/text/StringBuilder.h>
 #include <wtf/text/StringImpl.h>
+#include <wtf/unicode/icu/ICUHelpers.h>
 
 namespace JSC {
 
@@ -144,13 +145,17 @@
     UErrorCode status = U_ZERO_ERROR;
     Vector<char, 32> buffer(32);
     auto length = uloc_toLanguageTag(localeID, buffer.data(), buffer.size(), false, &status);
-    if (status == U_BUFFER_OVERFLOW_ERROR) {
+    if (needsToGrowToProduceBuffer(status)) {
         buffer.grow(length);
         status = U_ZERO_ERROR;
         uloc_toLanguageTag(localeID, buffer.data(), buffer.size(), false, &status);
     }
-    if (!U_FAILURE(status))
+    if (!U_FAILURE(status)) {
+        // This is used to store into static variables that may be shared across 
+        // JSC execution threads. This must be immortal to make concurrent ref/deref
+        // safe.
         return String(StringImpl::createStaticStringImpl(buffer.data(), length));
+    }
     return String();
 }
 
@@ -322,10 +327,10 @@
     // - uloc_toLanguageTag doesn't take an input size param so we must ensure the string is null-terminated ourselves
     // - before ICU 64, there's a chance that it will "buffer overflow" while requesting a *smaller* size
     UErrorCode status = U_ZERO_ERROR;
-    Vector<char, 32> intermediate(31);
+    Vector<char, 32> intermediate(32);
     int32_t parsedLength;
     auto intermediateLength = uloc_forLanguageTag(input.data(), intermediate.data(), intermediate.size(), &parsedLength, &status);
-    if (status == U_BUFFER_OVERFLOW_ERROR) {
+    if (needsToGrowToProduceCString(status)) {
         intermediate.resize(intermediateLength + 1);
         status = U_ZERO_ERROR;
         uloc_forLanguageTag(input.data(), intermediate.data(), intermediateLength + 1, &parsedLength, &status);
@@ -333,9 +338,12 @@
     if (U_FAILURE(status) || parsedLength != static_cast<int32_t>(input.length()))
         return String();
 
+    ASSERT(intermediate.contains('\0'));
+
+    status = U_ZERO_ERROR;
     Vector<char, 32> result(32);
     auto resultLength = uloc_toLanguageTag(intermediate.data(), result.data(), result.size(), false, &status);
-    if (status == U_BUFFER_OVERFLOW_ERROR) {
+    if (needsToGrowToProduceBuffer(status)) {
         result.grow(resultLength);
         status = U_ZERO_ERROR;
         uloc_toLanguageTag(intermediate.data(), result.data(), resultLength, false, &status);

Modified: trunk/Source/_javascript_Core/runtime/IntlRelativeTimeFormat.cpp (260881 => 260882)


--- trunk/Source/_javascript_Core/runtime/IntlRelativeTimeFormat.cpp	2020-04-29 07:09:44 UTC (rev 260881)
+++ trunk/Source/_javascript_Core/runtime/IntlRelativeTimeFormat.cpp	2020-04-29 07:15:18 UTC (rev 260882)
@@ -31,6 +31,7 @@
 #include "IntlObject.h"
 #include "JSCInlines.h"
 #include "ObjectConstructor.h"
+#include <wtf/unicode/icu/ICUHelpers.h>
 
 namespace JSC {
 
@@ -253,7 +254,7 @@
     UErrorCode status = U_ZERO_ERROR;
     Vector<UChar, 32> result(32);
     auto resultLength = formatRelativeTime(m_relativeDateTimeFormatter.get(), value, unitType.value(), result.data(), result.size(), &status);
-    if (status == U_BUFFER_OVERFLOW_ERROR) {
+    if (needsToGrowToProduceBuffer(status)) {
         status = U_ZERO_ERROR;
         result.grow(resultLength);
         formatRelativeTime(m_relativeDateTimeFormatter.get(), value, unitType.value(), result.data(), resultLength, &status);
@@ -295,7 +296,7 @@
 
     Vector<UChar, 32> buffer(32);
     auto numberLength = unum_formatDoubleForFields(m_numberFormat.get(), absValue, buffer.data(), buffer.size(), iterator.get(), &status);
-    if (status == U_BUFFER_OVERFLOW_ERROR) {
+    if (needsToGrowToProduceBuffer(status)) {
         status = U_ZERO_ERROR;
         buffer.grow(numberLength);
         unum_formatDoubleForFields(m_numberFormat.get(), absValue, buffer.data(), numberLength, iterator.get(), &status);

Modified: trunk/Source/_javascript_Core/runtime/StringPrototype.cpp (260881 => 260882)


--- trunk/Source/_javascript_Core/runtime/StringPrototype.cpp	2020-04-29 07:09:44 UTC (rev 260881)
+++ trunk/Source/_javascript_Core/runtime/StringPrototype.cpp	2020-04-29 07:15:18 UTC (rev 260882)
@@ -58,6 +58,7 @@
 #include <wtf/MathExtras.h>
 #include <wtf/text/StringBuilder.h>
 #include <wtf/text/StringView.h>
+#include <wtf/unicode/icu/ICUHelpers.h>
 
 namespace JSC {
 
@@ -1620,15 +1621,15 @@
     // 17. Let L be a String whose elements are, in order, the elements of cuList.
 
     // Most strings lower/upper case will be the same size as original, so try that first.
-    UErrorCode error(U_ZERO_ERROR);
+    UErrorCode error = U_ZERO_ERROR;
     Vector<UChar> buffer(viewLength);
     String lower;
     const int32_t resultLength = convertCase(buffer.data(), viewLength, view.upconvertedCharacters(), viewLength, utf8LocaleBuffer.data(), &error);
     if (U_SUCCESS(error))
         lower = String(buffer.data(), resultLength);
-    else if (error == U_BUFFER_OVERFLOW_ERROR) {
+    else if (needsToGrowToProduceBuffer(error)) {
         // Converted case needs more space than original. Try again.
-        UErrorCode error(U_ZERO_ERROR);
+        UErrorCode error = U_ZERO_ERROR;
         Vector<UChar> buffer(resultLength);
         convertCase(buffer.data(), resultLength, view.upconvertedCharacters(), viewLength, utf8LocaleBuffer.data(), &error);
         if (U_FAILURE(error))
@@ -1926,7 +1927,7 @@
         RELEASE_AND_RETURN(scope, string);
 
     int32_t normalizedStringLength = unorm2_normalize(normalizer, characters, view.length(), nullptr, 0, &status);
-    ASSERT(status == U_BUFFER_OVERFLOW_ERROR);
+    ASSERT(needsToGrowToProduceBuffer(status));
 
     UChar* buffer;
     auto result = StringImpl::tryCreateUninitialized(normalizedStringLength, buffer);

Modified: trunk/Source/WTF/ChangeLog (260881 => 260882)


--- trunk/Source/WTF/ChangeLog	2020-04-29 07:09:44 UTC (rev 260881)
+++ trunk/Source/WTF/ChangeLog	2020-04-29 07:15:18 UTC (rev 260882)
@@ -1,3 +1,43 @@
+2020-04-29  Saam Barati  <[email protected]>
+
+        U_STRING_NOT_TERMINATED_WARNING ICU must be handled when using the output buffer as a C string
+        https://bugs.webkit.org/show_bug.cgi?id=211142
+        <rdar://problem/62530860>
+
+        Reviewed by Darin Adler.
+
+        Most of our uses of ICU require us to produce a buffer of the correct
+        length. We often test if the first call to ICU API succeeds, and if it
+        doesn't, we grow to the required buffer size, and try again. However,
+        there are a few APIs that we use like this, except that they write their
+        output to a C string instead of a buffer.
+        
+        In a couple scenarios when we were producing C strings, we were only testing
+        for the U_BUFFER_OVERFLOW_ERROR, instead of both U_BUFFER_OVERFLOW_ERROR and
+        U_STRING_NOT_TERMINATED_WARNING. This patch fixes those bugs. It also
+        introduces two new helper methods for testing error codes returned by ICU.
+        
+        - The first is needsToGrowToProduceBuffer, which returns true if we need to
+        grow the buffer and re-call into ICU to get the result.
+        - The second is needsToGrowToProduceCString, which returns true if we need to
+        grow the buffer and re-call into ICU to produce a valid C string.
+        
+        I've audited all uses of U_BUFFER_OVERFLOW_ERROR and converted them to use one
+        of the above helper methods instead.
+        
+        The issues in our handling of U_STRING_NOT_TERMINATED_WARNING were caught on iOS JSC
+        tests in JSTests/stress/intl-datetimeformat.js
+
+        * WTF.xcodeproj/project.pbxproj:
+        * wtf/CMakeLists.txt:
+        * wtf/text/LineBreakIteratorPoolICU.h:
+        (WTF::LineBreakIteratorPool::makeLocaleWithBreakKeyword):
+        * wtf/text/StringView.cpp:
+        (WTF::normalizedNFC):
+        * wtf/unicode/icu/ICUHelpers.h: Added.
+        (WTF::needsToGrowToProduceCString):
+        (WTF::needsToGrowToProduceBuffer):
+
 2020-04-29  Noam Rosenthal  <[email protected]>
 
         Add StringView::isAllSpecialCharacters()

Modified: trunk/Source/WTF/WTF.xcodeproj/project.pbxproj (260881 => 260882)


--- trunk/Source/WTF/WTF.xcodeproj/project.pbxproj	2020-04-29 07:09:44 UTC (rev 260881)
+++ trunk/Source/WTF/WTF.xcodeproj/project.pbxproj	2020-04-29 07:15:18 UTC (rev 260882)
@@ -392,6 +392,7 @@
 		51F175291F3D486000C74950 /* PersistentEncoder.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = PersistentEncoder.cpp; sourceTree = "<group>"; };
 		51F1752A1F3D486000C74950 /* PersistentEncoder.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PersistentEncoder.h; sourceTree = "<group>"; };
 		526AEC911F6B4E5C00695F5D /* NoTailCalls.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = NoTailCalls.h; sourceTree = "<group>"; };
+		52B228C12458DC8200753D91 /* ICUHelpers.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ICUHelpers.h; sourceTree = "<group>"; };
 		530A63481FA3E3A00026A545 /* Scripts */ = {isa = PBXFileReference; lastKnownFileType = folder; path = Scripts; sourceTree = "<group>"; };
 		5311BD511EA71CAD00525281 /* Signals.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Signals.cpp; sourceTree = "<group>"; };
 		5311BD551EA7E15A00525281 /* LocklessBag.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LocklessBag.h; sourceTree = "<group>"; };
@@ -1438,6 +1439,7 @@
 		A8A4734F151A825B004123FF /* icu */ = {
 			isa = PBXGroup;
 			children = (
+				52B228C12458DC8200753D91 /* ICUHelpers.h */,
 				A8A47350151A825B004123FF /* CollatorICU.cpp */,
 			);
 			path = icu;

Modified: trunk/Source/WTF/wtf/CMakeLists.txt (260881 => 260882)


--- trunk/Source/WTF/wtf/CMakeLists.txt	2020-04-29 07:09:44 UTC (rev 260881)
+++ trunk/Source/WTF/wtf/CMakeLists.txt	2020-04-29 07:15:18 UTC (rev 260882)
@@ -358,6 +358,8 @@
     unicode/CharacterNames.h
     unicode/Collator.h
     unicode/UTF8Conversion.h
+
+    unicode/icu/ICUHelpers.h
 )
 
 set(WTF_SOURCES

Modified: trunk/Source/WTF/wtf/text/LineBreakIteratorPoolICU.h (260881 => 260882)


--- trunk/Source/WTF/wtf/text/LineBreakIteratorPoolICU.h	2020-04-29 07:09:44 UTC (rev 260881)
+++ trunk/Source/WTF/wtf/text/LineBreakIteratorPoolICU.h	2020-04-29 07:15:18 UTC (rev 260882)
@@ -30,6 +30,7 @@
 #include <wtf/NeverDestroyed.h>
 #include <wtf/ThreadSpecific.h>
 #include <wtf/text/AtomString.h>
+#include <wtf/unicode/icu/ICUHelpers.h>
 
 namespace WTF {
 
@@ -74,7 +75,7 @@
         int32_t lengthNeeded = uloc_setKeywordValue("lb", keywordValue, scratchBuffer.data(), scratchBuffer.size(), &status);
         if (U_SUCCESS(status))
             return AtomString::fromUTF8(scratchBuffer.data(), lengthNeeded);
-        if (status == U_BUFFER_OVERFLOW_ERROR) {
+        if (needsToGrowToProduceBuffer(status)) {
             scratchBuffer.grow(lengthNeeded + 1);
             memset(scratchBuffer.data() + utf8Locale.length(), 0, scratchBuffer.size() - utf8Locale.length());
             status = U_ZERO_ERROR;

Modified: trunk/Source/WTF/wtf/text/StringView.cpp (260881 => 260882)


--- trunk/Source/WTF/wtf/text/StringView.cpp	2020-04-29 07:09:44 UTC (rev 260881)
+++ trunk/Source/WTF/wtf/text/StringView.cpp	2020-04-29 07:15:18 UTC (rev 260882)
@@ -37,6 +37,7 @@
 #include <wtf/Optional.h>
 #include <wtf/text/StringToIntegerConversion.h>
 #include <wtf/text/TextBreakIterator.h>
+#include <wtf/unicode/icu/ICUHelpers.h>
 
 namespace WTF {
 
@@ -291,7 +292,7 @@
         return { string, { } };
 
     unsigned normalizedLength = unorm2_normalize(normalizer, string.characters16(), string.length(), nullptr, 0, &status);
-    ASSERT(status == U_BUFFER_OVERFLOW_ERROR);
+    ASSERT(needsToGrowToProduceBuffer(status));
 
     UChar* characters;
     String result = String::createUninitialized(normalizedLength, characters);

Added: trunk/Source/WTF/wtf/unicode/icu/ICUHelpers.h (0 => 260882)


--- trunk/Source/WTF/wtf/unicode/icu/ICUHelpers.h	                        (rev 0)
+++ trunk/Source/WTF/wtf/unicode/icu/ICUHelpers.h	2020-04-29 07:15:18 UTC (rev 260882)
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2020 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
+
+#include <unicode/utypes.h>
+
+namespace WTF {
+
+inline bool needsToGrowToProduceCString(UErrorCode errorCode)
+{
+    return errorCode == U_BUFFER_OVERFLOW_ERROR || errorCode == U_STRING_NOT_TERMINATED_WARNING;
+}
+
+inline bool needsToGrowToProduceBuffer(UErrorCode errorCode)
+{
+    return errorCode == U_BUFFER_OVERFLOW_ERROR;
+}
+
+}
+
+using WTF::needsToGrowToProduceCString;
+using WTF::needsToGrowToProduceBuffer;

Modified: trunk/Source/WebCore/ChangeLog (260881 => 260882)


--- trunk/Source/WebCore/ChangeLog	2020-04-29 07:09:44 UTC (rev 260881)
+++ trunk/Source/WebCore/ChangeLog	2020-04-29 07:15:18 UTC (rev 260882)
@@ -1,3 +1,25 @@
+2020-04-29  Saam Barati  <[email protected]>
+
+        U_STRING_NOT_TERMINATED_WARNING ICU must be handled when using the output buffer as a C string
+        https://bugs.webkit.org/show_bug.cgi?id=211142
+        <rdar://problem/62530860>
+
+        Reviewed by Darin Adler.
+
+        * editing/TextIterator.cpp:
+        (WebCore::normalizeCharacters):
+        * platform/text/LocaleICU.cpp:
+        (WebCore::LocaleICU::decimalSymbol):
+        (WebCore::LocaleICU::decimalTextAttribute):
+        (WebCore::getDateFormatPattern):
+        (WebCore::LocaleICU::createLabelVector):
+        (WebCore::getFormatForSkeleton):
+        * platform/text/LocaleToScriptMappingICU.cpp:
+        (WebCore::localeToScriptCodeForFontSelection):
+        * platform/text/TextCodecICU.cpp:
+        (WebCore::TextCodecICU::decode):
+        (WebCore::TextCodecICU::encode):
+
 2020-04-29  Noam Rosenthal  <[email protected]>
 
         Add StringView::isAllSpecialCharacters()

Modified: trunk/Source/WebCore/editing/TextIterator.cpp (260881 => 260882)


--- trunk/Source/WebCore/editing/TextIterator.cpp	2020-04-29 07:09:44 UTC (rev 260881)
+++ trunk/Source/WebCore/editing/TextIterator.cpp	2020-04-29 07:15:18 UTC (rev 260882)
@@ -66,6 +66,7 @@
 #include <wtf/text/StringBuilder.h>
 #include <wtf/text/TextBreakIterator.h>
 #include <wtf/unicode/CharacterNames.h>
+#include <wtf/unicode/icu/ICUHelpers.h>
 
 #if !UCONFIG_NO_COLLATION
 #include <unicode/usearch.h>
@@ -1836,7 +1837,7 @@
     buffer.resize(length);
 
     auto normalizedLength = unorm2_normalize(normalizer, characters, length, buffer.data(), length, &status);
-    ASSERT(U_SUCCESS(status) || status == U_BUFFER_OVERFLOW_ERROR);
+    ASSERT(U_SUCCESS(status) || needsToGrowToProduceBuffer(status));
 
     buffer.resize(normalizedLength);
 

Modified: trunk/Source/WebCore/platform/text/LocaleICU.cpp (260881 => 260882)


--- trunk/Source/WebCore/platform/text/LocaleICU.cpp	2020-04-29 07:09:44 UTC (rev 260881)
+++ trunk/Source/WebCore/platform/text/LocaleICU.cpp	2020-04-29 07:15:18 UTC (rev 260882)
@@ -37,6 +37,7 @@
 #include <unicode/uloc.h>
 #include <wtf/DateMath.h>
 #include <wtf/text/StringBuilder.h>
+#include <wtf/unicode/icu/ICUHelpers.h>
 
 
 namespace WebCore {
@@ -69,8 +70,8 @@
 {
     UErrorCode status = U_ZERO_ERROR;
     int32_t bufferLength = unum_getSymbol(m_numberFormat, symbol, 0, 0, &status);
-    ASSERT(U_SUCCESS(status) || status == U_BUFFER_OVERFLOW_ERROR);
-    if (U_FAILURE(status) && status != U_BUFFER_OVERFLOW_ERROR)
+    ASSERT(U_SUCCESS(status) || needsToGrowToProduceBuffer(status));
+    if (U_FAILURE(status) && !needsToGrowToProduceBuffer(status))
         return String();
     Vector<UChar> buffer(bufferLength);
     status = U_ZERO_ERROR;
@@ -84,8 +85,8 @@
 {
     UErrorCode status = U_ZERO_ERROR;
     int32_t bufferLength = unum_getTextAttribute(m_numberFormat, tag, 0, 0, &status);
-    ASSERT(U_SUCCESS(status) || status == U_BUFFER_OVERFLOW_ERROR);
-    if (U_FAILURE(status) && status != U_BUFFER_OVERFLOW_ERROR)
+    ASSERT(U_SUCCESS(status) || needsToGrowToProduceBuffer(status));
+    if (U_FAILURE(status) && !needsToGrowToProduceBuffer(status))
         return String();
     Vector<UChar> buffer(bufferLength);
     status = U_ZERO_ERROR;
@@ -150,7 +151,7 @@
 
     UErrorCode status = U_ZERO_ERROR;
     int32_t length = udat_toPattern(dateFormat, TRUE, 0, 0, &status);
-    if (status != U_BUFFER_OVERFLOW_ERROR || !length)
+    if (!needsToGrowToProduceBuffer(status) || !length)
         return emptyString();
     Vector<UChar> buffer(length);
     status = U_ZERO_ERROR;
@@ -172,7 +173,7 @@
     for (int32_t i = 0; i < size; ++i) {
         UErrorCode status = U_ZERO_ERROR;
         int32_t length = udat_getSymbols(dateFormat, type, startIndex + i, 0, 0, &status);
-        if (status != U_BUFFER_OVERFLOW_ERROR)
+        if (!needsToGrowToProduceBuffer(status))
             return makeUnique<Vector<String>>();
         Vector<UChar> buffer(length);
         status = U_ZERO_ERROR;
@@ -264,7 +265,7 @@
         return format;
     status = U_ZERO_ERROR;
     int32_t length = udatpg_getBestPattern(patternGenerator, skeleton, skeletonLength, 0, 0, &status);
-    if (status == U_BUFFER_OVERFLOW_ERROR && length) {
+    if (needsToGrowToProduceBuffer(status) && length) {
         Vector<UChar> buffer(length);
         status = U_ZERO_ERROR;
         udatpg_getBestPattern(patternGenerator, skeleton, skeletonLength, buffer.data(), length, &status);

Modified: trunk/Source/WebCore/platform/text/LocaleToScriptMappingICU.cpp (260881 => 260882)


--- trunk/Source/WebCore/platform/text/LocaleToScriptMappingICU.cpp	2020-04-29 07:09:44 UTC (rev 260881)
+++ trunk/Source/WebCore/platform/text/LocaleToScriptMappingICU.cpp	2020-04-29 07:15:18 UTC (rev 260882)
@@ -34,6 +34,7 @@
 #include <unicode/uloc.h>
 #include <wtf/text/CString.h>
 #include <wtf/text/WTFString.h>
+#include <wtf/unicode/icu/ICUHelpers.h>
 
 namespace WebCore {
 
@@ -71,7 +72,7 @@
     UScriptCode scriptCode = USCRIPT_COMMON;
     uscript_getCode(script, &scriptCode, 1, &status);
     // Ignore error that multiple scripts could be returned, since we only want one script.
-    if (U_FAILURE(status) && status != U_BUFFER_OVERFLOW_ERROR)
+    if (U_FAILURE(status) && !needsToGrowToProduceBuffer(status))
         return USCRIPT_COMMON;
 
     return scriptCodeForFontSelection(scriptCode);

Modified: trunk/Source/WebCore/platform/text/TextCodecICU.cpp (260881 => 260882)


--- trunk/Source/WebCore/platform/text/TextCodecICU.cpp	2020-04-29 07:09:44 UTC (rev 260881)
+++ trunk/Source/WebCore/platform/text/TextCodecICU.cpp	2020-04-29 07:15:18 UTC (rev 260882)
@@ -36,6 +36,7 @@
 #include <wtf/text/CString.h>
 #include <wtf/text/StringBuilder.h>
 #include <wtf/unicode/CharacterNames.h>
+#include <wtf/unicode/icu/ICUHelpers.h>
 
 namespace WebCore {
 
@@ -308,7 +309,7 @@
     do {
         int ucharsDecoded = decodeToBuffer(buffer, bufferLimit, source, sourceLimit, offsets, flush, err);
         result.appendCharacters(buffer, ucharsDecoded);
-    } while (err == U_BUFFER_OVERFLOW_ERROR);
+    } while (needsToGrowToProduceBuffer(err));
 
     if (U_FAILURE(err)) {
         // flush the converter so it can be reused, and not be bothered by this error.
@@ -461,7 +462,7 @@
         error = U_ZERO_ERROR;
         ucnv_fromUnicode(m_converter.get(), &target, targetLimit, &source, sourceLimit, 0, true, &error);
         result.append(reinterpret_cast<uint8_t*>(buffer), target - buffer);
-    } while (error == U_BUFFER_OVERFLOW_ERROR);
+    } while (needsToGrowToProduceBuffer(error));
     return result;
 }
 
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to