Skip to content

Commit abb5d88

Browse files
committed
[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 f139911 + 0b6dc52 commit abb5d88

19 files changed

+347
-194
lines changed

lib/Backend/GlobOpt.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13375,6 +13375,7 @@ GlobOpt::CheckJsArrayKills(IR::Instr *const instr)
1337513375
case IR::HelperArray_Shift:
1337613376
case IR::HelperArray_Splice:
1337713377
case IR::HelperArray_Unshift:
13378+
case IR::HelperArray_Concat:
1337813379
kills.SetKillsArrayHeadSegments();
1337913380
kills.SetKillsArrayHeadSegmentLengths();
1338013381
break;
@@ -13404,6 +13405,7 @@ GlobOpt::CheckJsArrayKills(IR::Instr *const instr)
1340413405
//case IR::HelperArray_Sort:
1340513406
case IR::HelperArray_Splice:
1340613407
case IR::HelperArray_Unshift:
13408+
case IR::HelperArray_Concat:
1340713409
kills.SetKillsNativeArrays();
1340813410
break;
1340913411
}

lib/Backend/GlobOptBailOut.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1306,7 +1306,7 @@ GlobOpt::MayNeedBailOnImplicitCall(IR::Instr const * instr, Value const * src1Va
13061306
return
13071307
!(
13081308
baseValueType.IsString() ||
1309-
(baseValueType.IsAnyArray() && baseValueType.GetObjectType() != ObjectType::ObjectWithArray) ||
1309+
baseValueType.IsArray() ||
13101310
(instr->HasBailOutInfo() && instr->GetBailOutKindNoBits() == IR::BailOutOnIrregularLength) // guarantees no implicit calls
13111311
);
13121312
}

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
@@ -1900,20 +1900,8 @@ GlobOpt::UpdateObjPtrValueType(IR::Opnd * opnd, IR::Instr * instr)
19001900
switch (typeId)
19011901
{
19021902
default:
1903-
if (typeId > Js::TypeIds_LastStaticType)
1904-
{
1905-
Assert(typeId != Js::TypeIds_Proxy);
1906-
if (objValueType.IsLikelyArrayOrObjectWithArray())
1907-
{
1908-
// If we have likely object with array before, we can't make it definite object with array
1909-
// since we have only proved that it is an object.
1910-
// Keep the likely array or object with array.
1911-
}
1912-
else
1913-
{
1914-
newValueType = ValueType::GetObject(ObjectType::Object);
1915-
}
1916-
}
1903+
// Can't mark as definite object because it may actually be object-with-array.
1904+
// Consider: a value type that subsumes object, array, and object-with-array.
19171905
break;
19181906
case Js::TypeIds_NativeIntArray:
19191907
case Js::TypeIds_NativeFloatArray:

lib/Backend/IRBuilder.cpp

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3749,7 +3749,7 @@ IRBuilder::BuildElementSlotI1(Js::OpCode newOpcode, uint32 offset, Js::RegSlot r
37493749
IR::Opnd*
37503750
IRBuilder::GetEnvironmentOperand(uint32 offset)
37513751
{
3752-
SymID symID;
3752+
StackSym* sym = nullptr;
37533753
// The byte code doesn't refer directly to a closure environment. Get the implicit one
37543754
// that's pointed to by the function body.
37553755
if (m_func->DoStackFrameDisplay() && m_func->GetLocalFrameDisplaySym())
@@ -3760,19 +3760,35 @@ IRBuilder::GetEnvironmentOperand(uint32 offset)
37603760
this->AddInstr(
37613761
IR::Instr::New(Js::OpCode::LdSlotArr, regOpnd, fieldOpnd, m_func),
37623762
offset);
3763-
symID = regOpnd->m_sym->m_id;
3763+
sym = regOpnd->m_sym;
37643764
}
37653765
else
37663766
{
3767+
SymID symID;
37673768
symID = this->GetEnvRegForInnerFrameDisplay();
37683769
Assert(symID != Js::Constants::NoRegister);
37693770
if (IsLoopBody() && !RegIsConstant(symID))
37703771
{
37713772
this->EnsureLoopBodyLoadSlot(symID);
37723773
}
3774+
3775+
if (m_func->DoStackNestedFunc() && symID == GetEnvReg())
3776+
{
3777+
// Environment is not guaranteed constant during this function because it could become boxed during execution,
3778+
// so load the environment every time you need it.
3779+
IR::RegOpnd *regOpnd = IR::RegOpnd::New(TyVar, m_func);
3780+
this->AddInstr(
3781+
IR::Instr::New(Js::OpCode::LdEnv, regOpnd, m_func),
3782+
offset);
3783+
sym = regOpnd->m_sym;
3784+
}
3785+
else
3786+
{
3787+
sym = StackSym::FindOrCreate(symID, (Js::RegSlot)symID, m_func);
3788+
}
37733789
}
37743790

3775-
return IR::RegOpnd::New(StackSym::FindOrCreate(symID, (Js::RegSlot)symID, m_func), TyVar, m_func);
3791+
return IR::RegOpnd::New(sym, TyVar, m_func);
37763792
}
37773793

37783794
template <typename SizePolicy>

lib/Backend/Inline.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5146,6 +5146,10 @@ Inline::MapFormals(Func *inlinee,
51465146
else
51475147
{
51485148
instr->SetSrc1(funcObjOpnd);
5149+
5150+
// This usage doesn't correspond with any byte code register, since interpreter stack frames
5151+
// get their function reference via this->function rather than from a register.
5152+
instr->GetSrc1()->SetIsJITOptimizedReg(true);
51495153
}
51505154
}
51515155
else

lib/Backend/Lower.cpp

Lines changed: 17 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -3765,13 +3765,11 @@ Lowerer::GenerateProfiledNewScArrayFastPath(IR::Instr *instr, Js::ArrayCallSiteI
37653765
GenerateMemInit(dstOpnd, Js::JavascriptNativeFloatArray::GetOffsetOfWeakFuncRef(), IR::AddrOpnd::New(weakFuncRef, IR::AddrOpndKindDynamicFunctionBodyWeakRef, m_func), instr, isZeroed);
37663766
// Js::JavascriptArray::MissingItem is a Var, so it may be 32-bit or 64 bit.
37673767
uint const offsetStart = sizeof(Js::SparseArraySegmentBase);
3768-
uint const missingItemCount = size * sizeof(double) / sizeof(Js::JavascriptArray::MissingItem);
3769-
i = i * sizeof(double) / sizeof(Js::JavascriptArray::MissingItem);
3770-
for (; i < missingItemCount; i++)
3768+
for (; i < size; i++)
37713769
{
37723770
GenerateMemInit(
3773-
headOpnd, offsetStart + i * sizeof(Js::JavascriptArray::MissingItem),
3774-
IR::AddrOpnd::New(Js::JavascriptArray::MissingItem, IR::AddrOpndKindConstantAddress, m_func, true),
3771+
headOpnd, offsetStart + i * sizeof(double),
3772+
GetMissingItemOpndForAssignment(TyFloat64, m_func),
37753773
instr, isZeroed);
37763774
}
37773775
}
@@ -3788,7 +3786,7 @@ Lowerer::GenerateProfiledNewScArrayFastPath(IR::Instr *instr, Js::ArrayCallSiteI
37883786
{
37893787
GenerateMemInit(
37903788
headOpnd, offsetStart + i * sizeof(Js::Var),
3791-
IR::AddrOpnd::New(Js::JavascriptArray::MissingItem, IR::AddrOpndKindConstantAddress, m_func, true),
3789+
GetMissingItemOpndForAssignment(TyVar, m_func),
37923790
instr, isZeroed);
37933791
}
37943792
}
@@ -4111,12 +4109,11 @@ Lowerer::GenerateProfiledNewScObjArrayFastPath(IR::Instr *instr, Js::ArrayCallSi
41114109

41124110
// Js::JavascriptArray::MissingItem is a Var, so it may be 32-bit or 64 bit.
41134111
uint const offsetStart = sizeof(Js::SparseArraySegmentBase);
4114-
uint const missingItemCount = size * sizeof(double) / sizeof(Js::JavascriptArray::MissingItem);
4115-
for (uint i = 0; i < missingItemCount; i++)
4112+
for (uint i = 0; i < size; i++)
41164113
{
41174114
GenerateMemInit(
4118-
headOpnd, offsetStart + i * sizeof(Js::JavascriptArray::MissingItem),
4119-
IR::AddrOpnd::New(Js::JavascriptArray::MissingItem, IR::AddrOpndKindConstantAddress, m_func, true),
4115+
headOpnd, offsetStart + i * sizeof(double),
4116+
GetMissingItemOpndForAssignment(TyFloat64, m_func),
41204117
instr, isZeroed);
41214118
}
41224119
}
@@ -4126,9 +4123,9 @@ Lowerer::GenerateProfiledNewScObjArrayFastPath(IR::Instr *instr, Js::ArrayCallSi
41264123
headOpnd = GenerateArrayObjectsAlloc<Js::JavascriptArray>(instr, &size, arrayInfo, &isZeroed, isNoArgs);
41274124
for (uint i = 0; i < size; i++)
41284125
{
4129-
GenerateMemInit(
4126+
GenerateMemInit(
41304127
headOpnd, offsetStart + i * sizeof(Js::Var),
4131-
IR::AddrOpnd::New(Js::JavascriptArray::MissingItem, IR::AddrOpndKindConstantAddress, m_func, true),
4128+
GetMissingItemOpndForAssignment(TyVar, m_func),
41324129
instr, isZeroed);
41334130
}
41344131
}
@@ -4159,8 +4156,8 @@ Lowerer::GenerateProfiledNewScObjArrayFastPath(IR::Instr *instr, Js::ArrayCallSi
41594156
uint allocationBucketsCount = ArrayType::AllocationBucketsCount;
41604157
uint(*allocationBuckets)[Js::JavascriptArray::AllocationBucketsInfoSize];
41614158
allocationBuckets = ArrayType::allocationBuckets;
4162-
uint sizeFactor = 1;
4163-
IRType missingItemType = (arrayInfo && arrayInfo->IsNativeIntArray()) ? IRType::TyInt32 : IRType::TyVar;
4159+
4160+
IRType missingItemType = (arrayInfo ? arrayInfo->IsNativeIntArray() ? IRType::TyInt32 : arrayInfo->IsNativeFloatArray() ? IRType::TyFloat64 : IRType::TyVar : IRType::TyVar);
41644161
IR::LabelInstr * arrayInitDone = IR::LabelInstr::New(Js::OpCode::Label, func);
41654162

41664163
bool isNativeArray = arrayInfo && (arrayInfo->IsNativeIntArray() || arrayInfo->IsNativeFloatArray());
@@ -4172,9 +4169,7 @@ Lowerer::GenerateProfiledNewScObjArrayFastPath(IR::Instr *instr, Js::ArrayCallSi
41724169
}
41734170
else if (arrayInfo && arrayInfo->IsNativeFloatArray())
41744171
{
4175-
// Js::JavascriptArray::MissingItem is a Var, so it may be 32-bit or 64 bit.
4176-
sizeFactor = sizeof(double) / sizeof(Js::JavascriptArray::MissingItem);
4177-
sizeOfElement = sizeof(Js::JavascriptArray::MissingItem);
4172+
sizeOfElement = sizeof(double);
41784173
GenerateArrayInfoIsNativeFloatAndNotIntArrayTest(instr, arrayInfo, arrayInfoAddr, helperLabel);
41794174
}
41804175
else
@@ -4204,7 +4199,7 @@ Lowerer::GenerateProfiledNewScObjArrayFastPath(IR::Instr *instr, Js::ArrayCallSi
42044199

42054200
for (uint8 i = 0;i < allocationBucketsCount;i++)
42064201
{
4207-
missingItemCount = allocationBuckets[i][Js::JavascriptArray::MissingElementsCountIndex] * sizeFactor;
4202+
missingItemCount = allocationBuckets[i][Js::JavascriptArray::MissingElementsCountIndex];
42084203

42094204
if (i > 0)
42104205
{
@@ -4235,7 +4230,7 @@ Lowerer::GenerateProfiledNewScObjArrayFastPath(IR::Instr *instr, Js::ArrayCallSi
42354230
// Ensure no. of missingItems written are same
42364231
Assert(missingItemIndex == missingItemInitializedSoFar);
42374232
// Ensure no. of missingItems match what present in allocationBuckets
4238-
Assert(missingItemIndex == allocationBuckets[allocationBucketsCount - 1][Js::JavascriptArray::MissingElementsCountIndex] * sizeFactor);
4233+
Assert(missingItemIndex == allocationBuckets[allocationBucketsCount - 1][Js::JavascriptArray::MissingElementsCountIndex]);
42394234

42404235
instr->InsertBefore(arrayInitDone);
42414236

@@ -4363,11 +4358,11 @@ Lowerer::GenerateProfiledNewScFloatArrayFastPath(IR::Instr *instr, Js::ArrayCall
43634358

43644359
// Js::JavascriptArray::MissingItem is a Var, so it may be 32-bit or 64 bit.
43654360
uint const offsetStart = sizeof(Js::SparseArraySegmentBase) + doubles->count * sizeof(double);
4366-
uint const missingItem = (size - doubles->count) * sizeof(double) / sizeof(Js::JavascriptArray::MissingItem);
4361+
uint const missingItem = (size - doubles->count);
43674362
for (uint i = 0; i < missingItem; i++)
43684363
{
4369-
GenerateMemInit(headOpnd, offsetStart + i * sizeof(Js::JavascriptArray::MissingItem),
4370-
IR::AddrOpnd::New(Js::JavascriptArray::MissingItem, IR::AddrOpndKindConstantAddress, m_func, true), instr, isHeadSegmentZeroed);
4364+
GenerateMemInit(headOpnd, offsetStart + i * sizeof(double),
4365+
GetMissingItemOpndForAssignment(TyFloat64, m_func), instr, isHeadSegmentZeroed);
43714366
}
43724367
// Skip pass the helper call
43734368
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++;
@@ -2313,10 +2323,11 @@ HRESULT Scanner<EncodingPolicy>::SysAllocErrorLine(int32 ichMinLine, __out BSTR*
23132323
typename EncodingPolicy::EncodedCharPtr pStart = static_cast<size_t>(ichMinLine) == IchMinLine() ? m_pchMinLine : m_pchBase + this->CharacterOffsetToUnitOffset(m_pchBase, m_currentCharacter, m_pchLast, ichMinLine);
23142324

23152325
// Determine the length by scanning for the next newline
2316-
charcount_t cch = LineLength(pStart, m_pchLast);
2326+
size_t cb = 0;
2327+
charcount_t cch = LineLength(pStart, m_pchLast, &cb);
23172328
Assert(cch <= LONG_MAX);
23182329

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

23212332
*pbstrLine = SysAllocStringLen(NULL, cch);
23222333
if (!*pbstrLine)

lib/Parser/Scan.h

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

781781
void ScanNewLine(uint ch);
782782
void NotifyScannedNewLine();
783-
charcount_t LineLength(EncodedCharPtr first, EncodedCharPtr last);
783+
charcount_t LineLength(EncodedCharPtr first, EncodedCharPtr last, size_t* cb);
784784

785785
tokens ScanIdentifier(bool identifyKwds, EncodedCharPtr *pp);
786786
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
@@ -6727,6 +6727,12 @@ namespace Js
67276727
// Finally exited with LeaveNull, We don't throw for early returns
67286728
if (finallyEndOffset == 0 && exceptionObj)
67296729
{
6730+
#if ENABLE_NATIVE_CODEGEN
6731+
if (scriptContext->GetThreadContext()->GetTryHandlerAddrOfReturnAddr() != nullptr)
6732+
{
6733+
JavascriptExceptionOperators::WalkStackForCleaningUpInlineeInfo(scriptContext, nullptr, scriptContext->GetThreadContext()->GetTryHandlerAddrOfReturnAddr());
6734+
}
6735+
#endif
67306736
JavascriptExceptionOperators::DoThrow(const_cast<Js::JavascriptExceptionObject *>(exceptionObj), scriptContext);
67316737
}
67326738
if (finallyEndOffset != 0)

0 commit comments

Comments
 (0)