From 846e508ea0862846e89ef41e87ecfb73a75ac130 Mon Sep 17 00:00:00 2001 From: Paul Leathers Date: Wed, 15 May 2019 17:30:04 -0700 Subject: [PATCH] CVE-2019-1051 --- lib/Backend/GlobOpt.h | 2 +- lib/Backend/GlobOptFields.cpp | 25 +++++++++++++++++++++---- 2 files changed, 22 insertions(+), 5 deletions(-) diff --git a/lib/Backend/GlobOpt.h b/lib/Backend/GlobOpt.h index 17676a0cc8d..e71c1900730 100644 --- a/lib/Backend/GlobOpt.h +++ b/lib/Backend/GlobOpt.h @@ -897,7 +897,7 @@ class GlobOpt void KillLiveFields(StackSym * stackSym, BVSparse * bv); void KillLiveFields(PropertySym * propertySym, BVSparse * bv); void KillLiveFields(BVSparse *const fieldsToKill, BVSparse *const bv) const; - void KillLiveElems(IR::IndirOpnd * indirOpnd, BVSparse * bv, bool inGlobOpt, Func *func); + void KillLiveElems(IR::IndirOpnd * indirOpnd, IR::Opnd * valueOpnd, BVSparse * bv, bool inGlobOpt, Func *func); void KillAllFields(BVSparse * bv); void SetAnyPropertyMayBeWrittenTo(); void AddToPropertiesWrittenTo(Js::PropertyId propertyId); diff --git a/lib/Backend/GlobOptFields.cpp b/lib/Backend/GlobOptFields.cpp index 87518063094..92a7e9ec108 100644 --- a/lib/Backend/GlobOptFields.cpp +++ b/lib/Backend/GlobOptFields.cpp @@ -208,7 +208,7 @@ void GlobOpt::KillLiveFields(BVSparse *const fieldsToKill, BV } void -GlobOpt::KillLiveElems(IR::IndirOpnd * indirOpnd, BVSparse * bv, bool inGlobOpt, Func *func) +GlobOpt::KillLiveElems(IR::IndirOpnd * indirOpnd, IR::Opnd * valueOpnd, BVSparse * bv, bool inGlobOpt, Func *func) { IR::RegOpnd *indexOpnd = indirOpnd->GetIndexOpnd(); @@ -241,6 +241,23 @@ GlobOpt::KillLiveElems(IR::IndirOpnd * indirOpnd, BVSparse * // 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); } + else if ((!valueOpnd || valueOpnd->IsVar()) && this->objectTypeSyms != nullptr) + { + // If we wind up converting a native array, block final-type opt at this point, because we could evolve + // to a type with the wrong type ID. Do this by noting that we may have evolved any type and so must + // check it before evolving it further. + IR::RegOpnd *baseOpnd = indirOpnd->GetBaseOpnd(); + Value * baseValue = baseOpnd ? this->currentBlock->globOptData.FindValue(baseOpnd->m_sym) : nullptr; + ValueInfo * baseValueInfo = baseValue ? baseValue->GetValueInfo() : nullptr; + if (!baseValueInfo || !baseValueInfo->IsNotNativeArray()) + { + if (this->currentBlock->globOptData.maybeWrittenTypeSyms == nullptr) + { + this->currentBlock->globOptData.maybeWrittenTypeSyms = JitAnew(this->alloc, BVSparse, this->alloc); + } + this->currentBlock->globOptData.maybeWrittenTypeSyms->Or(this->objectTypeSyms); + } + } } } @@ -333,7 +350,7 @@ GlobOpt::ProcessFieldKills(IR::Instr *instr, BVSparse *bv, bo case Js::OpCode::StElemI_A_Strict: Assert(dstOpnd != nullptr); KillLiveFields(this->lengthEquivBv, bv); - KillLiveElems(dstOpnd->AsIndirOpnd(), bv, inGlobOpt, instr->m_func); + KillLiveElems(dstOpnd->AsIndirOpnd(), instr->GetSrc1(), bv, inGlobOpt, instr->m_func); if (inGlobOpt) { KillObjectHeaderInlinedTypeSyms(this->currentBlock, false); @@ -343,7 +360,7 @@ GlobOpt::ProcessFieldKills(IR::Instr *instr, BVSparse *bv, bo case Js::OpCode::InitComputedProperty: case Js::OpCode::InitGetElemI: case Js::OpCode::InitSetElemI: - KillLiveElems(dstOpnd->AsIndirOpnd(), bv, inGlobOpt, instr->m_func); + KillLiveElems(dstOpnd->AsIndirOpnd(), instr->GetSrc1(), bv, inGlobOpt, instr->m_func); if (inGlobOpt) { KillObjectHeaderInlinedTypeSyms(this->currentBlock, false); @@ -353,7 +370,7 @@ GlobOpt::ProcessFieldKills(IR::Instr *instr, BVSparse *bv, bo case Js::OpCode::DeleteElemI_A: case Js::OpCode::DeleteElemIStrict_A: Assert(dstOpnd != nullptr); - KillLiveElems(instr->GetSrc1()->AsIndirOpnd(), bv, inGlobOpt, instr->m_func); + KillLiveElems(instr->GetSrc1()->AsIndirOpnd(), nullptr, bv, inGlobOpt, instr->m_func); break; case Js::OpCode::DeleteFld: