From 90e222e9a9ba64bd808666f44e6a0913d6318f78 Mon Sep 17 00:00:00 2001 From: Atul Katti Date: Thu, 24 Sep 2020 11:58:43 -0700 Subject: [PATCH 1/3] [CVE-2020-17048] --- lib/Backend/GlobOpt.cpp | 8 ++++++ lib/Backend/GlobOpt.h | 8 +++--- lib/Backend/GlobOptFields.cpp | 51 +++++++++++++---------------------- 3 files changed, 30 insertions(+), 37 deletions(-) diff --git a/lib/Backend/GlobOpt.cpp b/lib/Backend/GlobOpt.cpp index 7e6bea97f02..a27dc1d29c2 100644 --- a/lib/Backend/GlobOpt.cpp +++ b/lib/Backend/GlobOpt.cpp @@ -14591,6 +14591,14 @@ GlobOpt::OptIsInvariant( allowNonPrimitives = true; } break; + + case Js::OpCode::CheckFixedFld: + if (!instr->GetSrc1()->AsPropertySymOpnd()->NeedsPrimaryTypeCheck()) + { + break; + } + // Fall through. If the instruction has to do a type check as well as a fixed field check, then we need to check the invariance + // of the type symbol. case Js::OpCode::CheckObjType: // Bug 11712101: If the operand is a field, ensure that its containing object type is invariant // before hoisting -- that is, don't hoist a CheckObjType over a DeleteFld on that object. diff --git a/lib/Backend/GlobOpt.h b/lib/Backend/GlobOpt.h index a53b5aea1f1..3804f62221d 100644 --- a/lib/Backend/GlobOpt.h +++ b/lib/Backend/GlobOpt.h @@ -559,7 +559,7 @@ class GlobOpt void TryOptimizeInstrWithFixedDataProperty(IR::Instr * * const pInstr); bool CheckIfPropOpEmitsTypeCheck(IR::Instr *instr, IR::PropertySymOpnd *opnd); IR::PropertySymOpnd * CreateOpndForTypeCheckOnly(IR::PropertySymOpnd* opnd, Func* func); - bool FinishOptPropOp(IR::Instr *instr, IR::PropertySymOpnd *opnd, BasicBlock* block = nullptr, bool updateExistingValue = false, bool* emitsTypeCheckOut = nullptr, bool* changesTypeValueOut = nullptr); + bool FinishOptPropOp(IR::Instr *instr, IR::PropertySymOpnd *opnd, BasicBlock* block = nullptr, bool* emitsTypeCheckOut = nullptr, bool* changesTypeValueOut = nullptr); IR::Instr * SetTypeCheckBailOut(IR::Opnd *opnd, IR::Instr *instr, BailOutInfo *bailOutInfo); void OptArguments(IR::Instr *Instr); void TrackInstrsForScopeObjectRemoval(IR::Instr * instr); @@ -944,7 +944,7 @@ class GlobOpt bool ProcessPropOpInTypeCheckSeq(IR::Instr* instr, IR::PropertySymOpnd *opnd); bool CheckIfInstrInTypeCheckSeqEmitsTypeCheck(IR::Instr* instr, IR::PropertySymOpnd *opnd); template - bool ProcessPropOpInTypeCheckSeq(IR::Instr* instr, IR::PropertySymOpnd *opnd, BasicBlock* block, bool updateExistingValue, bool* emitsTypeCheckOut = nullptr, bool* changesTypeValueOut = nullptr, bool *isObjTypeChecked = nullptr); + bool ProcessPropOpInTypeCheckSeq(IR::Instr* instr, IR::PropertySymOpnd *opnd, BasicBlock* block, bool* emitsTypeCheckOut = nullptr, bool* changesTypeValueOut = nullptr, bool *isObjTypeChecked = nullptr); template bool MapObjectHeaderInlinedTypeSymsUntil(BasicBlock *block, bool isObjTypeSpecialized, SymID opndId, Fn fn); void KillObjectHeaderInlinedTypeSyms(BasicBlock *block, bool isObjTypeSpecialized, SymID symId = SymID_Invalid); @@ -954,8 +954,8 @@ class GlobOpt void SetTypeSetOnObjectTypeValue(Value* value, Js::EquivalentTypeSet* typeSet); void UpdateObjectTypeValue(Value* value, const JITTypeHolder type, bool setType, Js::EquivalentTypeSet* typeSet, bool setTypeSet); void SetObjectTypeFromTypeSym(StackSym *typeSym, Value* value, BasicBlock* block = nullptr); - void SetObjectTypeFromTypeSym(StackSym *typeSym, const JITTypeHolder type, Js::EquivalentTypeSet * typeSet, BasicBlock* block = nullptr, bool updateExistingValue = false); - void SetObjectTypeFromTypeSym(StackSym *typeSym, const JITTypeHolder type, Js::EquivalentTypeSet * typeSet, GlobOptBlockData *blockData, bool updateExistingValue = false); + void SetObjectTypeFromTypeSym(StackSym *typeSym, const JITTypeHolder type, Js::EquivalentTypeSet * typeSet, BasicBlock* block = nullptr); + void SetObjectTypeFromTypeSym(StackSym *typeSym, const JITTypeHolder type, Js::EquivalentTypeSet * typeSet, GlobOptBlockData *blockData); void KillObjectType(StackSym *objectSym, BVSparse* liveFields = nullptr); void KillAllObjectTypes(BVSparse* liveFields = nullptr); void EndFieldLifetime(IR::SymOpnd *symOpnd); diff --git a/lib/Backend/GlobOptFields.cpp b/lib/Backend/GlobOptFields.cpp index fcb524b246c..e8b670edd5b 100644 --- a/lib/Backend/GlobOptFields.cpp +++ b/lib/Backend/GlobOptFields.cpp @@ -875,7 +875,7 @@ GlobOpt::CreateOpndForTypeCheckOnly(IR::PropertySymOpnd* opnd, Func* func) } bool -GlobOpt::FinishOptPropOp(IR::Instr *instr, IR::PropertySymOpnd *opnd, BasicBlock* block, bool updateExistingValue, bool* emitsTypeCheckOut, bool* changesTypeValueOut) +GlobOpt::FinishOptPropOp(IR::Instr *instr, IR::PropertySymOpnd *opnd, BasicBlock* block, bool* emitsTypeCheckOut, bool* changesTypeValueOut) { if (!DoFieldRefOpts() || !OpCodeAttr::FastFldInstr(instr->m_opcode)) { @@ -888,7 +888,7 @@ GlobOpt::FinishOptPropOp(IR::Instr *instr, IR::PropertySymOpnd *opnd, BasicBlock if (isTypeCheckSeqCandidate) { - isObjTypeSpecialized = ProcessPropOpInTypeCheckSeq(instr, opnd, block, updateExistingValue, emitsTypeCheckOut, changesTypeValueOut, &isObjTypeChecked); + isObjTypeSpecialized = ProcessPropOpInTypeCheckSeq(instr, opnd, block, emitsTypeCheckOut, changesTypeValueOut, &isObjTypeChecked); } if (opnd == instr->GetDst() && this->objectTypeSyms) @@ -1102,19 +1102,19 @@ GlobOpt::CompareCurrentTypesWithExpectedTypes(JsTypeValueInfo *valueInfo, IR::Pr bool GlobOpt::ProcessPropOpInTypeCheckSeq(IR::Instr* instr, IR::PropertySymOpnd *opnd) { - return ProcessPropOpInTypeCheckSeq(instr, opnd, this->currentBlock, false); + return ProcessPropOpInTypeCheckSeq(instr, opnd, this->currentBlock); } bool GlobOpt::CheckIfInstrInTypeCheckSeqEmitsTypeCheck(IR::Instr* instr, IR::PropertySymOpnd *opnd) { bool emitsTypeCheck; - ProcessPropOpInTypeCheckSeq(instr, opnd, this->currentBlock, false, &emitsTypeCheck); + ProcessPropOpInTypeCheckSeq(instr, opnd, this->currentBlock, &emitsTypeCheck); return emitsTypeCheck; } template bool -GlobOpt::ProcessPropOpInTypeCheckSeq(IR::Instr* instr, IR::PropertySymOpnd *opnd, BasicBlock* block, bool updateExistingValue, bool* emitsTypeCheckOut, bool* changesTypeValueOut, bool *isTypeCheckedOut) +GlobOpt::ProcessPropOpInTypeCheckSeq(IR::Instr* instr, IR::PropertySymOpnd *opnd, BasicBlock* block, bool* emitsTypeCheckOut, bool* changesTypeValueOut, bool *isTypeCheckedOut) { // We no longer mark types as dead in the backward pass, so we should never see an instr with a dead type here // during the forward pass. For the time being we've retained the logic below to deal with dead types in case @@ -1193,7 +1193,7 @@ GlobOpt::ProcessPropOpInTypeCheckSeq(IR::Instr* instr, IR::PropertySymOpnd *opnd addsProperty = isStore && isSpecialized && opnd->HasInitialType(); if (produceType) { - SetObjectTypeFromTypeSym(typeSym, opndType, nullptr, block, updateExistingValue); + SetObjectTypeFromTypeSym(typeSym, opndType, nullptr, block); } } else if (valueInfo->GetJsType() != nullptr) @@ -1227,7 +1227,7 @@ GlobOpt::ProcessPropOpInTypeCheckSeq(IR::Instr* instr, IR::PropertySymOpnd *opnd } if (produceType) { - SetObjectTypeFromTypeSym(typeSym, opndType, nullptr, block, updateExistingValue); + SetObjectTypeFromTypeSym(typeSym, opndType, nullptr, block); } isSpecialized = !isTypeDead || !objectMayHaveAcquiredAdditionalProperties; emitsTypeCheck = isSpecialized && objectMayHaveAcquiredAdditionalProperties; @@ -1376,11 +1376,11 @@ GlobOpt::ProcessPropOpInTypeCheckSeq(IR::Instr* instr, IR::PropertySymOpnd *opnd { if (opnd->IsMono()) { - SetObjectTypeFromTypeSym(typeSym, opnd->GetFirstEquivalentType(), nullptr, block, updateExistingValue); + SetObjectTypeFromTypeSym(typeSym, opnd->GetFirstEquivalentType(), nullptr, block); } else { - SetObjectTypeFromTypeSym(typeSym, nullptr, opndTypeSet, block, updateExistingValue); + SetObjectTypeFromTypeSym(typeSym, nullptr, opndTypeSet, block); } } isSpecialized = !isTypeDead; @@ -1421,11 +1421,11 @@ GlobOpt::ProcessPropOpInTypeCheckSeq(IR::Instr* instr, IR::PropertySymOpnd *opnd { if (opnd->IsMono()) { - SetObjectTypeFromTypeSym(typeSym, opnd->GetFirstEquivalentType(), nullptr, block, updateExistingValue); + SetObjectTypeFromTypeSym(typeSym, opnd->GetFirstEquivalentType(), nullptr, block); } else { - SetObjectTypeFromTypeSym(typeSym, nullptr, opndTypeSet, block, updateExistingValue); + SetObjectTypeFromTypeSym(typeSym, nullptr, opndTypeSet, block); } } isSpecialized = !isTypeDead; @@ -1788,18 +1788,18 @@ GlobOpt::SetObjectTypeFromTypeSym(StackSym *typeSym, Value* value, BasicBlock* b } void -GlobOpt::SetObjectTypeFromTypeSym(StackSym *typeSym, const JITTypeHolder type, Js::EquivalentTypeSet * typeSet, BasicBlock* block, bool updateExistingValue) +GlobOpt::SetObjectTypeFromTypeSym(StackSym *typeSym, const JITTypeHolder type, Js::EquivalentTypeSet * typeSet, BasicBlock* block) { if (block == nullptr) { block = this->currentBlock; } - SetObjectTypeFromTypeSym(typeSym, type, typeSet, &block->globOptData, updateExistingValue); + SetObjectTypeFromTypeSym(typeSym, type, typeSet, &block->globOptData); } void -GlobOpt::SetObjectTypeFromTypeSym(StackSym *typeSym, const JITTypeHolder type, Js::EquivalentTypeSet * typeSet, GlobOptBlockData *blockData, bool updateExistingValue) +GlobOpt::SetObjectTypeFromTypeSym(StackSym *typeSym, const JITTypeHolder type, Js::EquivalentTypeSet * typeSet, GlobOptBlockData *blockData) { Assert(typeSym != nullptr); @@ -1810,25 +1810,10 @@ GlobOpt::SetObjectTypeFromTypeSym(StackSym *typeSym, const JITTypeHolder type, J blockData = &this->currentBlock->globOptData; } - if (updateExistingValue) - { - Value* value = blockData->FindValueFromMapDirect(typeSymId); - - // If we're trying to update an existing value, the value better exist. We only do this when updating a generic - // value created during loop pre-pass for field hoisting, so we expect the value info to still be blank. - Assert(value != nullptr && value->GetValueInfo() != nullptr && value->GetValueInfo()->IsJsType()); - JsTypeValueInfo* valueInfo = value->GetValueInfo()->AsJsType(); - Assert(valueInfo->GetJsType() == nullptr && valueInfo->GetJsTypeSet() == nullptr); - UpdateObjectTypeValue(value, type, true, typeSet, true); - } - else - { - JsTypeValueInfo* valueInfo = JsTypeValueInfo::New(this->alloc, type, typeSet); - this->SetSymStoreDirect(valueInfo, typeSym); - Value* value = NewValue(valueInfo); - blockData->SetValue(value, typeSym); - } - + JsTypeValueInfo* valueInfo = JsTypeValueInfo::New(this->alloc, type, typeSet); + this->SetSymStoreDirect(valueInfo, typeSym); + Value* value = NewValue(valueInfo); + blockData->SetValue(value, typeSym); blockData->liveFields->Set(typeSymId); } From e81e8a51ec7ba3d0dfb6089254f166c2733216e1 Mon Sep 17 00:00:00 2001 From: Paul Leathers Date: Wed, 30 Sep 2020 15:00:01 -0700 Subject: [PATCH 2/3] [CVE-2020-17054] --- lib/Backend/Lower.cpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/lib/Backend/Lower.cpp b/lib/Backend/Lower.cpp index 813227fe3e0..7543a787040 100644 --- a/lib/Backend/Lower.cpp +++ b/lib/Backend/Lower.cpp @@ -27152,8 +27152,11 @@ void Lowerer::LowerLdFrameDisplay(IR::Instr *instr, bool doStackFrameDisplay) if (instr->m_func != this->m_func && this->m_func->DoStackFrameDisplay()) { StackSym * inlineeFrameDisplaySym = instr->m_func->GetLocalFrameDisplaySym(); - Assert(inlineeFrameDisplaySym->IsAllocated()); - InsertMove(IR::SymOpnd::New(inlineeFrameDisplaySym, TyMachReg, m_func), dstOpnd, instr); + Assert((inlineeFrameDisplaySym && inlineeFrameDisplaySym->IsAllocated()) || this->m_func->IsLoopBody()); + if (inlineeFrameDisplaySym && inlineeFrameDisplaySym->IsAllocated()) + { + InsertMove(IR::SymOpnd::New(inlineeFrameDisplaySym, TyMachReg, m_func), dstOpnd, instr); + } } } From ab0e7c07c288e3c80241b007f3c8ccc8680431f0 Mon Sep 17 00:00:00 2001 From: Akrosh Gandhi Date: Mon, 9 Nov 2020 22:42:05 -0800 Subject: [PATCH 3/3] Updating release version to 1.11.23 --- Build/NuGet/.pack-version | 2 +- lib/Common/ChakraCoreVersion.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Build/NuGet/.pack-version b/Build/NuGet/.pack-version index 45333f34e4b..33fb4acf145 100644 --- a/Build/NuGet/.pack-version +++ b/Build/NuGet/.pack-version @@ -1 +1 @@ -1.11.22 +1.11.23 diff --git a/lib/Common/ChakraCoreVersion.h b/lib/Common/ChakraCoreVersion.h index e718f44cfc6..d6d376a71d9 100644 --- a/lib/Common/ChakraCoreVersion.h +++ b/lib/Common/ChakraCoreVersion.h @@ -17,7 +17,7 @@ // ChakraCore version number definitions (used in ChakraCore binary metadata) #define CHAKRA_CORE_MAJOR_VERSION 1 #define CHAKRA_CORE_MINOR_VERSION 11 -#define CHAKRA_CORE_PATCH_VERSION 22 +#define CHAKRA_CORE_PATCH_VERSION 23 #define CHAKRA_CORE_VERSION_RELEASE_QFE 0 // Redundant with PATCH_VERSION. Keep this value set to 0. // -------------