Skip to content

Commit 1e90fc4

Browse files
committed
[1.11>master] [1.10>1.11] [MERGE #5827 @pleath] November, 2018 Servicing Update
Merge pull request #5827 from pleath:servicing/1811 Addresses the following: CVE-2018-8541 CVE-2018-8542 CVE-2018-8543 CVE-2018-8551 CVE-2018-8555 CVE-2018-8556 CVE-2018-8557 CVE-2018-8588
2 parents 4b19999 + 7fd1686 commit 1e90fc4

19 files changed

+367
-213
lines changed

lib/Backend/GlobOpt.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13625,6 +13625,7 @@ GlobOpt::CheckJsArrayKills(IR::Instr *const instr)
1362513625
case IR::HelperArray_Shift:
1362613626
case IR::HelperArray_Splice:
1362713627
case IR::HelperArray_Unshift:
13628+
case IR::HelperArray_Concat:
1362813629
kills.SetKillsArrayHeadSegments();
1362913630
kills.SetKillsArrayHeadSegmentLengths();
1363013631
break;
@@ -13654,6 +13655,7 @@ GlobOpt::CheckJsArrayKills(IR::Instr *const instr)
1365413655
//case IR::HelperArray_Sort:
1365513656
case IR::HelperArray_Splice:
1365613657
case IR::HelperArray_Unshift:
13658+
case IR::HelperArray_Concat:
1365713659
kills.SetKillsNativeArrays();
1365813660
break;
1365913661
}

lib/Backend/GlobOptBailOut.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1324,7 +1324,7 @@ GlobOpt::MayNeedBailOnImplicitCall(IR::Instr const * instr, Value const * src1Va
13241324
return
13251325
!(
13261326
baseValueType.IsString() ||
1327-
(baseValueType.IsAnyArray() && baseValueType.GetObjectType() != ObjectType::ObjectWithArray) ||
1327+
baseValueType.IsArray() ||
13281328
(instr->HasBailOutInfo() && instr->GetBailOutKindNoBits() == IR::BailOutOnIrregularLength) // guarantees no implicit calls
13291329
);
13301330
}

lib/Backend/GlobOptExpr.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -844,6 +844,7 @@ GlobOpt::ProcessArrayValueKills(IR::Instr *instr)
844844
case IR::HelperArray_Shift:
845845
case IR::HelperArray_Unshift:
846846
case IR::HelperArray_Splice:
847+
case IR::HelperArray_Concat:
847848
this->currentBlock->globOptData.liveArrayValues->ClearAll();
848849
break;
849850
}

lib/Backend/GlobOptFields.cpp

