Procházet zdrojové kódy

[MERGE #5869 @akroshg] December 2018, servicing update

Merge pull request #5869 from akroshg:servicing/1812

Addresses followings
CVE-2018-8583
CVE-2018-8624
CVE-2018-8618
CVE-2018-8629
CVE-2018-8617
Akrosh Gandhi před 7 roky
rodič
revize
daa5d2505d

+ 9 - 1
lib/Backend/BackwardPass.cpp

@@ -8669,7 +8669,15 @@ BackwardPass::RestoreInductionVariableValuesAfterMemOp(Loop *loop)
 
         IR::Opnd *inductionVariableOpnd = IR::RegOpnd::New(sym, IRType::TyInt32, localFunc);
         IR::Opnd *sizeOpnd = globOpt->GenerateInductionVariableChangeForMemOp(loop, inductionVariableChangeInfo.unroll);
-        loop->landingPad->InsertAfter(IR::Instr::New(opCode, inductionVariableOpnd, inductionVariableOpnd, sizeOpnd, loop->GetFunc()));
+        IR::Instr* restoreInductionVarInstr = IR::Instr::New(opCode, inductionVariableOpnd, inductionVariableOpnd, sizeOpnd, loop->GetFunc());
+
+        // The IR that restores the induction variable's value is placed before the MemOp. Since this IR can
+        // bailout to the loop's landing pad, placing this IR before the MemOp avoids performing the MemOp,
+        // bailing out because of this IR, and then performing the effects of the loop again.
+        loop->landingPad->InsertInstrBefore(restoreInductionVarInstr, loop->memOpInfo->instr);
+
+        // If restoring an induction variable results in an overflow, bailout to the loop's landing pad.
+        restoreInductionVarInstr->ConvertToBailOutInstr(loop->bailOutInfo, IR::BailOutOnOverflow);
     };
 
     for (auto it = loop->memOpInfo->inductionVariableChangeInfoMap->GetIterator(); it.IsValid(); it.MoveNext())

+ 7 - 1
lib/Backend/FlowGraph.cpp

@@ -5266,7 +5266,7 @@ BasicBlock::MergePredBlocksValueMaps(GlobOpt* globOpt)
             }
             if(symsRequiringCompensationToMergedValueInfoMap.Count() != 0)
             {
-                globOpt->InsertValueCompensation(pred, symsRequiringCompensationToMergedValueInfoMap);
+                globOpt->InsertValueCompensation(pred, &symsRequiringCompensationToMergedValueInfoMap);
             }
         }
     } NEXT_PREDECESSOR_EDGE_EDITING;
@@ -5325,6 +5325,12 @@ BasicBlock::MergePredBlocksValueMaps(GlobOpt* globOpt)
         loop->liveFieldsOnEntry = JitAnew(globOpt->alloc, BVSparse<JitArenaAllocator>, globOpt->alloc);
         loop->liveFieldsOnEntry->Copy(this->globOptData.liveFields);
 
+        if (symsRequiringCompensationToMergedValueInfoMap.Count() != 0)
+        {
+            loop->symsRequiringCompensationToMergedValueInfoMap = JitAnew(globOpt->alloc, SymToValueInfoMap, globOpt->alloc);
+            loop->symsRequiringCompensationToMergedValueInfoMap->Copy(&symsRequiringCompensationToMergedValueInfoMap);
+        }
+        
         if(globOpt->DoBoundCheckHoist() && loop->inductionVariables)
         {
             globOpt->FinalizeInductionVariables(loop, &blockData);

+ 4 - 1
lib/Backend/FlowGraph.h

@@ -575,6 +575,7 @@ public:
     BVSparse<JitArenaAllocator> *lossyInt32SymsOnEntry; // see GlobOptData::liveLossyInt32Syms
     BVSparse<JitArenaAllocator> *float64SymsOnEntry;
     BVSparse<JitArenaAllocator> *liveFieldsOnEntry;
+    SymToValueInfoMap           *symsRequiringCompensationToMergedValueInfoMap;
 
     BVSparse<JitArenaAllocator> *symsUsedBeforeDefined;                // stack syms that are live in the landing pad, and used before they are defined in the loop
     BVSparse<JitArenaAllocator> *likelyIntSymsUsedBeforeDefined;       // stack syms that are live in the landing pad with a likely-int value, and used before they are defined in the loop
@@ -694,6 +695,7 @@ public:
         // Temporary map to reuse existing startIndexOpnd while emitting
         // 0 = !increment & !alreadyChanged, 1 = !increment & alreadyChanged, 2 = increment & !alreadyChanged, 3 = increment & alreadyChanged
         IR::RegOpnd* startIndexOpndCache[4];
+        IR::Instr* instr;
     } MemOpInfo;
 
     bool doMemOp : 1;
