Skip to content

Commit ce816cc

Browse files
author
Mark Lam
committed
Make Intl.Segmenter more resilient to an OutOfMemory error.
https://bugs.webkit.org/show_bug.cgi?id=263278 rdar://116884999 Reviewed by Justin Michaud. * JSTests/stress/out-of-memory-in-intl-segmenter.js: Added. (catch): * Source/JavaScriptCore/JavaScriptCore.order: * Source/JavaScriptCore/runtime/IntlSegmenter.cpp: (JSC::IntlSegmenter::segment const): * Source/WTF/wtf/URLHelpers.cpp: (WTF::URLHelpers::mapHostName): * Source/WTF/wtf/text/WTFString.cpp: (WTF::String::charactersWithoutNullTermination const): (WTF::String::charactersWithNullTermination const): * Source/WTF/wtf/text/WTFString.h: * Source/WebCore/PAL/pal/text/win/TextCodecWin.cpp: (PAL::TextCodecWin::enumerateSupportedEncodings): * Source/WebCore/platform/win/ClipboardUtilitiesWin.cpp: (WebCore::setFileDescriptorData): Canonical link: https://commits.webkit.org/269471@main
1 parent de69fde commit ce816cc

File tree

8 files changed

+38
-14
lines changed

8 files changed

+38
-14
lines changed
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
//@ skip if $memoryLimited
2+
3+
var exception;
4+
try {
5+
let a = 'a'.repeat(2147483647);
6+
const segmenter = new Intl.Segmenter('en');
7+
const iter = segmenter.segment(a);
8+
} catch (e) {
9+
exception = e;
10+
}
11+
12+
if (exception != "RangeError: Out of memory")
13+
throw "FAILED";
14+

Source/JavaScriptCore/JavaScriptCore.order

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,6 @@ __ZN3WTFL16threadEntryPointEPv
8181
__ZN3WTF31initializeCurrentThreadInternalEPKc
8282
__ZN3WTF20ThreadIdentifierData10initializeEj
8383
__ZN3WTF5MutexD1Ev
84-
__ZN3WTF6String29charactersWithNullTerminationEv
8584
__ZN3WTF10StringImpl34createWithTerminatingNullCharacterERKS0_
8685
__ZNK3WTF10StringImpl17getData16SlowCaseEv
8786
__ZN3WTF15AutodrainedPoolC1Ev

