From 8af718902bfdc23bdce67d013eb25bd73773e306 Mon Sep 17 00:00:00 2001 From: Michael Holman Date: Thu, 24 May 2018 13:42:28 -0700 Subject: [PATCH 1/4] [CVE-2018-8227] Edge - Bad input to JIT process causes OOB write - Internal --- lib/Backend/Func.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/Backend/Func.cpp b/lib/Backend/Func.cpp index f60b4d66de6..29cb4d23fcb 100644 --- a/lib/Backend/Func.cpp +++ b/lib/Backend/Func.cpp @@ -262,7 +262,7 @@ Func::Func(JitArenaAllocator *alloc, JITTimeWorkItem * workItem, ObjTypeSpecFldInfo * info = GetWorkItem()->GetJITTimeInfo()->GetObjTypeSpecFldInfo(i); if (info != nullptr) { - Assert(info->GetObjTypeSpecFldId() < GetTopFunc()->GetWorkItem()->GetJITTimeInfo()->GetGlobalObjTypeSpecFldInfoCount()); + AssertOrFailFast(info->GetObjTypeSpecFldId() < GetTopFunc()->GetWorkItem()->GetJITTimeInfo()->GetGlobalObjTypeSpecFldInfoCount()); GetTopFunc()->m_globalObjTypeSpecFldInfoArray[info->GetObjTypeSpecFldId()] = info; } } From 9b270c55bfea2fbefc9482d3414c4b4b395cad10 Mon Sep 17 00:00:00 2001 From: Meghana Gupta Date: Tue, 29 May 2018 11:04:56 -0700 Subject: [PATCH 2/4] [CVE-2018-8229] Edge - Chakra JIT Type confusion with hoisted SetConcatStrMultiItemBE instructions - Google, Inc. --- lib/Backend/GlobOpt.cpp | 21 +++++++++++++++------ lib/Backend/GlobOpt.h | 2 +- 2 files changed, 16 insertions(+), 7 deletions(-) diff --git a/lib/Backend/GlobOpt.cpp b/lib/Backend/GlobOpt.cpp index a1dba18ed77..25d425e3020 100644 --- a/lib/Backend/GlobOpt.cpp +++ b/lib/Backend/GlobOpt.cpp @@ -16452,14 +16452,16 @@ void GlobOpt::OptHoistUpdateValueType( Loop* loop, IR::Instr* instr, - IR::Opnd* srcOpnd, + IR::Opnd** srcOpndPtr /* All code paths that change src, should update srcOpndPtr*/, Value* opndVal) { - if (opndVal == nullptr || instr->m_opcode == Js::OpCode::FromVar) + if (opndVal == nullptr || instr->m_opcode == Js::OpCode::FromVar || srcOpndPtr == nullptr || *srcOpndPtr == nullptr) { return; } + IR::Opnd* srcOpnd = *srcOpndPtr; + Sym* opndSym = srcOpnd->GetSym();; if (opndSym) @@ -16472,8 +16474,11 @@ GlobOpt::OptHoistUpdateValueType( if (srcOpnd->GetValueType() != opndValueTypeInLandingPad) { + srcOpnd->SetValueType(opndValueTypeInLandingPad); + if (instr->m_opcode == Js::OpCode::SetConcatStrMultiItemBE) { + Assert(!opndSym->IsPropertySym()); Assert(!opndValueTypeInLandingPad.IsString()); Assert(instr->GetDst()); @@ -16484,6 +16489,9 @@ GlobOpt::OptHoistUpdateValueType( IR::Instr::New(Js::OpCode::Conv_PrimStr, strOpnd, srcOpnd->Use(instr->m_func), instr->m_func); instr->ReplaceSrc(srcOpnd, strOpnd); + // Replace above will free srcOpnd, so reassign it + *srcOpndPtr = srcOpnd = reinterpret_cast(strOpnd); + if (loop->bailOutInfo->bailOutInstr) { loop->bailOutInfo->bailOutInstr->InsertBefore(convPrimStrInstr); @@ -16492,9 +16500,10 @@ GlobOpt::OptHoistUpdateValueType( { landingPad->InsertAfter(convPrimStrInstr); } - } - srcOpnd->SetValueType(opndValueTypeInLandingPad); + // If we came here opndSym can't be PropertySym + return; + } } @@ -16528,7 +16537,7 @@ GlobOpt::OptHoistInvariant( if (src1) { // We are hoisting this instruction possibly past other uses, which might invalidate the last use info. Clear it. - OptHoistUpdateValueType(loop, instr, src1, src1Val); + OptHoistUpdateValueType(loop, instr, &src1, src1Val); if (src1->IsRegOpnd()) { @@ -16538,7 +16547,7 @@ GlobOpt::OptHoistInvariant( IR::Opnd* src2 = instr->GetSrc2(); if (src2) { - OptHoistUpdateValueType(loop, instr, src2, src2Val); + OptHoistUpdateValueType(loop, instr, &src2, src2Val); if (src2->IsRegOpnd()) { diff --git a/lib/Backend/GlobOpt.h b/lib/Backend/GlobOpt.h index 116f61ec73d..5c10c3cd878 100644 --- a/lib/Backend/GlobOpt.h +++ b/lib/Backend/GlobOpt.h @@ -758,7 +758,7 @@ class GlobOpt bool TryHoistInvariant(IR::Instr *instr, BasicBlock *block, Value *dstVal, Value *src1Val, Value *src2Val, bool isNotTypeSpecConv, const bool lossy = false, const bool forceInvariantHoisting = false, IR::BailOutKind bailoutKind = IR::BailOutInvalid); void HoistInvariantValueInfo(ValueInfo *const invariantValueInfoToHoist, Value *const valueToUpdate, BasicBlock *const targetBlock); - void OptHoistUpdateValueType(Loop* loop, IR::Instr* instr, IR::Opnd* srcOpnd, Value *const srcVal); + void OptHoistUpdateValueType(Loop* loop, IR::Instr* instr, IR::Opnd** srcOpndPtr, Value *const srcVal); public: static bool IsTypeSpecPhaseOff(Func const * func); static bool DoAggressiveIntTypeSpec(Func const * func); From c8abc36d55bc329c73711170084cfb9c8dda983a Mon Sep 17 00:00:00 2001 From: Paul Leathers Date: Tue, 29 May 2018 16:13:04 -0700 Subject: [PATCH 3/4] [CVE-2018-8236] Virtual typed array buffer read/written after free --- lib/Backend/GlobOpt.cpp | 30 +++++++++++++++++++++++------- 1 file changed, 23 insertions(+), 7 deletions(-) diff --git a/lib/Backend/GlobOpt.cpp b/lib/Backend/GlobOpt.cpp index 25d425e3020..c42a77c9ec7 100644 --- a/lib/Backend/GlobOpt.cpp +++ b/lib/Backend/GlobOpt.cpp @@ -12746,6 +12746,8 @@ GlobOpt::DoTrackNewValueForKills(Value *const value) const bool isJsArray = valueInfo->IsArrayOrObjectWithArray(); Assert(!isJsArray == valueInfo->IsOptimizedTypedArray()); + const bool isVirtualTypedArray = valueInfo->IsOptimizedVirtualTypedArray(); + Loop *implicitCallsLoop; if(currentBlock->next && !currentBlock->next->isDeleted && currentBlock->next->isLoopHeader) { @@ -12760,7 +12762,7 @@ GlobOpt::DoTrackNewValueForKills(Value *const value) implicitCallsLoop = currentBlock->loop; } - if(isJsArray) + if(isJsArray || isVirtualTypedArray) { if(!DoArrayCheckHoist(valueInfo->Type(), implicitCallsLoop)) { @@ -12779,7 +12781,7 @@ GlobOpt::DoTrackNewValueForKills(Value *const value) VerifyArrayValueInfoForTracking(valueInfo, isJsArray, currentBlock); #endif - if(!isJsArray) + if(!isJsArray && !isVirtualTypedArray) { return; } @@ -12815,11 +12817,13 @@ GlobOpt::DoTrackCopiedValueForKills(Value *const value) const bool isJsArray = valueInfo->IsArrayOrObjectWithArray(); Assert(!isJsArray == valueInfo->IsOptimizedTypedArray()); + const bool isVirtualTypedArray = valueInfo->IsOptimizedVirtualTypedArray(); + #if DBG VerifyArrayValueInfoForTracking(valueInfo, isJsArray, currentBlock); #endif - if(!isJsArray && !(valueInfo->IsArrayValueInfo() && valueInfo->AsArrayValueInfo()->HeadSegmentLengthSym())) + if(!isJsArray && !isVirtualTypedArray && !(valueInfo->IsArrayValueInfo() && valueInfo->AsArrayValueInfo()->HeadSegmentLengthSym())) { return; } @@ -12862,11 +12866,13 @@ GlobOpt::DoTrackMergedValueForKills( const bool isJsArray = valueInfo->IsArrayOrObjectWithArray(); Assert(!isJsArray == valueInfo->IsOptimizedTypedArray()); + const bool isVirtualTypedArray = valueInfo->IsOptimizedVirtualTypedArray(); + #if DBG VerifyArrayValueInfoForTracking(valueInfo, isJsArray, currentBlock, true); #endif - if(!isJsArray && !(valueInfo->IsArrayValueInfo() && valueInfo->AsArrayValueInfo()->HeadSegmentLengthSym())) + if(!isJsArray && !isVirtualTypedArray && !(valueInfo->IsArrayValueInfo() && valueInfo->AsArrayValueInfo()->HeadSegmentLengthSym())) { return; } @@ -12899,6 +12905,7 @@ GlobOpt::TrackValueInfoChangeForKills(BasicBlock *const block, Value *const valu const bool trackOldValueInfo = oldValueInfo->IsArrayOrObjectWithArray() || + oldValueInfo->IsOptimizedVirtualTypedArray() || ( oldValueInfo->IsOptimizedTypedArray() && oldValueInfo->IsArrayValueInfo() && @@ -12915,6 +12922,7 @@ GlobOpt::TrackValueInfoChangeForKills(BasicBlock *const block, Value *const valu const bool trackNewValueInfo = newValueInfo->IsArrayOrObjectWithArray() || + newValueInfo->IsOptimizedVirtualTypedArray() || ( newValueInfo->IsOptimizedTypedArray() && newValueInfo->IsArrayValueInfo() && @@ -12983,6 +12991,7 @@ GlobOpt::ProcessValueKills(IR::Instr *const instr) ValueInfo *const valueInfo = value->GetValueInfo(); Assert( valueInfo->IsArrayOrObjectWithArray() || + valueInfo->IsOptimizedVirtualTypedArray() || valueInfo->IsOptimizedTypedArray() && valueInfo->AsArrayValueInfo()->HeadSegmentLengthSym()); if (valueInfo->IsArrayOrObjectWithArray() || valueInfo->IsOptimizedVirtualTypedArray()) { @@ -13008,6 +13017,7 @@ GlobOpt::ProcessValueKills(IR::Instr *const instr) ValueInfo *const valueInfo = value->GetValueInfo(); Assert( valueInfo->IsArrayOrObjectWithArray() || + valueInfo->IsOptimizedVirtualTypedArray() || valueInfo->IsOptimizedTypedArray() && valueInfo->AsArrayValueInfo()->HeadSegmentLengthSym()); if(!valueInfo->IsArrayOrObjectWithArray() || !valueInfo->HasNoMissingValues()) { @@ -13028,6 +13038,7 @@ GlobOpt::ProcessValueKills(IR::Instr *const instr) ValueInfo *const valueInfo = value->GetValueInfo(); Assert( valueInfo->IsArrayOrObjectWithArray() || + valueInfo->IsOptimizedVirtualTypedArray() || valueInfo->IsOptimizedTypedArray() && valueInfo->AsArrayValueInfo()->HeadSegmentLengthSym()); if(!valueInfo->IsArrayOrObjectWithArray() || valueInfo->HasVarElements()) { @@ -13054,6 +13065,7 @@ GlobOpt::ProcessValueKills(IR::Instr *const instr) ValueInfo *valueInfo = value->GetValueInfo(); Assert( valueInfo->IsArrayOrObjectWithArray() || + valueInfo->IsOptimizedVirtualTypedArray() || valueInfo->IsOptimizedTypedArray() && valueInfo->AsArrayValueInfo()->HeadSegmentLengthSym()); if(!valueInfo->IsArrayOrObjectWithArray()) { @@ -13129,8 +13141,9 @@ GlobOpt::ProcessValueKills(BasicBlock *const block, GlobOptBlockData *const bloc ValueInfo *const valueInfo = value->GetValueInfo(); Assert( valueInfo->IsArrayOrObjectWithArray() || + valueInfo->IsOptimizedVirtualTypedArray() || valueInfo->IsOptimizedTypedArray() && valueInfo->AsArrayValueInfo()->HeadSegmentLengthSym()); - if(valueInfo->IsArrayOrObjectWithArray()) + if(valueInfo->IsArrayOrObjectWithArray() || valueInfo->IsOptimizedVirtualTypedArray()) { ChangeValueType(nullptr, value, valueInfo->Type().ToLikely(), false); continue; @@ -13163,18 +13176,21 @@ GlobOpt::ProcessValueKillsForLoopHeaderAfterBackEdgeMerge(BasicBlock *const bloc ValueInfo *valueInfo = value->GetValueInfo(); Assert( valueInfo->IsArrayOrObjectWithArray() || + valueInfo->IsOptimizedVirtualTypedArray() || valueInfo->IsOptimizedTypedArray() && valueInfo->AsArrayValueInfo()->HeadSegmentLengthSym()); const bool isJsArray = valueInfo->IsArrayOrObjectWithArray(); Assert(!isJsArray == valueInfo->IsOptimizedTypedArray()); - if(isJsArray ? loopKills.KillsValueType(valueInfo->Type()) : loopKills.KillsTypedArrayHeadSegmentLengths()) + const bool isVirtualTypedArray = valueInfo->IsOptimizedVirtualTypedArray(); + + if((isJsArray || isVirtualTypedArray) ? loopKills.KillsValueType(valueInfo->Type()) : loopKills.KillsTypedArrayHeadSegmentLengths()) { // Hoisting array checks and other related things for this type is disabled for the loop due to the kill, as // compensation code is currently not added on back-edges. When merging values from a back-edge, the array value // type cannot be definite, as that may require adding compensation code on the back-edge if the optimization pass // chooses to not optimize the array. - if(isJsArray) + if(isJsArray || isVirtualTypedArray) { ChangeValueType(nullptr, value, valueInfo->Type().ToLikely(), false); } From 1b4f8dce2e9ac8eb01941ea8550b9f4eb1a5bcdf Mon Sep 17 00:00:00 2001 From: "Lei Shi (CHAKRA)" Date: Tue, 12 Jun 2018 10:20:07 -0700 Subject: [PATCH 4/4] bump versions --- 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 bfa363e76ed..8decb929b98 100644 --- a/Build/NuGet/.pack-version +++ b/Build/NuGet/.pack-version @@ -1 +1 @@ -1.8.4 +1.8.5 diff --git a/lib/Common/ChakraCoreVersion.h b/lib/Common/ChakraCoreVersion.h index 9503cf10387..267a427b842 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 8 -#define CHAKRA_CORE_PATCH_VERSION 4 +#define CHAKRA_CORE_PATCH_VERSION 5 #define CHAKRA_CORE_VERSION_RELEASE_QFE 0 // Redundant with PATCH_VERSION. Keep this value set to 0. // -------------