Lines changed: 2 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1987,20 +1987,8 @@ GlobOpt::UpdateObjPtrValueType(IR::Opnd * opnd, IR::Instr * instr)
19871987
switch (typeId)
19881988
{
19891989
default:
1990-
if (typeId > Js::TypeIds_LastStaticType)
1991-
{
1992-
Assert(typeId != Js::TypeIds_Proxy);
1993-
if (objValueType.IsLikelyArrayOrObjectWithArray())
1994-
{
1995-
// If we have likely object with array before, we can't make it definite object with array
1996-
// since we have only proved that it is an object.
1997-
// Keep the likely array or object with array.
1998-
}
1999-
else
2000-
{
2001-
newValueType = ValueType::GetObject(ObjectType::Object);
2002-
}
2003-
}
1990+
// Can't mark as definite object because it may actually be object-with-array.
1991+
// Consider: a value type that subsumes object, array, and object-with-array.
20041992
break;
20051993
case Js::TypeIds_NativeIntArray:
20061994
case Js::TypeIds_NativeFloatArray:

lib/Backend/IRBuilder.cpp

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3798,7 +3798,7 @@ IRBuilder::BuildElementSlotI1(Js::OpCode newOpcode, uint32 offset, Js::RegSlot r
37983798
IR::Opnd*
37993799
IRBuilder::GetEnvironmentOperand(uint32 offset)
38003800
{
3801-
SymID symID;
3801+
StackSym* sym = nullptr;
38023802
// The byte code doesn't refer directly to a closure environment. Get the implicit one
38033803
// that's pointed to by the function body.
38043804
if (m_func->DoStackFrameDisplay() && m_func->GetLocalFrameDisplaySym())
@@ -3809,19 +3809,35 @@ IRBuilder::GetEnvironmentOperand(uint32 offset)
38093809
this->AddInstr(
38103810
IR::Instr::New(Js::OpCode::LdSlotArr, regOpnd, fieldOpnd, m_func),
38113811
offset);
3812-
symID = regOpnd->m_sym->m_id;
3812+
sym = regOpnd->m_sym;
38133813
}
38143814
else
38153815
{
3816+
SymID symID;
38163817
symID = this->GetEnvRegForInnerFrameDisplay();
38173818
Assert(symID != Js::Constants::NoRegister);
38183819
if (IsLoopBody() && !RegIsConstant(symID))
38193820
{
38203821
this->EnsureLoopBodyLoadSlot(symID);
38213822
}
3823+
3824+
if (m_func->DoStackNestedFunc() && symID == GetEnvReg())
3825+
{
3826+
// Environment is not guaranteed constant during this function because it could become boxed during execution,
3827+
// so load the environment every time you need it.
3828+
IR::RegOpnd *regOpnd = IR::RegOpnd::New(TyVar, m_func);
3829+
this->AddInstr(
3830+
IR::Instr::New(Js::OpCode::LdEnv, regOpnd, m_func),
3831+
offset);
3832+
sym = regOpnd->m_sym;
3833+
}
3834+
else
3835+
{
3836+
sym = StackSym::FindOrCreate(symID, (Js::RegSlot)symID, m_func);
3837+
}
38223838
}
38233839

3824-
return IR::RegOpnd::New(StackSym::FindOrCreate(symID, (Js::RegSlot)symID, m_func), TyVar, m_func);
3840+
return IR::RegOpnd::New(sym, TyVar, m_func);
38253841
}
38263842

38273843
template <typename SizePolicy>

lib/Backend/Inline.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5294,6 +5294,10 @@ Inline::MapFormals(Func *inlinee,
52945294
else
52955295
{
52965296
instr->SetSrc1(funcObjOpnd);
5297+
5298+
// This usage doesn't correspond with any byte code register, since interpreter stack frames
5299+
// get their function reference via this->function rather than from a register.
5300+
instr->GetSrc1()->SetIsJITOptimizedReg(true);
52975301
}
52985302
}
52995303
else

lib/Backend/Lower.cpp

Lines changed: 37 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -3757,22 +3757,6 @@ Lowerer::GenerateProfiledNewScArrayFastPath(IR::Instr *instr, Js::ArrayCallSiteI
37573757
IR::RegOpnd *headOpnd;
37583758
uint32 i = length;
37593759

3760-
auto fillMissingItems = [&](IRType type, uint missingItemCount, uint offsetStart, uint itemSpacing)
3761-
{
3762-
IR::Opnd * missingItemOpnd = GetMissingItemOpnd(type, func);
3763-
#if _M_ARM32_OR_ARM64
3764-
IR::Instr * move = this->InsertMove(IR::RegOpnd::New(type, instr->m_func), missingItemOpnd, instr);
3765-
missingItemOpnd = move->GetDst();
3766-
#endif
3767-
const IR::AutoReuseOpnd autoReuseHeadOpnd(headOpnd, func);
3768-
const IR::AutoReuseOpnd autoReuseMissingItemOpnd(missingItemOpnd, func);
3769-
3770-
for (; i < missingItemCount; i++)
3771-
{
3772-
GenerateMemInit(headOpnd, offsetStart + i * itemSpacing, missingItemOpnd, instr, isZeroed);
3773-
}
3774-
};
3775-
37763760
if (instr->GetDst() && instr->GetDst()->GetValueType().IsLikelyNativeIntArray())
37773761
{
37783762
if (!IsSmallObject<Js::JavascriptNativeIntArray>(length))
@@ -3782,10 +3766,14 @@ Lowerer::GenerateProfiledNewScArrayFastPath(IR::Instr *instr, Js::ArrayCallSiteI
37823766
GenerateArrayInfoIsNativeIntArrayTest(instr, arrayInfo, arrayInfoAddr, helperLabel);
37833767
Assert(Js::JavascriptNativeIntArray::GetOffsetOfArrayFlags() + sizeof(uint16) == Js::JavascriptNativeIntArray::GetOffsetOfArrayCallSiteIndex());
37843768
headOpnd = GenerateArrayLiteralsAlloc<Js::JavascriptNativeIntArray>(instr, &size, arrayInfo, &isZeroed);
3769+
const IR::AutoReuseOpnd autoReuseHeadOpnd(headOpnd, func);
37853770

37863771
GenerateMemInit(dstOpnd, Js::JavascriptNativeIntArray::GetOffsetOfWeakFuncRef(), IR::AddrOpnd::New(weakFuncRef, IR::AddrOpndKindDynamicFunctionBodyWeakRef, m_func), instr, isZeroed);
3787-
3788-
fillMissingItems(TyInt32, size, sizeof(Js::SparseArraySegmentBase), sizeof(int32));
3772+
for (; i < size; i++)
3773+
{
3774+
GenerateMemInit(headOpnd, sizeof(Js::SparseArraySegmentBase) + i * sizeof(int32),
3775+
Js::JavascriptNativeIntArray::MissingItem, instr, isZeroed);
3776+
}
37893777
}
37903778
else if (instr->GetDst() && instr->GetDst()->GetValueType().IsLikelyNativeFloatArray())
37913779
{
@@ -3796,24 +3784,35 @@ Lowerer::GenerateProfiledNewScArrayFastPath(IR::Instr *instr, Js::ArrayCallSiteI
37963784
GenerateArrayInfoIsNativeFloatAndNotIntArrayTest(instr, arrayInfo, arrayInfoAddr, helperLabel);
37973785
Assert(Js::JavascriptNativeFloatArray::GetOffsetOfArrayFlags() + sizeof(uint16) == Js::JavascriptNativeFloatArray::GetOffsetOfArrayCallSiteIndex());
37983786
headOpnd = GenerateArrayLiteralsAlloc<Js::JavascriptNativeFloatArray>(instr, &size, arrayInfo, &isZeroed);
3787+
const IR::AutoReuseOpnd autoReuseHeadOpnd(headOpnd, func);
37993788

38003789
GenerateMemInit(dstOpnd, Js::JavascriptNativeFloatArray::GetOffsetOfWeakFuncRef(), IR::AddrOpnd::New(weakFuncRef, IR::AddrOpndKindDynamicFunctionBodyWeakRef, m_func), instr, isZeroed);
3801-
3790+
// Js::JavascriptArray::MissingItem is a Var, so it may be 32-bit or 64 bit.
38023791
uint const offsetStart = sizeof(Js::SparseArraySegmentBase);
3803-
uint const missingItemCount = size * sizeof(double) / sizeof(Js::JavascriptArray::MissingItem);
3804-
i = i * sizeof(double) / sizeof(Js::JavascriptArray::MissingItem);
3805-
3806-
fillMissingItems(TyVar, missingItemCount, offsetStart, sizeof(Js::JavascriptArray::MissingItem));
3792+
for (; i < size; i++)
3793+
{
3794+
GenerateMemInit(
3795+
headOpnd, offsetStart + i * sizeof(double),
3796+
GetMissingItemOpndForAssignment(TyFloat64, m_func),
3797+
instr, isZeroed);
3798+
}
38073799
}
38083800
else
38093801
{
38103802
if (!IsSmallObject<Js::JavascriptArray>(length))
38113803
{
38123804
return false;
38133805
}
3814-
3806+
uint const offsetStart = sizeof(Js::SparseArraySegmentBase);
38153807
headOpnd = GenerateArrayLiteralsAlloc<Js::JavascriptArray>(instr, &size, arrayInfo, &isZeroed);
3816-
fillMissingItems(TyVar, size, sizeof(Js::SparseArraySegmentBase), sizeof(Js::Var));
3808+
const IR::AutoReuseOpnd autoReuseHeadOpnd(headOpnd, func);
3809+
for (; i < size; i++)
3810+
{
3811+
GenerateMemInit(
3812+
headOpnd, offsetStart + i * sizeof(Js::Var),
3813+
GetMissingItemOpndForAssignment(TyVar, m_func),
3814+
instr, isZeroed);
3815+
}
38173816
}
38183817

38193818
// Skip pass the helper call
@@ -4134,12 +4133,11 @@ Lowerer::GenerateProfiledNewScObjArrayFastPath(IR::Instr *instr, Js::ArrayCallSi
41344133

41354134
// Js::JavascriptArray::MissingItem is a Var, so it may be 32-bit or 64 bit.
41364135
uint const offsetStart = sizeof(Js::SparseArraySegmentBase);
4137-
uint const missingItemCount = size * sizeof(double) / sizeof(Js::JavascriptArray::MissingItem);
4138-
for (uint i = 0; i < missingItemCount; i++)
4136+
for (uint i = 0; i < size; i++)
41394137
{
41404138
GenerateMemInit(
4141-
headOpnd, offsetStart + i * sizeof(Js::JavascriptArray::MissingItem),
4142-
IR::AddrOpnd::New(Js::JavascriptArray::MissingItem, IR::AddrOpndKindConstantAddress, m_func, true),
4139+
headOpnd, offsetStart + i * sizeof(double),
4140+
GetMissingItemOpndForAssignment(TyFloat64, m_func),
41434141
instr, isZeroed);
41444142
}
41454143
}
@@ -4149,9 +4147,9 @@ Lowerer::GenerateProfiledNewScObjArrayFastPath(IR::Instr *instr, Js::ArrayCallSi
41494147
headOpnd = GenerateArrayObjectsAlloc<Js::JavascriptArray>(instr, &size, arrayInfo, &isZeroed, isNoArgs);
41504148
for (uint i = 0; i < size; i++)
41514149
{
4152-
GenerateMemInit(
4150+
GenerateMemInit(
41534151
headOpnd, offsetStart + i * sizeof(Js::Var),
4154-
IR::AddrOpnd::New(Js::JavascriptArray::MissingItem, IR::AddrOpndKindConstantAddress, m_func, true),
4152+
GetMissingItemOpndForAssignment(TyVar, m_func),
41554153
instr, isZeroed);
41564154
}
41574155
}
@@ -4182,8 +4180,8 @@ Lowerer::GenerateProfiledNewScObjArrayFastPath(IR::Instr *instr, Js::ArrayCallSi
41824180
uint allocationBucketsCount = ArrayType::AllocationBucketsCount;
41834181
uint(*allocationBuckets)[Js::JavascriptArray::AllocationBucketsInfoSize];
41844182
allocationBuckets = ArrayType::allocationBuckets;
4185-
uint sizeFactor = 1;
4186-
IRType missingItemType = (arrayInfo && arrayInfo->IsNativeIntArray()) ? IRType::TyInt32 : IRType::TyVar;
4183+
4184+
IRType missingItemType = (arrayInfo ? arrayInfo->IsNativeIntArray() ? IRType::TyInt32 : arrayInfo->IsNativeFloatArray() ? IRType::TyFloat64 : IRType::TyVar : IRType::TyVar);
41874185
IR::LabelInstr * arrayInitDone = IR::LabelInstr::New(Js::OpCode::Label, func);
41884186

41894187
bool isNativeArray = arrayInfo && (arrayInfo->IsNativeIntArray() || arrayInfo->IsNativeFloatArray());
@@ -4195,9 +4193,7 @@ Lowerer::GenerateProfiledNewScObjArrayFastPath(IR::Instr *instr, Js::ArrayCallSi
41954193
}
41964194
else if (arrayInfo && arrayInfo->IsNativeFloatArray())
41974195
{
4198-
// Js::JavascriptArray::MissingItem is a Var, so it may be 32-bit or 64 bit.
4199-
sizeFactor = sizeof(double) / sizeof(Js::JavascriptArray::MissingItem);
4200-
sizeOfElement = sizeof(Js::JavascriptArray::MissingItem);
4196+
sizeOfElement = sizeof(double);
42014197
GenerateArrayInfoIsNativeFloatAndNotIntArrayTest(instr, arrayInfo, arrayInfoAddr, helperLabel);
42024198
}
42034199
else
@@ -4227,7 +4223,7 @@ Lowerer::GenerateProfiledNewScObjArrayFastPath(IR::Instr *instr, Js::ArrayCallSi
42274223

42284224
for (uint8 i = 0;i < allocationBucketsCount;i++)
42294225
{
4230-
missingItemCount = allocationBuckets[i][Js::JavascriptArray::MissingElementsCountIndex] * sizeFactor;
4226+
missingItemCount = allocationBuckets[i][Js::JavascriptArray::MissingElementsCountIndex];
42314227

42324228
if (i > 0)
42334229
{
@@ -4258,7 +4254,7 @@ Lowerer::GenerateProfiledNewScObjArrayFastPath(IR::Instr *instr, Js::ArrayCallSi
42584254
// Ensure no. of missingItems written are same
42594255
Assert(missingItemIndex == missingItemInitializedSoFar);
42604256
// Ensure no. of missingItems match what present in allocationBuckets
4261-
Assert(missingItemIndex == allocationBuckets[allocationBucketsCount - 1][Js::JavascriptArray::MissingElementsCountIndex] * sizeFactor);
4257+
Assert(missingItemIndex == allocationBuckets[allocationBucketsCount - 1][Js::JavascriptArray::MissingElementsCountIndex]);
42624258

42634259
instr->InsertBefore(arrayInitDone);
42644260

@@ -4386,11 +4382,11 @@ Lowerer::GenerateProfiledNewScFloatArrayFastPath(IR::Instr *instr, Js::ArrayCall
43864382

43874383
// Js::JavascriptArray::MissingItem is a Var, so it may be 32-bit or 64 bit.
43884384
uint const offsetStart = sizeof(Js::SparseArraySegmentBase) + doubles->count * sizeof(double);
4389-
uint const missingItem = (size - doubles->count) * sizeof(double) / sizeof(Js::JavascriptArray::MissingItem);
4385+
uint const missingItem = (size - doubles->count);
43904386
for (uint i = 0; i < missingItem; i++)
43914387
{
4392-
GenerateMemInit(headOpnd, offsetStart + i * sizeof(Js::JavascriptArray::MissingItem),
4393-
IR::AddrOpnd::New(Js::JavascriptArray::MissingItem, IR::AddrOpndKindConstantAddress, m_func, true), instr, isHeadSegmentZeroed);
4388+
GenerateMemInit(headOpnd, offsetStart + i * sizeof(double),
4389+
GetMissingItemOpndForAssignment(TyFloat64, m_func), instr, isHeadSegmentZeroed);
43944390
}
43954391
// Skip pass the helper call
43964392
IR::LabelInstr * doneLabel = IR::LabelInstr::New(Js::OpCode::Label, func);

lib/Parser/Scan.cpp

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -193,20 +193,30 @@ void Scanner<EncodingPolicy>::PrepareForBackgroundParse(Js::ScriptContext *scrip
193193
// This is used to determine a length of BSTR, which can't contain a NUL character.
194194
//-----------------------------------------------------------------------------
195195
template <typename EncodingPolicy>
196-
charcount_t Scanner<EncodingPolicy>::LineLength(EncodedCharPtr first, EncodedCharPtr last)
196+
charcount_t Scanner<EncodingPolicy>::LineLength(EncodedCharPtr first, EncodedCharPtr last, size_t* cb)
197197
{
198+
Assert(cb != nullptr);
199+
198200
charcount_t result = 0;
199201
EncodedCharPtr p = first;
200202

201203
for (;;)
202204
{
205+
EncodedCharPtr prev = p;
203206
switch( this->template ReadFull<false>(p, last) )
204207
{
205208
case kchNWL: // _C_NWL
206209
case kchRET:
207210
case kchLS:
208211
case kchPS:
209212
case kchNUL: // _C_NUL
213+
// p is now advanced past the line terminator character.
214+
// We need to know the number of bytes making up the line, not including the line terminator character.
215+
// To avoid subtracting a variable number of bytes because the line terminator characters are different
216+
// number of bytes long (plus there may be multiple valid encodings for these characters) just keep
217+
// track of the first byte of the line terminator character in prev.
218+
Assert(prev >= first);
219+
*cb = prev - first;
210220
return result;
211221
}
212222
result++;
@@ -2331,10 +2341,11 @@ HRESULT Scanner<EncodingPolicy>::SysAllocErrorLine(int32 ichMinLine, __out BSTR*
23312341
typename EncodingPolicy::EncodedCharPtr pStart = static_cast<size_t>(ichMinLine) == IchMinLine() ? m_pchMinLine : m_pchBase + this->CharacterOffsetToUnitOffset(m_pchBase, m_currentCharacter, m_pchLast, ichMinLine);
23322342

23332343
// Determine the length by scanning for the next newline
2334-
charcount_t cch = LineLength(pStart, m_pchLast);
2344+
size_t cb = 0;
2345+
charcount_t cch = LineLength(pStart, m_pchLast, &cb);
23352346
Assert(cch <= LONG_MAX);
23362347

2337-
typename EncodingPolicy::EncodedCharPtr pEnd = static_cast<size_t>(ichMinLine) == IchMinLine() ? m_pchMinLine + cch : m_pchBase + this->CharacterOffsetToUnitOffset(m_pchBase, m_currentCharacter, m_pchLast, cch);
2348+
typename EncodingPolicy::EncodedCharPtr pEnd = static_cast<size_t>(ichMinLine) == IchMinLine() ? m_pchMinLine + cb : m_pchBase + this->CharacterOffsetToUnitOffset(m_pchBase, m_currentCharacter, m_pchLast, cch);
23382349

23392350
*pbstrLine = SysAllocStringLen(NULL, cch);
23402351
if (!*pbstrLine)

lib/Parser/Scan.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -793,7 +793,7 @@ class Scanner : public IScanner, public EncodingPolicy
793793

794794
void ScanNewLine(uint ch);
795795
void NotifyScannedNewLine();
796-
charcount_t LineLength(EncodedCharPtr first, EncodedCharPtr last);
796+
charcount_t LineLength(EncodedCharPtr first, EncodedCharPtr last, size_t* cb);
797797

798798
tokens ScanIdentifier(bool identifyKwds, EncodedCharPtr *pp);
799799
BOOL FastIdentifierContinue(EncodedCharPtr&p, EncodedCharPtr last);

lib/Runtime/Language/InterpreterStackFrame.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6793,6 +6793,12 @@ namespace Js
67936793
// Finally exited with LeaveNull, We don't throw for early returns
67946794
if (finallyEndOffset == 0 && exceptionObj)
67956795
{
6796+
#if ENABLE_NATIVE_CODEGEN
6797+
if (scriptContext->GetThreadContext()->GetTryHandlerAddrOfReturnAddr() != nullptr)
6798+
{
6799+
JavascriptExceptionOperators::WalkStackForCleaningUpInlineeInfo(scriptContext, nullptr, scriptContext->GetThreadContext()->GetTryHandlerAddrOfReturnAddr());
6800+
}
6801+
#endif
67966802
JavascriptExceptionOperators::DoThrow(const_cast<Js::JavascriptExceptionObject *>(exceptionObj), scriptContext);
67976803
}
67986804
if (finallyEndOffset != 0)

0 commit comments

Comments
 (0)