Source/JavaScriptCore/runtime/IntlSegmenter.cpp

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,13 @@ JSValue IntlSegmenter::segment(JSGlobalObject* globalObject, JSValue stringValue
117117
RETURN_IF_EXCEPTION(scope, { });
118118
String string = jsString->value(globalObject);
119119
RETURN_IF_EXCEPTION(scope, { });
120-
auto upconvertedCharacters = Box<Vector<UChar>>::create(string.charactersWithoutNullTermination());
120+
auto expectedCharacters = string.charactersWithoutNullTermination();
121+
if (!expectedCharacters) {
122+
throwOutOfMemoryError(globalObject, scope);
123+
return { };
124+
}
125+
126+
auto upconvertedCharacters = Box<Vector<UChar>>::create(expectedCharacters.value());
121127

122128
UErrorCode status = U_ZERO_ERROR;
123129
auto segmenter = std::unique_ptr<UBreakIterator, UBreakIteratorDeleter>(cloneUBreakIterator(m_segmenter.get(), &status));

Source/WTF/wtf/URLHelpers.cpp

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (C) 2005-2022 Apple Inc. All rights reserved.
2+
* Copyright (C) 2005-2023 Apple Inc. All rights reserved.
33
* Copyright (C) 2018 Igalia S.L.
44
*
55
* Redistribution and use in source and binary forms, with or without
@@ -648,8 +648,11 @@ std::optional<String> mapHostName(const String& hostName, URLDecodeFunction deco
648648

649649
unsigned length = string.length();
650650

651-
auto sourceBuffer = string.charactersWithNullTermination();
652-
651+
auto expectedSourceBuffer = string.charactersWithNullTermination();
652+
if (!expectedSourceBuffer)
653+
return std::nullopt;
654+
auto sourceBuffer = expectedSourceBuffer.value();
655+
653656
UChar destinationBuffer[URLParser::hostnameBufferLength];
654657
UErrorCode uerror = U_ZERO_ERROR;
655658
UIDNAInfo processingDetails = UIDNA_INFO_INITIALIZER;

Source/WTF/wtf/text/WTFString.cpp

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
/*
22
* (C) 1999 Lars Knoll ([email protected])
3-
* Copyright (C) 2004-2019 Apple Inc. All rights reserved.
3+
* Copyright (C) 2004-2023 Apple Inc. All rights reserved.
44
* Copyright (C) 2007-2009 Torch Mobile, Inc.
55
*
66
* This library is free software; you can redistribute it and/or
@@ -171,12 +171,13 @@ String String::foldCase() const
171171
return m_impl ? m_impl->foldCase() : String { };
172172
}
173173

174-
Vector<UChar> String::charactersWithoutNullTermination() const
174+
Expected<Vector<UChar>, UTF8ConversionError> String::charactersWithoutNullTermination() const
175175
{
176176
Vector<UChar> result;
177177

178178
if (m_impl) {
179-
result.reserveInitialCapacity(length() + 1);
179+
if (!result.tryReserveInitialCapacity(length() + 1))
180+
return makeUnexpected(UTF8ConversionError::OutOfMemory);
180181

181182
if (is8Bit()) {
182183
const LChar* characters8 = m_impl->characters8();
@@ -190,10 +191,11 @@ Vector<UChar> String::charactersWithoutNullTermination() const
190191
return result;
191192
}
192193

193-
Vector<UChar> String::charactersWithNullTermination() const
194+
Expected<Vector<UChar>, UTF8ConversionError> String::charactersWithNullTermination() const
194195
{
195196
auto result = charactersWithoutNullTermination();
196-
result.append(0);
197+
if (result)
198+
result.value().append(0);
197199
return result;
198200
}
199201

Source/WTF/wtf/text/WTFString.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -161,8 +161,8 @@ class String final {
161161
size_t reverseFind(ASCIILiteral literal, unsigned start = MaxLength) const { return m_impl ? m_impl->reverseFind(literal, start) : notFound; }
162162
size_t reverseFind(StringView, unsigned start = MaxLength) const;
163163

164-
WTF_EXPORT_PRIVATE Vector<UChar> charactersWithNullTermination() const;
165-
WTF_EXPORT_PRIVATE Vector<UChar> charactersWithoutNullTermination() const;
164+
WTF_EXPORT_PRIVATE Expected<Vector<UChar>, UTF8ConversionError> charactersWithNullTermination() const;
165+
WTF_EXPORT_PRIVATE Expected<Vector<UChar>, UTF8ConversionError> charactersWithoutNullTermination() const;
166166

167167
WTF_EXPORT_PRIVATE UChar32 characterStartingAt(unsigned) const;
168168

Source/WebCore/PAL/pal/text/win/TextCodecWin.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -298,7 +298,7 @@ void TextCodecWin::enumerateSupportedEncodings(EncodingReceiver& receiver)
298298
languageManager();
299299
for (CharsetSet::iterator i = supportedCharsets().begin(); i != supportedCharsets().end(); ++i) {
300300
HashMap<String, CharsetInfo>::iterator j = knownCharsets().find(*i);
301-
if (j != knownCharsets().end() && !receiver.receive(j->value.m_name.data(), j->value.m_friendlyName.charactersWithNullTermination().data(), j->value.m_codePage))
301+
if (j != knownCharsets().end() && !receiver.receive(j->value.m_name.data(), j->value.m_friendlyName.charactersWithNullTermination()->data(), j->value.m_codePage))
302302
break;
303303
}
304304
}

Source/WebCore/platform/win/ClipboardUtilitiesWin.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -418,7 +418,7 @@ void setFileDescriptorData(IDataObject* dataObject, int size, const String& pass
418418
fgd->fgd[0].nFileSizeLow = size;
419419

420420
int maxSize = std::min<int>(pathname.length(), std::size(fgd->fgd[0].cFileName));
421-
CopyMemory(fgd->fgd[0].cFileName, pathname.charactersWithNullTermination().data(), maxSize * sizeof(UChar));
421+
CopyMemory(fgd->fgd[0].cFileName, pathname.charactersWithNullTermination()->data(), maxSize * sizeof(UChar));
422422
GlobalUnlock(medium.hGlobal);
423423

424424
dataObject->SetData(fileDescriptorFormat(), &medium, TRUE);

0 commit comments

Comments
 (0)