Skip to content

Commit b99834b

Browse files
committed
Update String.prototype.repeat to throw non-fatal for length too big
1 parent 38662ef commit b99834b

File tree

2 files changed

+21
-3
lines changed

2 files changed

+21
-3
lines changed

lib/Runtime/Library/JavascriptString.cpp

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2574,9 +2574,18 @@ namespace Js
25742574

25752575
if (args.Info.Count > 1)
25762576
{
2577-
if (!JavascriptOperators::IsUndefinedObject(args[1]))
2577+
if (TaggedInt::Is(args[1]))
25782578
{
2579-
double countDbl = JavascriptConversion::ToInteger(args[1], scriptContext);
2579+
int32 signedCount = TaggedInt::ToInt32(args[1]);
2580+
if (signedCount < 0)
2581+
{
2582+
JavascriptError::ThrowRangeError(scriptContext, JSERR_ArgumentOutOfRange, _u("String.prototype.repeat"));
2583+
}
2584+
count = (uint32) signedCount;
2585+
}
2586+
else if (!JavascriptOperators::IsUndefinedObject(args[1]))
2587+
{
2588+
double countDbl = JavascriptConversion::ToInteger_Full(args[1], scriptContext);
25802589
if (JavascriptNumber::IsPosInf(countDbl) || countDbl < 0.0)
25812590
{
25822591
JavascriptError::ThrowRangeError(scriptContext, JSERR_ArgumentOutOfRange, _u("String.prototype.repeat"));
@@ -2607,7 +2616,14 @@ namespace Js
26072616
const char16* currentRawString = currentString->GetString();
26082617
charcount_t currentLength = currentString->GetLength();
26092618

2610-
charcount_t finalBufferCount = UInt32Math::Add(UInt32Math::Mul(count, currentLength), 1);
2619+
charcount_t finalBufferCount = 0;
2620+
bool hasOverflow = UInt32Math::Mul(count, currentLength, &finalBufferCount);
2621+
if (hasOverflow || !IsValidCharCount(finalBufferCount))
2622+
{
2623+
JavascriptError::ThrowRangeError(scriptContext, JSERR_OutOfBoundString);
2624+
}
2625+
finalBufferCount = finalBufferCount + 1;
2626+
26112627
char16* buffer = RecyclerNewArrayLeaf(scriptContext->GetRecycler(), char16, finalBufferCount);
26122628

26132629
if (currentLength == 1)

test/es6/ES6StringAPIs.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
//-------------------------------------------------------------------------------------------------------
22
// Copyright (C) Microsoft. All rights reserved.
3+
// Copyright (c) 2021 ChakraCore Project Contributors. All rights reserved.
34
// Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
45
//-------------------------------------------------------------------------------------------------------
56

@@ -271,6 +272,7 @@ var tests = [
271272
assert.throws(function () { s.repeat(-1); }, RangeError, "negative repeat counts are out of range", "String.prototype.repeat: argument out of range");
272273
assert.throws(function () { s.repeat(-Infinity); }, RangeError, "negative infinite repeat count is out of range", "String.prototype.repeat: argument out of range");
273274
assert.throws(function () { s.repeat(Infinity); }, RangeError, "infinite repeat count is out of range", "String.prototype.repeat: argument out of range");
275+
assert.throws(function () { s.repeat(2 ** 30); }, RangeError, "lengths too large for a string throw");
274276

275277
assert.areEqual("\0\0\0\0", "\0".repeat(4), "null character embedded in string is repeated");
276278
assert.areEqual("a\0ba\0ba\0b", "a\0b".repeat(3), "null character embedded in string mixed with normal characters is repeated");

0 commit comments

Comments
 (0)