Explorar o código

[CVE-2019-1141] Chakra JIT Type Confusion

During the loop prepass the index variable is not fully constructed, so we can't rely it being negative
So we need to kiil the object type.
Akrosh Gandhi %!s(int64=6) %!d(string=hai) anos
pai
achega
329d9d213e
Modificáronse 3 ficheiros con 12 adicións e 5 borrados
  1. 8 2
      lib/Backend/GlobOpt.cpp
  2. 1 1
      lib/Backend/GlobOpt.h
  3. 3 2
      lib/Backend/GlobOptFields.cpp

+ 8 - 2
lib/Backend/GlobOpt.cpp

@@ -2695,7 +2695,7 @@ GlobOpt::OptInstr(IR::Instr *&instr, bool* isInstrRemoved)
 }
 
 bool
-GlobOpt::IsNonNumericRegOpnd(IR::RegOpnd *opnd, bool inGlobOpt) const
+GlobOpt::IsNonNumericRegOpnd(IR::RegOpnd *opnd, bool inGlobOpt, bool *isSafeToTransferInPrepass /*=nullptr*/) const
 {
     if (opnd == nullptr)
     {
@@ -2725,12 +2725,18 @@ GlobOpt::IsNonNumericRegOpnd(IR::RegOpnd *opnd, bool inGlobOpt) const
         {
             return true;
         }
+
+        bool isSafeToTransfer = this->IsSafeToTransferInPrepass(opnd->m_sym, opndValueInfo);
+        if (isSafeToTransferInPrepass != nullptr)
+        {
+            *isSafeToTransferInPrepass = isSafeToTransfer;
+        }
         if (this->prePassLoop->preservesNumberValue->Test(opnd->m_sym->m_id))
         {
             return false;
         }
 
-        return !this->IsSafeToTransferInPrepass(opnd->m_sym, opndValueInfo);
+        return !isSafeToTransfer;
     }
 
     return true;

+ 1 - 1
lib/Backend/GlobOpt.h

@@ -773,7 +773,7 @@ private:
                                                 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** srcOpndPtr, Value *const srcVal);
-    bool                    IsNonNumericRegOpnd(IR::RegOpnd *opnd, bool inGlobOpt) const;
+    bool                    IsNonNumericRegOpnd(IR::RegOpnd *opnd, bool inGlobOpt, bool *isSafeToTransferInPrepass = nullptr) const;
 
 public:
     static bool             IsTypeSpecPhaseOff(Func const * func);

+ 3 - 2
lib/Backend/GlobOptFields.cpp

@@ -225,7 +225,8 @@ GlobOpt::KillLiveElems(IR::IndirOpnd * indirOpnd, IR::Opnd * valueOpnd, BVSparse
     // - We check the type specialization status for the sym as well. For the purpose of doing kills, we can assume that
     //   if type specialization happened, that fields don't need to be killed. Note that they may be killed in the next
     //   pass based on the value.
-    if (func->GetThisOrParentInlinerHasArguments() || this->IsNonNumericRegOpnd(indexOpnd, inGlobOpt))
+    bool isSafeToTransfer = true;
+    if (func->GetThisOrParentInlinerHasArguments() || this->IsNonNumericRegOpnd(indexOpnd, inGlobOpt, &isSafeToTransfer))
     {
         this->KillAllFields(bv); // This also kills all property type values, as the same bit-vector tracks those stack syms
         SetAnyPropertyMayBeWrittenTo();
@@ -236,7 +237,7 @@ GlobOpt::KillLiveElems(IR::IndirOpnd * indirOpnd, IR::Opnd * valueOpnd, BVSparse
         ValueInfo * indexValueInfo = indexValue ? indexValue->GetValueInfo() : nullptr;
         int indexLowerBound = 0;
 
-        if (indirOpnd->GetOffset() < 0 || (indexOpnd && (!indexValueInfo || !indexValueInfo->TryGetIntConstantLowerBound(&indexLowerBound, false) || indexLowerBound < 0)))
+        if (!isSafeToTransfer || indirOpnd->GetOffset() < 0 || (indexOpnd && (!indexValueInfo || !indexValueInfo->TryGetIntConstantLowerBound(&indexLowerBound, false) || indexLowerBound < 0)))
         {
             // Write/delete to a non-integer numeric index can't alias a name on the RHS of a dot, but it change object layout
             this->KillAllObjectTypes(bv);