@@ -741,7 +743,8 @@ public:
         allFieldsKilled(false),
         isLeaf(true),
         isProcessed(false),
-        initialValueFieldMap(alloc)
+        initialValueFieldMap(alloc),
+        symsRequiringCompensationToMergedValueInfoMap(nullptr)
     {
         this->loopNumber = ++func->loopCount;
     }

+ 15 - 9
lib/Backend/GlobOpt.cpp

@@ -599,6 +599,11 @@ GlobOpt::OptBlock(BasicBlock *block)
                     this->tempBv->And(liveOnBackEdge);
                     this->ToFloat64(this->tempBv, block->loop->landingPad);
 
+                    if (block->loop->symsRequiringCompensationToMergedValueInfoMap)
+                    {
+                        InsertValueCompensation(block, block->loop->symsRequiringCompensationToMergedValueInfoMap);
+                    }
+
                     // Now that we're done with the liveFields within this loop, trim the set to those syms
                     // that the backward pass told us were live out of the loop.
                     // This assumes we have no further need of the liveFields within the loop.
@@ -1151,10 +1156,10 @@ void GlobOpt::FieldPRE(Loop *loop)
 
 void GlobOpt::InsertValueCompensation(
     BasicBlock *const predecessor,
-    const SymToValueInfoMap &symsRequiringCompensationToMergedValueInfoMap)
+    const SymToValueInfoMap *symsRequiringCompensationToMergedValueInfoMap)
 {
     Assert(predecessor);
-    Assert(symsRequiringCompensationToMergedValueInfoMap.Count() != 0);
+    Assert(symsRequiringCompensationToMergedValueInfoMap->Count() != 0);
 
     IR::Instr *insertBeforeInstr = predecessor->GetLastInstr();
     Func *const func = insertBeforeInstr->m_func;
@@ -1193,7 +1198,7 @@ void GlobOpt::InsertValueCompensation(
         }
     };
     JsUtil::List<DelayChangeValueInfo, ArenaAllocator> delayChangeValueInfo(alloc);
-    for(auto it = symsRequiringCompensationToMergedValueInfoMap.GetIterator(); it.IsValid(); it.MoveNext())
+    for(auto it = symsRequiringCompensationToMergedValueInfoMap->GetIterator(); it.IsValid(); it.MoveNext())
     {
         const auto &entry = it.Current();
         Sym *const sym = entry.Key();
@@ -1840,6 +1845,10 @@ GlobOpt::IsAllowedForMemOpt(IR::Instr* instr, bool isMemset, IR::RegOpnd *baseOp
             return false;
         }
     }
