Skip to content

Commit

Permalink
[1.11>master] [1.10>1.11] [MERGE #5827 @pleath] November, 2018 Servic…
Browse files Browse the repository at this point in the history
…ing 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
  • Loading branch information
pleath committed Nov 13, 2018
2 parents 4b19999 + 7fd1686 commit 1e90fc4
Show file tree
Hide file tree
Showing 19 changed files with 367 additions and 213 deletions.
2 changes: 2 additions & 0 deletions lib/Backend/GlobOpt.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13625,6 +13625,7 @@ GlobOpt::CheckJsArrayKills(IR::Instr *const instr)
case IR::HelperArray_Shift:
case IR::HelperArray_Splice:
case IR::HelperArray_Unshift:
case IR::HelperArray_Concat:
kills.SetKillsArrayHeadSegments();
kills.SetKillsArrayHeadSegmentLengths();
break;
Expand Down Expand Up @@ -13654,6 +13655,7 @@ GlobOpt::CheckJsArrayKills(IR::Instr *const instr)
//case IR::HelperArray_Sort:
case IR::HelperArray_Splice:
case IR::HelperArray_Unshift:
case IR::HelperArray_Concat:
kills.SetKillsNativeArrays();
break;
}
Expand Down
2 changes: 1 addition & 1 deletion lib/Backend/GlobOptBailOut.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1324,7 +1324,7 @@ GlobOpt::MayNeedBailOnImplicitCall(IR::Instr const * instr, Value const * src1Va
return
!(
baseValueType.IsString() ||
(baseValueType.IsAnyArray() && baseValueType.GetObjectType() != ObjectType::ObjectWithArray) ||
baseValueType.IsArray() ||
(instr->HasBailOutInfo() && instr->GetBailOutKindNoBits() == IR::BailOutOnIrregularLength) // guarantees no implicit calls
);
}
Expand Down
1 change: 1 addition & 0 deletions lib/Backend/GlobOptExpr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -844,6 +844,7 @@ GlobOpt::ProcessArrayValueKills(IR::Instr *instr)
case IR::HelperArray_Shift:
case IR::HelperArray_Unshift:
case IR::HelperArray_Splice:
case IR::HelperArray_Concat:
this->currentBlock->globOptData.liveArrayValues->ClearAll();
break;
}
Expand Down
16 changes: 2 additions & 14 deletions lib/Backend/GlobOptFields.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1987,20 +1987,8 @@ GlobOpt::UpdateObjPtrValueType(IR::Opnd * opnd, IR::Instr * instr)
switch (typeId)
{
default:
if (typeId > Js::TypeIds_LastStaticType)
{
Assert(typeId != Js::TypeIds_Proxy);
if (objValueType.IsLikelyArrayOrObjectWithArray())
{
// If we have likely object with array before, we can't make it definite object with array
// since we have only proved that it is an object.
// Keep the likely array or object with array.
}
else
{
newValueType = ValueType::GetObject(ObjectType::Object);
}
}
// Can't mark as definite object because it may actually be object-with-array.
// Consider: a value type that subsumes object, array, and object-with-array.
break;
case Js::TypeIds_NativeIntArray:
case Js::TypeIds_NativeFloatArray:
Expand Down
22 changes: 19 additions & 3 deletions lib/Backend/IRBuilder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3798,7 +3798,7 @@ IRBuilder::BuildElementSlotI1(Js::OpCode newOpcode, uint32 offset, Js::RegSlot r
IR::Opnd*
IRBuilder::GetEnvironmentOperand(uint32 offset)
{
SymID symID;
StackSym* sym = nullptr;
// The byte code doesn't refer directly to a closure environment. Get the implicit one
// that's pointed to by the function body.
if (m_func->DoStackFrameDisplay() && m_func->GetLocalFrameDisplaySym())
Expand All @@ -3809,19 +3809,35 @@ IRBuilder::GetEnvironmentOperand(uint32 offset)
this->AddInstr(
IR::Instr::New(Js::OpCode::LdSlotArr, regOpnd, fieldOpnd, m_func),
offset);
symID = regOpnd->m_sym->m_id;
sym = regOpnd->m_sym;
}
else
{
SymID symID;
symID = this->GetEnvRegForInnerFrameDisplay();
Assert(symID != Js::Constants::NoRegister);
if (IsLoopBody() && !RegIsConstant(symID))
{
this->EnsureLoopBodyLoadSlot(symID);
}

if (m_func->DoStackNestedFunc() && symID == GetEnvReg())
{
// Environment is not guaranteed constant during this function because it could become boxed during execution,
// so load the environment every time you need it.
IR::RegOpnd *regOpnd = IR::RegOpnd::New(TyVar, m_func);
this->AddInstr(
IR::Instr::New(Js::OpCode::LdEnv, regOpnd, m_func),
offset);
sym = regOpnd->m_sym;
}
else
{
sym = StackSym::FindOrCreate(symID, (Js::RegSlot)symID, m_func);
}
}

return IR::RegOpnd::New(StackSym::FindOrCreate(symID, (Js::RegSlot)symID, m_func), TyVar, m_func);
return IR::RegOpnd::New(sym, TyVar, m_func);
}

template <typename SizePolicy>
Expand Down
4 changes: 4 additions & 0 deletions lib/Backend/Inline.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5294,6 +5294,10 @@ Inline::MapFormals(Func *inlinee,
else
{
instr->SetSrc1(funcObjOpnd);

// This usage doesn't correspond with any byte code register, since interpreter stack frames
// get their function reference via this->function rather than from a register.
instr->GetSrc1()->SetIsJITOptimizedReg(true);
}
}
else
Expand Down
78 changes: 37 additions & 41 deletions lib/Backend/Lower.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3757,22 +3757,6 @@ Lowerer::GenerateProfiledNewScArrayFastPath(IR::Instr *instr, Js::ArrayCallSiteI
IR::RegOpnd *headOpnd;
uint32 i = length;

auto fillMissingItems = [&](IRType type, uint missingItemCount, uint offsetStart, uint itemSpacing)
{
IR::Opnd * missingItemOpnd = GetMissingItemOpnd(type, func);
#if _M_ARM32_OR_ARM64
IR::Instr * move = this->InsertMove(IR::RegOpnd::New(type, instr->m_func), missingItemOpnd, instr);
missingItemOpnd = move->GetDst();
#endif
const IR::AutoReuseOpnd autoReuseHeadOpnd(headOpnd, func);
const IR::AutoReuseOpnd autoReuseMissingItemOpnd(missingItemOpnd, func);

for (; i < missingItemCount; i++)
{
GenerateMemInit(headOpnd, offsetStart + i * itemSpacing, missingItemOpnd, instr, isZeroed);
}
};

if (instr->GetDst() && instr->GetDst()->GetValueType().IsLikelyNativeIntArray())
{
if (!IsSmallObject<Js::JavascriptNativeIntArray>(length))
Expand All @@ -3782,10 +3766,14 @@ Lowerer::GenerateProfiledNewScArrayFastPath(IR::Instr *instr, Js::ArrayCallSiteI
GenerateArrayInfoIsNativeIntArrayTest(instr, arrayInfo, arrayInfoAddr, helperLabel);
Assert(Js::JavascriptNativeIntArray::GetOffsetOfArrayFlags() + sizeof(uint16) == Js::JavascriptNativeIntArray::GetOffsetOfArrayCallSiteIndex());
headOpnd = GenerateArrayLiteralsAlloc<Js::JavascriptNativeIntArray>(instr, &size, arrayInfo, &isZeroed);
const IR::AutoReuseOpnd autoReuseHeadOpnd(headOpnd, func);

GenerateMemInit(dstOpnd, Js::JavascriptNativeIntArray::GetOffsetOfWeakFuncRef(), IR::AddrOpnd::New(weakFuncRef, IR::AddrOpndKindDynamicFunctionBodyWeakRef, m_func), instr, isZeroed);

fillMissingItems(TyInt32, size, sizeof(Js::SparseArraySegmentBase), sizeof(int32));
for (; i < size; i++)
{
GenerateMemInit(headOpnd, sizeof(Js::SparseArraySegmentBase) + i * sizeof(int32),
Js::JavascriptNativeIntArray::MissingItem, instr, isZeroed);
}
}
else if (instr->GetDst() && instr->GetDst()->GetValueType().IsLikelyNativeFloatArray())
{
Expand All @@ -3796,24 +3784,35 @@ Lowerer::GenerateProfiledNewScArrayFastPath(IR::Instr *instr, Js::ArrayCallSiteI
GenerateArrayInfoIsNativeFloatAndNotIntArrayTest(instr, arrayInfo, arrayInfoAddr, helperLabel);
Assert(Js::JavascriptNativeFloatArray::GetOffsetOfArrayFlags() + sizeof(uint16) == Js::JavascriptNativeFloatArray::GetOffsetOfArrayCallSiteIndex());
headOpnd = GenerateArrayLiteralsAlloc<Js::JavascriptNativeFloatArray>(instr, &size, arrayInfo, &isZeroed);
const IR::AutoReuseOpnd autoReuseHeadOpnd(headOpnd, func);

GenerateMemInit(dstOpnd, Js::JavascriptNativeFloatArray::GetOffsetOfWeakFuncRef(), IR::AddrOpnd::New(weakFuncRef, IR::AddrOpndKindDynamicFunctionBodyWeakRef, m_func), instr, isZeroed);

// Js::JavascriptArray::MissingItem is a Var, so it may be 32-bit or 64 bit.
uint const offsetStart = sizeof(Js::SparseArraySegmentBase);
uint const missingItemCount = size * sizeof(double) / sizeof(Js::JavascriptArray::MissingItem);
i = i * sizeof(double) / sizeof(Js::JavascriptArray::MissingItem);

fillMissingItems(TyVar, missingItemCount, offsetStart, sizeof(Js::JavascriptArray::MissingItem));
for (; i < size; i++)
{
GenerateMemInit(
headOpnd, offsetStart + i * sizeof(double),
GetMissingItemOpndForAssignment(TyFloat64, m_func),
instr, isZeroed);
}
}
else
{
if (!IsSmallObject<Js::JavascriptArray>(length))
{
return false;
}

uint const offsetStart = sizeof(Js::SparseArraySegmentBase);
headOpnd = GenerateArrayLiteralsAlloc<Js::JavascriptArray>(instr, &size, arrayInfo, &isZeroed);
fillMissingItems(TyVar, size, sizeof(Js::SparseArraySegmentBase), sizeof(Js::Var));
const IR::AutoReuseOpnd autoReuseHeadOpnd(headOpnd, func);
for (; i < size; i++)
{
GenerateMemInit(
headOpnd, offsetStart + i * sizeof(Js::Var),
GetMissingItemOpndForAssignment(TyVar, m_func),
instr, isZeroed);
}
}

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

// Js::JavascriptArray::MissingItem is a Var, so it may be 32-bit or 64 bit.
uint const offsetStart = sizeof(Js::SparseArraySegmentBase);
uint const missingItemCount = size * sizeof(double) / sizeof(Js::JavascriptArray::MissingItem);
for (uint i = 0; i < missingItemCount; i++)
for (uint i = 0; i < size; i++)
{
GenerateMemInit(
headOpnd, offsetStart + i * sizeof(Js::JavascriptArray::MissingItem),
IR::AddrOpnd::New(Js::JavascriptArray::MissingItem, IR::AddrOpndKindConstantAddress, m_func, true),
headOpnd, offsetStart + i * sizeof(double),
GetMissingItemOpndForAssignment(TyFloat64, m_func),
instr, isZeroed);
}
}
Expand All @@ -4149,9 +4147,9 @@ Lowerer::GenerateProfiledNewScObjArrayFastPath(IR::Instr *instr, Js::ArrayCallSi
headOpnd = GenerateArrayObjectsAlloc<Js::JavascriptArray>(instr, &size, arrayInfo, &isZeroed, isNoArgs);
for (uint i = 0; i < size; i++)
{
GenerateMemInit(
GenerateMemInit(
headOpnd, offsetStart + i * sizeof(Js::Var),
IR::AddrOpnd::New(Js::JavascriptArray::MissingItem, IR::AddrOpndKindConstantAddress, m_func, true),
GetMissingItemOpndForAssignment(TyVar, m_func),
instr, isZeroed);
}
}
Expand Down Expand Up @@ -4182,8 +4180,8 @@ Lowerer::GenerateProfiledNewScObjArrayFastPath(IR::Instr *instr, Js::ArrayCallSi
uint allocationBucketsCount = ArrayType::AllocationBucketsCount;
uint(*allocationBuckets)[Js::JavascriptArray::AllocationBucketsInfoSize];
allocationBuckets = ArrayType::allocationBuckets;
uint sizeFactor = 1;
IRType missingItemType = (arrayInfo && arrayInfo->IsNativeIntArray()) ? IRType::TyInt32 : IRType::TyVar;

IRType missingItemType = (arrayInfo ? arrayInfo->IsNativeIntArray() ? IRType::TyInt32 : arrayInfo->IsNativeFloatArray() ? IRType::TyFloat64 : IRType::TyVar : IRType::TyVar);
IR::LabelInstr * arrayInitDone = IR::LabelInstr::New(Js::OpCode::Label, func);

bool isNativeArray = arrayInfo && (arrayInfo->IsNativeIntArray() || arrayInfo->IsNativeFloatArray());
Expand All @@ -4195,9 +4193,7 @@ Lowerer::GenerateProfiledNewScObjArrayFastPath(IR::Instr *instr, Js::ArrayCallSi
}
else if (arrayInfo && arrayInfo->IsNativeFloatArray())
{
// Js::JavascriptArray::MissingItem is a Var, so it may be 32-bit or 64 bit.
sizeFactor = sizeof(double) / sizeof(Js::JavascriptArray::MissingItem);
sizeOfElement = sizeof(Js::JavascriptArray::MissingItem);
sizeOfElement = sizeof(double);
GenerateArrayInfoIsNativeFloatAndNotIntArrayTest(instr, arrayInfo, arrayInfoAddr, helperLabel);
}
else
Expand Down Expand Up @@ -4227,7 +4223,7 @@ Lowerer::GenerateProfiledNewScObjArrayFastPath(IR::Instr *instr, Js::ArrayCallSi

for (uint8 i = 0;i < allocationBucketsCount;i++)
{
missingItemCount = allocationBuckets[i][Js::JavascriptArray::MissingElementsCountIndex] * sizeFactor;
missingItemCount = allocationBuckets[i][Js::JavascriptArray::MissingElementsCountIndex];

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

instr->InsertBefore(arrayInitDone);

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

// Js::JavascriptArray::MissingItem is a Var, so it may be 32-bit or 64 bit.
uint const offsetStart = sizeof(Js::SparseArraySegmentBase) + doubles->count * sizeof(double);
uint const missingItem = (size - doubles->count) * sizeof(double) / sizeof(Js::JavascriptArray::MissingItem);
uint const missingItem = (size - doubles->count);
for (uint i = 0; i < missingItem; i++)
{
GenerateMemInit(headOpnd, offsetStart + i * sizeof(Js::JavascriptArray::MissingItem),
IR::AddrOpnd::New(Js::JavascriptArray::MissingItem, IR::AddrOpndKindConstantAddress, m_func, true), instr, isHeadSegmentZeroed);
GenerateMemInit(headOpnd, offsetStart + i * sizeof(double),
GetMissingItemOpndForAssignment(TyFloat64, m_func), instr, isHeadSegmentZeroed);
}
// Skip pass the helper call
IR::LabelInstr * doneLabel = IR::LabelInstr::New(Js::OpCode::Label, func);
Expand Down
17 changes: 14 additions & 3 deletions lib/Parser/Scan.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -193,20 +193,30 @@ void Scanner<EncodingPolicy>::PrepareForBackgroundParse(Js::ScriptContext *scrip
// This is used to determine a length of BSTR, which can't contain a NUL character.
//-----------------------------------------------------------------------------
template <typename EncodingPolicy>
charcount_t Scanner<EncodingPolicy>::LineLength(EncodedCharPtr first, EncodedCharPtr last)
charcount_t Scanner<EncodingPolicy>::LineLength(EncodedCharPtr first, EncodedCharPtr last, size_t* cb)
{
Assert(cb != nullptr);

charcount_t result = 0;
EncodedCharPtr p = first;

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

// Determine the length by scanning for the next newline
charcount_t cch = LineLength(pStart, m_pchLast);
size_t cb = 0;
charcount_t cch = LineLength(pStart, m_pchLast, &cb);
Assert(cch <= LONG_MAX);

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

*pbstrLine = SysAllocStringLen(NULL, cch);
if (!*pbstrLine)
Expand Down
2 changes: 1 addition & 1 deletion lib/Parser/Scan.h
Original file line number Diff line number Diff line change
Expand Up @@ -793,7 +793,7 @@ class Scanner : public IScanner, public EncodingPolicy

void ScanNewLine(uint ch);
void NotifyScannedNewLine();
charcount_t LineLength(EncodedCharPtr first, EncodedCharPtr last);
charcount_t LineLength(EncodedCharPtr first, EncodedCharPtr last, size_t* cb);

tokens ScanIdentifier(bool identifyKwds, EncodedCharPtr *pp);
BOOL FastIdentifierContinue(EncodedCharPtr&p, EncodedCharPtr last);
Expand Down
6 changes: 6 additions & 0 deletions lib/Runtime/Language/InterpreterStackFrame.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6793,6 +6793,12 @@ namespace Js
// Finally exited with LeaveNull, We don't throw for early returns
if (finallyEndOffset == 0 && exceptionObj)
{
#if ENABLE_NATIVE_CODEGEN
if (scriptContext->GetThreadContext()->GetTryHandlerAddrOfReturnAddr() != nullptr)
{
JavascriptExceptionOperators::WalkStackForCleaningUpInlineeInfo(scriptContext, nullptr, scriptContext->GetThreadContext()->GetTryHandlerAddrOfReturnAddr());
}
#endif
JavascriptExceptionOperators::DoThrow(const_cast<Js::JavascriptExceptionObject *>(exceptionObj), scriptContext);
}
if (finallyEndOffset != 0)
Expand Down
Loading

0 comments on commit 1e90fc4

Please sign in to comment.