From 28d0667d28378437cdb05d2e5b7600adfe6ee6dd Mon Sep 17 00:00:00 2001 From: robobun <117481402+robobun@users.noreply.github.com> Date: Mon, 20 Jul 2026 04:14:00 +0000 Subject: [PATCH] IntlCollator: throw OOM instead of crashing when upconverting a >=2^30 Latin-1 string StringView::upconvertedCharacters() grows a Vector, and WTF::Vector caps capacity at (UINT_MAX >> 1) / sizeof(T). For char16_t that is 2^30 - 1 elements, so an 8-bit StringView of length >= 2^30 hits the FailureAction::Crash path in VectorBufferBase::allocateBuffer and aborts the process. compareStrings() reaches the ucol_strcoll fallback whenever the DUCET fast path bails (control characters, non-ASCII Latin-1, or a collator that cannot use the table). With a Latin-1 string at the 1 GiB boundary that upconversion is the first allocation we make, so 'x'.localeCompare('\x00'.repeat(2**30)) and the equivalent Intl.Collator().compare() SIGABRT. Check the length before upconverting and throw an Out of memory RangeError, matching the guard that already protects String.prototype.normalize() in StringPrototype.cpp. --- Source/JavaScriptCore/runtime/IntlCollator.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/Source/JavaScriptCore/runtime/IntlCollator.cpp b/Source/JavaScriptCore/runtime/IntlCollator.cpp index 6d745aa0e534..a85355d41e29 100644 --- a/Source/JavaScriptCore/runtime/IntlCollator.cpp +++ b/Source/JavaScriptCore/runtime/IntlCollator.cpp @@ -310,8 +310,13 @@ UCollationResult IntlCollator::compareStrings(JSGlobalObject* globalObject, Stri return std::nullopt; }()); - if (!result) + if (!result) { + if ((x.is8Bit() && x.length() >= (1u << 30)) || (y.is8Bit() && y.length() >= (1u << 30))) [[unlikely]] { + throwOutOfMemoryError(globalObject, scope); + return { }; + } result = ucol_strcoll(m_collator.get(), x.upconvertedCharacters(), x.length(), y.upconvertedCharacters(), y.length()); + } if (U_FAILURE(status)) { throwException(globalObject, scope, createError(globalObject, "Failed to compare strings."_s));