Skip to content

Commit 5af1a81

Browse files
committed
[1.6>1.7] [MERGE #3425 @Cellule] Fix possible infinite loop in String.raw()
Merge pull request #3425 from Cellule:raw I was able to construct a use case where we would end up in an infinite loop. It takes forever to run to just overflow the uint32, but I figured we should at least avoid possible infinite loops. A possible solution could be to just cap the length to loop through to UINT32_MAX, but it would be technically not spec compliant.
2 parents 10d2f11 + 4a8dae8 commit 5af1a81

File tree

1 file changed

+19
-10
lines changed

1 file changed

+19
-10
lines changed

lib/Runtime/Library/JavascriptString.cpp

Lines changed: 19 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1565,22 +1565,31 @@ namespace Js
15651565
// strcon2 /
15661566
// expr2 \__ step 3
15671567
// strcon3 /
1568-
for (uint32 i = 1; i < length; ++i)
1568+
const auto append = [&] (Var var)
15691569
{
1570-
// First append the next substitution expression
1571-
// If we have an arg at [i+1] use that one, otherwise empty string (which is nop)
1572-
if (i+1 < args.Info.Count)
1573-
{
1574-
string = JavascriptConversion::ToString(args[i+1], scriptContext);
1575-
1570+
JavascriptString* string = JavascriptConversion::ToString(var, scriptContext);
15761571
stringBuilder.Append(string);
1572+
};
1573+
uint32 loopMax = length >= UINT_MAX ? UINT_MAX-1 : (uint32)length;
1574+
uint32 i = 1;
1575+
uint32 argsCount = args.Info.Count;
1576+
for (; i < loopMax; ++i)
1577+
{
1578+
// First append the next substitution expression if available
1579+
if (i + 1 < argsCount)
1580+
{
1581+
append(args[i + 1]);
15771582
}
15781583

15791584
// Then append the next string (this will also cover the final string case)
1580-
var = JavascriptOperators::OP_GetElementI_UInt32(raw, i, scriptContext);
1581-
string = JavascriptConversion::ToString(var, scriptContext);
1585+
append(JavascriptOperators::OP_GetElementI_UInt32(raw, i, scriptContext));
1586+
}
15821587

1583-
stringBuilder.Append(string);
1588+
// Length can be greater than uint32 max (unlikely in practice)
1589+
for (int64 j = (int64)i; j < length; ++j)
1590+
{
1591+
// Append whatever is left in the array/object
1592+
append(JavascriptOperators::OP_GetElementI(raw, JavascriptNumber::ToVar(j, scriptContext), scriptContext));
15841593
}
15851594

15861595
// CompoundString::Builder has saved our lives

0 commit comments

Comments
 (0)