+    else
+    {
+        return false;
+    }
 
     if (!baseValueType.IsTypedArray())
     {
@@ -2843,12 +2852,6 @@ GlobOpt::OptDst(
         {
             this->FinishOptPropOp(instr, opnd->AsPropertySymOpnd());
         }
-        else if (instr->m_opcode == Js::OpCode::StElemI_A ||
-                 instr->m_opcode == Js::OpCode::StElemI_A_Strict ||
-                 instr->m_opcode == Js::OpCode::InitComputedProperty)
-        {
-            this->KillObjectHeaderInlinedTypeSyms(this->currentBlock, false);
-        }
 
         if (opnd->IsIndirOpnd() && !this->IsLoopPrePass())
         {
@@ -16854,6 +16857,9 @@ GlobOpt::EmitMemop(Loop * loop, LoopCount *loopCount, const MemOpEmitData* emitD
     memopInstr->SetSrc2(sizeOpnd);
     insertBeforeInstr->InsertBefore(memopInstr);
 
+
+    loop->memOpInfo->instr = memopInstr;
+
 #if DBG_DUMP
     if (DO_MEMOP_TRACE())
     {

+ 1 - 1
lib/Backend/GlobOpt.h

@@ -737,7 +737,7 @@ private:
     void                    PreLowerCanonicalize(IR::Instr *instr, Value **pSrc1Val, Value **pSrc2Val);
     void                    ProcessKills(IR::Instr *instr);
     void                    InsertCloneStrs(BasicBlock *toBlock, GlobOptBlockData *toData, GlobOptBlockData *fromData);
-    void                    InsertValueCompensation(BasicBlock *const predecessor, const SymToValueInfoMap &symsRequiringCompensationToMergedValueInfoMap);
+    void                    InsertValueCompensation(BasicBlock *const predecessor, const SymToValueInfoMap *symsRequiringCompensationToMergedValueInfoMap);
     IR::Instr *             ToVarUses(IR::Instr *instr, IR::Opnd *opnd, bool isDst, Value *val);
     void                    ToVar(BVSparse<JitArenaAllocator> *bv, BasicBlock *block);
     IR::Instr *             ToVar(IR::Instr *instr, IR::RegOpnd *regOpnd, BasicBlock *block, Value *val, bool needsUpdate);

+ 25 - 3
lib/Backend/GlobOptFields.cpp

@@ -328,10 +328,20 @@ GlobOpt::ProcessFieldKills(IR::Instr *instr, BVSparse<JitArenaAllocator> *bv, bo
         Assert(dstOpnd != nullptr);
         KillLiveFields(this->lengthEquivBv, bv);
         KillLiveElems(dstOpnd->AsIndirOpnd(), bv, inGlobOpt, instr->m_func);
+        if (inGlobOpt)
+        {
+            KillObjectHeaderInlinedTypeSyms(this->currentBlock, false);
+        }
         break;
 
     case Js::OpCode::InitComputedProperty:
+    case Js::OpCode::InitGetElemI:
+    case Js::OpCode::InitSetElemI:
         KillLiveElems(dstOpnd->AsIndirOpnd(), bv, inGlobOpt, instr->m_func);
+        if (inGlobOpt)
+        {
+            KillObjectHeaderInlinedTypeSyms(this->currentBlock, false);
+        }
         break;
 
     case Js::OpCode::DeleteElemI_A:
@@ -394,6 +404,10 @@ GlobOpt::ProcessFieldKills(IR::Instr *instr, BVSparse<JitArenaAllocator> *bv, bo
     case Js::OpCode::InlineArrayPush:
     case Js::OpCode::InlineArrayPop:
         KillLiveFields(this->lengthEquivBv, bv);
+        if (inGlobOpt)
+        {
+            KillObjectHeaderInlinedTypeSyms(this->currentBlock, false);
+        }
         break;
 
     case Js::OpCode::InlineeStart:
@@ -410,10 +424,18 @@ GlobOpt::ProcessFieldKills(IR::Instr *instr, BVSparse<JitArenaAllocator> *bv, bo
         fnHelper = instr->GetSrc1()->AsHelperCallOpnd()->m_fnHelper;
 
         // Kill length field for built-ins that can update it.
-        if(nullptr != this->lengthEquivBv && (fnHelper == IR::JnHelperMethod::HelperArray_Shift || fnHelper == IR::JnHelperMethod::HelperArray_Splice
-            || fnHelper == IR::JnHelperMethod::HelperArray_Unshift))
+        if(fnHelper == IR::JnHelperMethod::HelperArray_Shift 
+           || fnHelper == IR::JnHelperMethod::HelperArray_Splice
+           || fnHelper == IR::JnHelperMethod::HelperArray_Unshift)
         {
-            KillLiveFields(this->lengthEquivBv, bv);
+            if (nullptr != this->lengthEquivBv)
+            {
+                KillLiveFields(this->lengthEquivBv, bv);
+            }
+            if (inGlobOpt)
+            {
+                KillObjectHeaderInlinedTypeSyms(this->currentBlock, false);
+            }
         }
 
         if ((fnHelper == IR::JnHelperMethod::HelperRegExp_Exec)

+ 10 - 5
lib/Backend/GlobOptIntBounds.cpp

@@ -1822,11 +1822,16 @@ void GlobOpt::GenerateLoopCountPlusOne(Loop *const loop, LoopCount *const loopCo
         IR::RegOpnd *loopCountOpnd = IR::RegOpnd::New(type, func);
         IR::RegOpnd *minusOneOpnd = IR::RegOpnd::New(loopCount->LoopCountMinusOneSym(), type, func);
         minusOneOpnd->SetIsJITOptimizedReg(true);
-        insertBeforeInstr->InsertBefore(IR::Instr::New(Js::OpCode::Add_I4,
-                                                       loopCountOpnd,
-                                                       minusOneOpnd,
-                                                       IR::IntConstOpnd::New(1, type, func, true),
-                                                       func));
+        IR::Instr* incrInstr = IR::Instr::New(Js::OpCode::Add_I4,
+            loopCountOpnd,
+            minusOneOpnd,
+            IR::IntConstOpnd::New(1, type, func, true),
+            func);
+
+        insertBeforeInstr->InsertBefore(incrInstr);
+
+        // Incrementing to 1 can overflow - add a bounds check bailout here
+        incrInstr->ConvertToBailOutInstr(bailOutInfo, IR::BailOutOnFailedHoistedLoopCountBasedBoundCheck);
         loopCount->SetLoopCountSym(loopCountOpnd->GetStackSym());
     }
 }