Răsfoiți Sursa

[CVE-2017-0234] Too aggressive bound check removal

Don't eliminate bounds checks on virtual typed arrays if we can't guarantee that the accesses will be within 4Gb
Rajat Dua 8 ani în urmă
părinte
comite
a1345ad480
1 a modificat fișierele cu 31 adăugiri și 3 ștergeri
  1. 31 3
      lib/Backend/GlobOpt.cpp

+ 31 - 3
lib/Backend/GlobOpt.cpp

@@ -16338,9 +16338,37 @@ GlobOpt::OptArraySrc(IR::Instr * *const instrRef)
             )
            )
         {
-            eliminatedLowerBoundCheck = true;
-            eliminatedUpperBoundCheck = true;
-            canBailOutOnArrayAccessHelperCall = false;
+            // Unless we're in asm.js (where it is guaranteed that virtual typed array accesses cannot read/write beyond 4GB),
+            // check the range of the index to make sure we won't access beyond the reserved memory beforing eliminating bounds
+            // checks in jitted code.
+            if (!GetIsAsmJSFunc())
+            {
+                IR::RegOpnd * idxOpnd = baseOwnerIndir->GetIndexOpnd();
+                if (idxOpnd)
+                {
+                    StackSym * idxSym = idxOpnd->m_sym->IsTypeSpec() ? idxOpnd->m_sym->GetVarEquivSym(nullptr) : idxOpnd->m_sym;
+                    Value * idxValue = FindValue(idxSym);
+                    IntConstantBounds idxConstantBounds;
+                    if (idxValue && idxValue->GetValueInfo()->TryGetIntConstantBounds(&idxConstantBounds))
+                    {
+                        BYTE indirScale = Lowerer::GetArrayIndirScale(baseValueType);
+                        int32 upperBound = idxConstantBounds.UpperBound();
+                        int32 lowerBound = idxConstantBounds.LowerBound();
+                        if (lowerBound >= 0 && ((static_cast<uint64>(upperBound) << indirScale) < MAX_ASMJS_ARRAYBUFFER_LENGTH))
+                        {
+                            eliminatedLowerBoundCheck = true;
+                            eliminatedUpperBoundCheck = true;
+                            canBailOutOnArrayAccessHelperCall = false;
+                        }
+                    }
+                }
+            }
+            else
+            {
+                eliminatedLowerBoundCheck = true;
+                eliminatedUpperBoundCheck = true;
+                canBailOutOnArrayAccessHelperCall = false;
+            }
         }
     }