VYPR
High severityNVD Advisory· Published Jun 12, 2019· Updated May 20, 2025

Chakra Scripting Engine Memory Corruption Vulnerability

CVE-2019-1052

Description

A remote code execution vulnerability exists in the way that the Chakra scripting engine handles objects in memory in Microsoft Edge (HTML-based). The vulnerability could corrupt memory in such a way that an attacker could execute arbitrary code in the context of the current user. An attacker who successfully exploited the vulnerability could gain the same user rights as the current user. If the current user is logged on with administrative user rights, an attacker who successfully exploited the vulnerability could take control of an affected system. An attacker could then install programs; view, change, or delete data; or create new accounts with full user rights. In a web-based attack scenario, an attacker could host a specially crafted website that is designed to exploit the vulnerability through Microsoft Edge (HTML-based) and then convince a user to view the website. The attacker could also take advantage of compromised websites and websites that accept or host user-provided content or advertisements. These websites could contain specially crafted content that could exploit the vulnerability. The security update addresses the vulnerability by modifying how the Chakra scripting engine handles objects in memory.

AI Insight

LLM-synthesized narrative grounded in this CVE's description and references.

A remote code execution vulnerability in Microsoft Edge's Chakra scripting engine due to improper handling of objects in memory, allowing arbitrary code execution.

A remote code execution vulnerability exists in the way that the Chakra scripting engine handles objects in memory in Microsoft Edge (HTML-based). The vulnerability could corrupt memory in such a way that an attacker could execute arbitrary code in the context of the current user. The issue originates from improper handling of type specialization and array conversion in the ChakraCore JavaScript engine. Specifically, a flaw in GlobOpt::KillLiveElems could fail to properly kill field types when converting native arrays, allowing type confusion that leads to memory corruption [1][2].

In a web-based attack scenario, an attacker could host a specially crafted website designed to exploit the vulnerability through Microsoft Edge and then convince a user to view the website. The attacker could also take advantage of compromised websites and websites that accept or host user-provided content or advertisements [1]. The exploit does not require any special privileges beyond convincing the user to visit the malicious site, making it a significant client-side attack vector. The vulnerability can be triggered via JavaScript running in the browser, leading to exploitable memory corruption [3][4].

An attacker who successfully exploited the vulnerability could gain the same user rights as the current user. If the current user is logged on with administrative user rights, an attacker could take control of an affected system, install programs; view, change, or delete data; or create new accounts with full user rights [1]. This represents a complete compromise of confidentiality, integrity, and availability, with the impact scaling with the victim's privileges.

The security update addresses the vulnerability by modifying how the Chakra scripting engine handles objects in memory, specifically by improving the logic in GlobOpt::KillLiveElems to properly handle type specialization and array conversion scenarios [1][2]. Microsoft released a security update as part of its June 2019 Patch Tuesday. ChakraCore 1.11 also received a servicing update to fix this issue in the open-source engine [2]. Users should apply the latest Microsoft Edge updates and ensure ChakraCore is updated to the patched version.

AI Insight generated on May 22, 2026. Synthesized from this CVE's description and the cited reference URLs; citations are validated against the source bundle.

Affected packages

Versions sourced from the GitHub Security Advisory.

PackageAffected versionsPatched versions
Microsoft.ChakraCoreNuGet
< 1.11.101.11.10

Affected products

3

Patches

2
3d6226cc2d10

[MERGE #6155 @pleath] ChakraCore servicing update for June, 2019

https://github.com/chakra-core/ChakraCorePaul LeathersJun 11, 2019via ghsa
23 files changed · +430 74
  • Build/Common.Build.Default.props+1 0 modified
    @@ -17,6 +17,7 @@
         <PlatformToolset Condition="'$(BuildToolVersion)'=='12.0'">v120</PlatformToolset>
         <PlatformToolset Condition="'$(BuildToolVersion)'=='14.0'">v140</PlatformToolset>
         <PlatformToolset Condition="'$(BuildToolVersion)'=='15.0'">v141</PlatformToolset>
    +    <PlatformToolset Condition="'$(BuildToolVersion)'=='16.0'">v142</PlatformToolset>
       </PropertyGroup>
     
       <!-- Default ChakraDevConfigDir -->
    
  • Build/NuGet/.pack-version+1 1 modified
    @@ -1 +1 @@
    -1.11.9
    +1.11.10
    
  • lib/Backend/BackwardPass.cpp+75 4 modified
    @@ -1645,6 +1645,8 @@ BackwardPass::ProcessLoop(BasicBlock * lastBlock)
         {
             Assert(loop->symsAssignedToInLoop == nullptr);
             loop->symsAssignedToInLoop = JitAnew(this->globOpt->alloc, BVSparse<JitArenaAllocator>, this->globOpt->alloc);
    +        Assert(loop->preservesNumberValue == nullptr);
    +        loop->preservesNumberValue = JitAnew(this->globOpt->alloc, BVSparse<JitArenaAllocator>, this->globOpt->alloc);
         }
     
         FOREACH_BLOCK_BACKWARD_IN_RANGE_DEAD_OR_ALIVE(block, lastBlock, nullptr)
    @@ -4316,7 +4318,10 @@ BackwardPass::ProcessNoImplicitCallDef(IR::Instr *const instr)
         const bool transferArrayLengthSymUse = !!currentBlock->noImplicitCallArrayLengthSymUses->TestAndClear(dstSym->m_id);
     
         IR::Opnd *const src = instr->GetSrc1();
    -    if(!src || instr->GetSrc2())
    +
    +    // Stop attempting to transfer noImplicitCallUses symbol if the instr is not a transfer instr (based on the opcode's 
    +    // flags) or does not have the attributes to be a transfer instr (based on the existance of src and src2).
    +    if(!src || (instr->GetSrc2() && !OpCodeAttr::NonIntTransfer(instr->m_opcode)))
         {
             return;
         }
    @@ -5004,16 +5009,24 @@ BackwardPass::UpdateArrayBailOutKind(IR::Instr *const instr)
             return;
         }
     
    +    instr->GetDst()->AsIndirOpnd()->AllowConversion(true);
         IR::BailOutKind includeBailOutKinds = IR::BailOutInvalid;
         if (!baseValueType.IsNotNativeArray() &&
    -        (!baseValueType.IsLikelyNativeArray() || instr->GetSrc1()->IsVar()) &&
             !currentBlock->noImplicitCallNativeArrayUses->IsEmpty() &&
             !(instr->GetBailOutKind() & IR::BailOutOnArrayAccessHelperCall))
         {
             // There is an upwards-exposed use of a native array. Since the array referenced by this instruction can be aliased,
             // this instruction needs to bail out if it converts the native array even if this array specifically is not
             // upwards-exposed.
    -        includeBailOutKinds |= IR::BailOutConvertedNativeArray;
    +        if (!baseValueType.IsLikelyNativeArray() || instr->GetSrc1()->IsVar())
    +        {
    +            includeBailOutKinds |= IR::BailOutConvertedNativeArray;
    +        }
    +        else
    +        {
    +            // We are assuming that array conversion is impossible here, so make sure we execute code that fails if conversion does happen.
    +            instr->GetDst()->AsIndirOpnd()->AllowConversion(false);
    +        }
         }
     
         if(baseOpnd->IsArrayRegOpnd() && baseOpnd->AsArrayRegOpnd()->EliminatedUpperBoundCheck())
    @@ -7410,6 +7423,52 @@ BackwardPass::TrackFloatSymEquivalence(IR::Instr *const instr)
         }
     }
     
    +bool 
    +BackwardPass::SymIsIntconstOrSelf(Sym *sym, IR::Opnd *opnd)
    +{
    +    Assert(sym->IsStackSym());
    +    if (!opnd->IsRegOpnd())
    +    {
    +        return false;
    +    }
    +    StackSym *opndSym = opnd->AsRegOpnd()->m_sym;
    +
    +    if (sym == opndSym)
    +    {
    +        return true;
    +    }
    +
    +    if (!opndSym->IsSingleDef())
    +    {
    +        return false;
    +    }
    +
    +    if (opndSym->GetInstrDef()->m_opcode == Js::OpCode::LdC_A_I4)
    +    {
    +        return true;
    +    }
    +
    +    return false;
    +}
    +
    +bool
    +BackwardPass::InstrPreservesNumberValues(IR::Instr *instr, Sym *defSym)
    +{
    +    if (instr->m_opcode == Js::OpCode::Ld_A)
    +    {
    +        if (instr->GetSrc1()->IsRegOpnd())
    +        {
    +            IR::RegOpnd *src1 = instr->GetSrc1()->AsRegOpnd();
    +            if (src1->m_sym->IsSingleDef())
    +            {
    +                instr = src1->m_sym->GetInstrDef();
    +            }
    +        }
    +    }
    +    return (OpCodeAttr::ProducesNumber(instr->m_opcode) ||
    +        (instr->m_opcode == Js::OpCode::Add_A && this->SymIsIntconstOrSelf(defSym, instr->GetSrc1()) && this->SymIsIntconstOrSelf(defSym, instr->GetSrc2())));
    +}
    +
     bool
     BackwardPass::ProcessDef(IR::Opnd * opnd)
     {
    @@ -7424,7 +7483,19 @@ BackwardPass::ProcessDef(IR::Opnd * opnd)
                 this->InvalidateCloneStrCandidate(opnd);
                 if ((tag == Js::BackwardPhase) && IsPrePass())
                 {
    -                this->currentPrePassLoop->symsAssignedToInLoop->Set(sym->m_id);
    +                bool firstDef = !this->currentPrePassLoop->symsAssignedToInLoop->TestAndSet(sym->m_id);
    +
    +                if (firstDef)
    +                {
    +                    if (this->InstrPreservesNumberValues(this->currentInstr, sym))
    +                    {
    +                        this->currentPrePassLoop->preservesNumberValue->Set(sym->m_id);
    +                    }
    +                }
    +                else if (!this->InstrPreservesNumberValues(this->currentInstr, sym))
    +                {
    +                    this->currentPrePassLoop->preservesNumberValue->Clear(sym->m_id);
    +                }
                 }
             }
         }
    
  • lib/Backend/BackwardPass.h+3 0 modified
    @@ -36,6 +36,9 @@ class BackwardPass
         bool ProcessDef(IR::Opnd * opnd);
         void ProcessTransfers(IR::Instr * instr);
         void ProcessFieldKills(IR::Instr * instr);
    +    bool SymIsIntconstOrSelf(Sym *sym, IR::Opnd *opnd);
    +    bool InstrPreservesNumberValues(IR::Instr *instr, Sym *defSym);
    +
         template<typename T> void ClearBucketsOnFieldKill(IR::Instr *instr, HashTable<T> *table);
         StackSym* ProcessByteCodeUsesDst(IR::ByteCodeUsesInstr * byteCodeUsesInstr);
         const BVSparse<JitArenaAllocator>* ProcessByteCodeUsesSrcs(IR::ByteCodeUsesInstr * byteCodeUsesInstr);
    
  • lib/Backend/FlowGraph.h+2 0 modified
    @@ -588,6 +588,7 @@ class Loop
         // cleanup in PreOptPeep in the pre-pass of a loop. For aggressively transferring
         // values in prepass, we need to know if a source sym was ever assigned to in a loop.
         BVSparse<JitArenaAllocator> *symsAssignedToInLoop;
    +    BVSparse<JitArenaAllocator> *preservesNumberValue;
     
         BailOutInfo *       bailOutInfo;
         IR::BailOutInstr *  toPrimitiveSideEffectCheck;
    @@ -733,6 +734,7 @@ class Loop
             symsAssignedToInLoop(nullptr),
             needImplicitCallBailoutChecksForJsArrayCheckHoist(false),
             inductionVariables(nullptr),
    +        preservesNumberValue(nullptr),
             dominatingLoopCountableBlock(nullptr),
             loopCount(nullptr),
             loopCountBasedBoundBaseSyms(nullptr),
    
  • lib/Backend/GlobOpt.cpp+68 1 modified
    @@ -1244,7 +1244,7 @@ void GlobOpt::InsertValueCompensation(
             {
                 IR::Instr *const newInstr =
                     IR::Instr::New(
    -                    Js::OpCode::Ld_I4,
    +                    Js::OpCode::Ld_A,
                         IR::RegOpnd::New(mergedHeadSegmentLengthSym, mergedHeadSegmentLengthSym->GetType(), func),
                         IR::RegOpnd::New(predecessorHeadSegmentLengthSym, predecessorHeadSegmentLengthSym->GetType(), func),
                         func);
    @@ -2694,6 +2694,48 @@ GlobOpt::OptInstr(IR::Instr *&instr, bool* isInstrRemoved)
         return instrNext;
     }
     
    +bool
    +GlobOpt::IsNonNumericRegOpnd(IR::RegOpnd *opnd, bool inGlobOpt) const
    +{
    +    if (opnd == nullptr)
    +    {
    +        return false;
    +    }
    +
    +    if (opnd->m_sym->m_isNotNumber)
    +    {
    +        return true;
    +    }
    +
    +    if (!inGlobOpt)
    +    {
    +        return false;
    +    }
    +
    +    if (opnd->GetValueType().IsNumber() || currentBlock->globOptData.IsTypeSpecialized(opnd->m_sym))
    +    {
    +        if (!this->IsLoopPrePass())
    +        {
    +            return false;
    +        }
    +
    +        Value * opndValue = this->currentBlock->globOptData.FindValue(opnd->m_sym);
    +        ValueInfo * opndValueInfo = opndValue ? opndValue->GetValueInfo() : nullptr;
    +        if (!opndValueInfo)
    +        {
    +            return true;
    +        }
    +        if (this->prePassLoop->preservesNumberValue->Test(opnd->m_sym->m_id))
    +        {
    +            return false;
    +        }
    +
    +        return !this->IsSafeToTransferInPrepass(opnd->m_sym, opndValueInfo);
    +    }
    +
    +    return true;
    +}
    +
     bool
     GlobOpt::OptTagChecks(IR::Instr *instr)
     {
    @@ -12827,6 +12869,26 @@ GlobOpt::ProcessValueKills(IR::Instr *const instr)
                 it.RemoveCurrent();
             }
         }
    +    else if(kills.KillsObjectArraysWithNoMissingValues())
    +    {
    +        // Some operations may kill objects with arrays-with-no-missing-values in unlikely circumstances. Convert their value types to likely
    +        // versions so that the checks have to be redone.
    +        for(auto it = valuesToKillOnCalls->GetIteratorWithRemovalSupport(); it.IsValid(); it.MoveNext())
    +        {
    +            Value *const value = it.CurrentValue();
    +            ValueInfo *const valueInfo = value->GetValueInfo();
    +            Assert(
    +                valueInfo->IsArrayOrObjectWithArray() ||
    +                valueInfo->IsOptimizedVirtualTypedArray() ||
    +                valueInfo->IsOptimizedTypedArray() && valueInfo->AsArrayValueInfo()->HeadSegmentLengthSym());
    +            if(!valueInfo->IsArrayOrObjectWithArray() || valueInfo->IsArray() || !valueInfo->HasNoMissingValues())
    +            {
    +                continue;
    +            }
    +            ChangeValueType(nullptr, value, valueInfo->Type().ToLikely(), false);
    +            it.RemoveCurrent();
    +        }
    +    }
     
         if(kills.KillsNativeArrays())
         {
    @@ -13358,6 +13420,11 @@ GlobOpt::CheckJsArrayKills(IR::Instr *const instr)
                 {
                     kills.SetKillsArrayLengths();
                 }
    +
    +            if(doArrayMissingValueCheckHoist && !(useValueTypes && arrayValueType.IsArray()))
    +            {
    +                kills.SetKillsObjectArraysWithNoMissingValues();
    +            }
                 break;
             }
     
    
  • lib/Backend/GlobOptFields.cpp+22 12 modified
    @@ -208,7 +208,7 @@ void GlobOpt::KillLiveFields(BVSparse<JitArenaAllocator> *const fieldsToKill, BV
     }
     
     void
    -GlobOpt::KillLiveElems(IR::IndirOpnd * indirOpnd, BVSparse<JitArenaAllocator> * bv, bool inGlobOpt, Func *func)
    +GlobOpt::KillLiveElems(IR::IndirOpnd * indirOpnd, IR::Opnd * valueOpnd, BVSparse<JitArenaAllocator> * bv, bool inGlobOpt, Func *func)
     {
         IR::RegOpnd *indexOpnd = indirOpnd->GetIndexOpnd();
     
    @@ -225,14 +225,7 @@ GlobOpt::KillLiveElems(IR::IndirOpnd * indirOpnd, BVSparse<JitArenaAllocator> *
         // - 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() ||
    -        (
    -            indexOpnd &&
    -            (
    -                indexOpnd->m_sym->m_isNotNumber ||
    -                (inGlobOpt && !indexOpnd->GetValueType().IsNumber() && !currentBlock->globOptData.IsTypeSpecialized(indexOpnd->m_sym))
    -            )
    -        ))
    +    if (func->GetThisOrParentInlinerHasArguments() || this->IsNonNumericRegOpnd(indexOpnd, inGlobOpt))
         {
             this->KillAllFields(bv); // This also kills all property type values, as the same bit-vector tracks those stack syms
             SetAnyPropertyMayBeWrittenTo();
    @@ -248,6 +241,23 @@ GlobOpt::KillLiveElems(IR::IndirOpnd * indirOpnd, BVSparse<JitArenaAllocator> *
                 // 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<JitArenaAllocator>, this->alloc);
    +                }
    +                this->currentBlock->globOptData.maybeWrittenTypeSyms->Or(this->objectTypeSyms);
    +            }
    +        }
         }
     }
     
    @@ -340,7 +350,7 @@ GlobOpt::ProcessFieldKills(IR::Instr *instr, BVSparse<JitArenaAllocator> *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);
    @@ -350,7 +360,7 @@ GlobOpt::ProcessFieldKills(IR::Instr *instr, BVSparse<JitArenaAllocator> *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);
    @@ -360,7 +370,7 @@ GlobOpt::ProcessFieldKills(IR::Instr *instr, BVSparse<JitArenaAllocator> *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:
    
  • lib/Backend/GlobOpt.h+7 1 modified
    @@ -317,6 +317,7 @@ class JsArrayKills
             {
                 bool killsAllArrays : 1;
                 bool killsArraysWithNoMissingValues : 1;
    +            bool killsObjectArraysWithNoMissingValues : 1;
                 bool killsNativeArrays : 1;
                 bool killsArrayHeadSegments : 1;
                 bool killsArrayHeadSegmentLengths : 1;
    @@ -342,6 +343,9 @@ class JsArrayKills
         bool KillsArraysWithNoMissingValues() const { return killsArraysWithNoMissingValues; }
         void SetKillsArraysWithNoMissingValues() { killsArraysWithNoMissingValues = true; }
     
    +    bool KillsObjectArraysWithNoMissingValues() const { return killsObjectArraysWithNoMissingValues; }
    +    void SetKillsObjectArraysWithNoMissingValues() { killsObjectArraysWithNoMissingValues = true; }
    +
         bool KillsNativeArrays() const { return killsNativeArrays; }
         void SetKillsNativeArrays() { killsNativeArrays = true; }
     
    @@ -769,6 +773,8 @@ class GlobOpt
                                                     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;
    +
     public:
         static bool             IsTypeSpecPhaseOff(Func const * func);
         static bool             DoAggressiveIntTypeSpec(Func const * func);
    @@ -891,7 +897,7 @@ class GlobOpt
         void                    KillLiveFields(StackSym * stackSym, BVSparse<JitArenaAllocator> * bv);
         void                    KillLiveFields(PropertySym * propertySym, BVSparse<JitArenaAllocator> * bv);
         void                    KillLiveFields(BVSparse<JitArenaAllocator> *const fieldsToKill, BVSparse<JitArenaAllocator> *const bv) const;
    -    void                    KillLiveElems(IR::IndirOpnd * indirOpnd, BVSparse<JitArenaAllocator> * bv, bool inGlobOpt, Func *func);
    +    void                    KillLiveElems(IR::IndirOpnd * indirOpnd, IR::Opnd * valueOpnd, BVSparse<JitArenaAllocator> * bv, bool inGlobOpt, Func *func);
         void                    KillAllFields(BVSparse<JitArenaAllocator> * bv);
         void                    SetAnyPropertyMayBeWrittenTo();
         void                    AddToPropertiesWrittenTo(Js::PropertyId propertyId);
    
  • lib/Backend/InductionVariable.cpp+34 0 modified
    @@ -81,6 +81,21 @@ bool InductionVariable::Add(const int n)
         if(n == 0)
             return true;
     
    +    int lowerBound = changeBounds.LowerBound();
    +    int upperBound = changeBounds.UpperBound();
    +
    +    if (n < 0 && (lowerBound < upperBound || (lowerBound == upperBound && lowerBound > 0)))
    +    {
    +        isChangeDeterminate = false;
    +        return false;
    +    }
    +
    +    if (n > 0 && (lowerBound > upperBound || (lowerBound == upperBound && lowerBound < 0)))
    +    {
    +        isChangeDeterminate = false;
    +        return false;
    +    }
    +
         int newLowerBound;
         if(changeBounds.LowerBound() == IntConstMin)
         {
    @@ -148,6 +163,25 @@ void InductionVariable::Merge(const InductionVariable &other)
         // The value number may be different, the caller will give the merged info the appropriate value number
     
         isChangeDeterminate &= other.isChangeDeterminate;
    +    if(!isChangeDeterminate)
    +        return;
    +
    +    int lowerBound = this->ChangeBounds().LowerBound();
    +    int upperBound = this->ChangeBounds().UpperBound();
    +
    +    int otherLowerBound = other.ChangeBounds().LowerBound();
    +    int otherUpperBound = other.ChangeBounds().UpperBound();
    +
    +    if ((lowerBound < upperBound || (lowerBound == upperBound && lowerBound > 0)) && !(otherLowerBound < otherUpperBound || (otherLowerBound == otherUpperBound && otherLowerBound > 0)))
    +    {
    +        isChangeDeterminate = false;
    +    }
    +
    +    if ((lowerBound > upperBound || (lowerBound == upperBound && lowerBound < 0)) && !(otherLowerBound > otherUpperBound || (otherLowerBound == otherUpperBound && otherLowerBound < 0)))
    +    {
    +        isChangeDeterminate = false;
    +    }
    +
         if(!isChangeDeterminate)
             return;
     
    
  • lib/Backend/Inline.cpp+21 18 modified
    @@ -69,7 +69,7 @@ Inline::Optimize(Func *func, __in_ecount_opt(callerArgOutCount) IR::Instr *calle
     
                         if (instr->AsLabelInstr()->m_isForInExit)
                         {
    -                        Assert(this->currentForInDepth != 0);
    +                        AssertOrFailFast(this->currentForInDepth != 0);
                             this->currentForInDepth--;
                         }
                     }
    @@ -2158,14 +2158,12 @@ Inline::InlineBuiltInFunction(IR::Instr *callInstr, const FunctionJITTimeInfo *
         IR::Instr *inlineBuiltInEndInstr = nullptr;
         if (inlineCallOpCode ==  Js::OpCode::InlineFunctionApply)
         {
    -       inlineBuiltInEndInstr = InlineApply(callInstr, inlineeData, inlinerData, symCallerThis, pIsInlined, profileId, recursiveInlineDepth, inlineCallArgCount - (usesThisArgument ? 1 : 0));
    -       return inlineBuiltInEndInstr->m_next;
    +        return InlineApply(callInstr, inlineeData, inlinerData, symCallerThis, pIsInlined, profileId, recursiveInlineDepth, inlineCallArgCount - (usesThisArgument ? 1 : 0));
         }
     
         if (inlineCallOpCode ==  Js::OpCode::InlineFunctionCall)
         {
    -       inlineBuiltInEndInstr = InlineCall(callInstr, inlineeData, inlinerData, symCallerThis, pIsInlined, profileId, recursiveInlineDepth);
    -       return inlineBuiltInEndInstr->m_next;
    +        return InlineCall(callInstr, inlineeData, inlinerData, symCallerThis, pIsInlined, profileId, recursiveInlineDepth);
         }
     
     
    @@ -2415,9 +2413,10 @@ IR::Instr* Inline::InlineApply(IR::Instr *callInstr, const FunctionJITTimeInfo *
         // We may still decide not to inline.
         *pIsInlined = false;
     
    +    IR::Instr* instrNext = callInstr->m_next;
         if (argsCount == 0)
         {
    -        return callInstr;
    +        return instrNext;
         }
     
         Js::BuiltinFunction builtInId = Js::JavascriptLibrary::GetBuiltInForFuncInfo(applyData->GetLocalFunctionId());
    @@ -2459,7 +2458,7 @@ IR::Instr* Inline::InlineApply(IR::Instr *callInstr, const FunctionJITTimeInfo *
             if (PHASE_OFF1(Js::InlineApplyWithoutArrayArgPhase))
             {
                 *pIsInlined = false;
    -            return callInstr;
    +            return instrNext;
             }
             *pIsInlined = true;
     
    @@ -2490,7 +2489,7 @@ IR::Instr* Inline::InlineApply(IR::Instr *callInstr, const FunctionJITTimeInfo *
             {
                 INLINE_TESTTRACE(_u("INLINING: Skip Inline: Supporting inlining func.apply(this, array) or func.apply(this, arguments) with formals in the parent function only when func is a built-in inlinable as apply target \tCaller: %s (%s)\n"),
                     inlinerData->GetBody()->GetDisplayName(), inlinerData->GetDebugNumberSet(debugStringBuffer));
    -            return callInstr;
    +            return instrNext;
             }
         }
     
    @@ -2506,6 +2505,7 @@ IR::Instr* Inline::InlineApply(IR::Instr *callInstr, const FunctionJITTimeInfo *
     
     IR::Instr * Inline::InlineApplyWithArgumentsObject(IR::Instr * callInstr, IR::Instr * argsObjectArgInstr, const FunctionJITTimeInfo * funcInfo)
     {
    +    IR::Instr* instrNext = callInstr->m_next;
         IR::Instr* ldHeapArguments = argsObjectArgInstr->GetSrc1()->GetStackSym()->GetInstrDef();
         argsObjectArgInstr->ReplaceSrc1(ldHeapArguments->GetDst());
     
    @@ -2595,14 +2595,15 @@ IR::Instr * Inline::InlineApplyWithArgumentsObject(IR::Instr * callInstr, IR::In
     
         argout = IR::Instr::New(Js::OpCode::ArgOut_A_Dynamic, linkOpnd2, explicitThisArgOut->GetSrc1(), linkOpnd1, callInstr->m_func); // push explicit this as this pointer
         callInstr->InsertBefore(argout);
    -    return callInstr;
    +    return instrNext;
     }
     
     /*
     This method will only do CallDirect style inlining of built-in targets. No script function inlining.
     */
     IR::Instr * Inline::InlineApplyBuiltInTargetWithArray(IR::Instr * callInstr, const FunctionJITTimeInfo * applyInfo, const FunctionJITTimeInfo * builtInInfo)
     {
    +    IR::Instr* instrNext = callInstr->m_next;
         IR::Instr * implicitThisArgOut = nullptr;
         IR::Instr * explicitThisArgOut = nullptr;
         IR::Instr * arrayArgOut = nullptr;
    @@ -2620,7 +2621,7 @@ IR::Instr * Inline::InlineApplyBuiltInTargetWithArray(IR::Instr * callInstr, con
         IR::Instr* applyTargetLdInstr = nullptr;
         if (!TryGetApplyAndTargetLdInstrs(callInstr, &applyLdInstr, &applyTargetLdInstr))
         {
    -        return callInstr;
    +        return instrNext;
         }
         // Fixed function/function object checks for target built-in
         callInstr->ReplaceSrc1(applyTargetLdInstr->GetDst());
    @@ -2685,11 +2686,12 @@ IR::Instr * Inline::InlineApplyBuiltInTargetWithArray(IR::Instr * callInstr, con
         callInstr->ReplaceSrc1(helperCallOpnd);
         callInstr->ReplaceSrc2(argOut->GetDst());
     
    -    return callInstr;
    +    return instrNext;
     }
     
     IR::Instr * Inline::InlineApplyWithoutArrayArgument(IR::Instr *callInstr, const FunctionJITTimeInfo * applyInfo, const FunctionJITTimeInfo * applyTargetInfo)
     {
    +    IR::Instr* instrNext = callInstr->m_next;
         IR::Instr * implicitThisArgOut = nullptr;
         IR::Instr * explicitThisArgOut = nullptr;
         IR::Instr * dummyInstr = nullptr;
    @@ -2728,12 +2730,12 @@ IR::Instr * Inline::InlineApplyWithoutArrayArgument(IR::Instr *callInstr, const
     
         if (!callTargetStackSym->IsSingleDef())
         {
    -        return callInstr;
    +        return instrNext;
         }
     
         if (!applyTargetInfo)
         {
    -        return callInstr;
    +        return instrNext;
         }
     
         bool safeThis = false;
    @@ -2745,7 +2747,7 @@ IR::Instr * Inline::InlineApplyWithoutArrayArgument(IR::Instr *callInstr, const
             callInstr->InsertBefore(bytecodeUses);
         }
     
    -    return callInstr;
    +    return instrNext;
     }
     
     void Inline::GetArgInstrsForCallAndApply(IR::Instr* callInstr, IR::Instr** implicitThisArgOut, IR::Instr** explicitThisArgOut, IR::Instr** argumentsOrArrayArgOut, uint &argOutCount)
    @@ -3015,7 +3017,7 @@ Inline::InlineCallApplyTarget_Shared(IR::Instr *callInstr, bool originalCallTarg
         // instrNext
         IR::Instr* instrNext = callInstr->m_next;
     
    -    return InlineFunctionCommon(callInstr, originalCallTargetOpndIsJITOpt, originalCallTargetStackSym, inlineeData, inlinee, instrNext, returnValueOpnd, callInstr, nullptr, recursiveInlineDepth, safeThis, isApplyTarget)->m_prev;
    +    return InlineFunctionCommon(callInstr, originalCallTargetOpndIsJITOpt, originalCallTargetStackSym, inlineeData, inlinee, instrNext, returnValueOpnd, callInstr, nullptr, recursiveInlineDepth, safeThis, isApplyTarget);
     }
     
     IR::Opnd *
    @@ -3029,14 +3031,15 @@ Inline::ConvertToInlineBuiltInArgOut(IR::Instr * argInstr)
     IR::Instr*
     Inline::InlineCall(IR::Instr *callInstr, const FunctionJITTimeInfo *funcInfo, const FunctionJITTimeInfo * inlinerData, const StackSym *symCallerThis, bool* pIsInlined, uint callSiteId, uint recursiveInlineDepth)
     {
    +    IR::Instr* instrNext = callInstr->m_next;
         Func *func = callInstr->m_func;
         Js::BuiltinFunction builtInId = Js::JavascriptLibrary::GetBuiltInForFuncInfo(funcInfo->GetLocalFunctionId());
     
         *pIsInlined = false;
         if (PHASE_OFF(Js::InlineCallPhase, this->topFunc) || PHASE_OFF(Js::InlineCallPhase, func)
             || !this->topFunc->GetJITFunctionBody()->GetInParamsCount())
         {
    -        return callInstr;
    +        return instrNext;
         }
     
         // Convert all the current ARG_OUT to  ArgOut_A_InlineBuiltIn
    @@ -3045,7 +3048,7 @@ Inline::InlineCall(IR::Instr *callInstr, const FunctionJITTimeInfo *funcInfo, co
         if (!GetDefInstr(linkOpnd)->GetSrc2()->IsSymOpnd())
         {
             // There is no benefit of inlining.call() with no arguments.
    -        return callInstr;
    +        return instrNext;
         }
     
         *pIsInlined = true;
    @@ -3125,7 +3128,7 @@ Inline::InlineCall(IR::Instr *callInstr, const FunctionJITTimeInfo *funcInfo, co
         }
         clonedArgout->SetSrc2(startCall->GetDst());
         Assert(GetDefInstr(orgLinkOpnd) == argImplicitInstr);
    -    return callInstr;
    +    return instrNext;
     }
     
     bool
    
  • lib/Backend/IR.cpp+8 1 modified
    @@ -3307,7 +3307,14 @@ bool Instr::TransfersSrcValue()
     
         // Consider: Add opcode attribute to indicate whether the opcode would use the value or not
     
    -    return this->GetDst() != nullptr && this->GetSrc2() == nullptr && !OpCodeAttr::DoNotTransfer(this->m_opcode) && !this->CallsAccessor();
    +    return
    +        this->GetDst() != nullptr &&
    +
    +        // The lack of a Src2 does not always indicate that the instr is not a transfer instr (ex: StSlotChkUndecl).
    +        (this->GetSrc2() == nullptr || OpCodeAttr::NonIntTransfer(this->m_opcode)) &&
    +
    +        !OpCodeAttr::DoNotTransfer(this->m_opcode) &&
    +        !this->CallsAccessor();
     }
     
     
    
  • lib/Backend/JnHelperMethodList.h+6 0 modified
    @@ -205,6 +205,12 @@ HELPERCALLCHK(Op_SetNativeIntElementI_Int32, Js::JavascriptOperators::OP_SetNati
     HELPERCALLCHK(Op_SetNativeFloatElementI_Int32, Js::JavascriptOperators::OP_SetNativeFloatElementI_Int32, AttrCanThrow)
     HELPERCALLCHK(Op_SetNativeIntElementI_UInt32, Js::JavascriptOperators::OP_SetNativeIntElementI_UInt32, AttrCanThrow)
     HELPERCALLCHK(Op_SetNativeFloatElementI_UInt32, Js::JavascriptOperators::OP_SetNativeFloatElementI_UInt32, AttrCanThrow)
    +HELPERCALLCHK(Op_SetNativeIntElementI_NoConvert, Js::JavascriptOperators::OP_SetNativeIntElementI_NoConvert, AttrCanThrow)
    +HELPERCALLCHK(Op_SetNativeFloatElementI_NoConvert, Js::JavascriptOperators::OP_SetNativeFloatElementI_NoConvert, AttrCanThrow)
    +HELPERCALLCHK(Op_SetNativeIntElementI_Int32_NoConvert, Js::JavascriptOperators::OP_SetNativeIntElementI_Int32_NoConvert, AttrCanThrow)
    +HELPERCALLCHK(Op_SetNativeFloatElementI_Int32_NoConvert, Js::JavascriptOperators::OP_SetNativeFloatElementI_Int32_NoConvert, AttrCanThrow)
    +HELPERCALLCHK(Op_SetNativeIntElementI_UInt32_NoConvert, Js::JavascriptOperators::OP_SetNativeIntElementI_UInt32_NoConvert, AttrCanThrow)
    +HELPERCALLCHK(Op_SetNativeFloatElementI_UInt32_NoConvert, Js::JavascriptOperators::OP_SetNativeFloatElementI_UInt32_NoConvert, AttrCanThrow)
     HELPERCALLCHK(ScrArr_SetNativeIntElementC, Js::JavascriptArray::OP_SetNativeIntElementC, AttrCanNotBeReentrant)
     HELPERCALLCHK(ScrArr_SetNativeFloatElementC, Js::JavascriptArray::OP_SetNativeFloatElementC, AttrCanNotBeReentrant)
     HELPERCALLCHK(Op_DeleteElementI, Js::JavascriptOperators::OP_DeleteElementI, AttrCanThrow)
    
  • lib/Backend/Lower.cpp+11 6 modified
    @@ -9001,6 +9001,8 @@ Lowerer::LowerStElemI(IR::Instr * instr, Js::PropertyOperationFlags flags, bool
     
         AssertMsg(dst->IsIndirOpnd(), "Expected indirOpnd on StElementI");
     
    +    bool allowConvert = dst->AsIndirOpnd()->ConversionAllowed();
    +
     #if !FLOATVAR
         if (dst->AsIndirOpnd()->GetBaseOpnd()->GetValueType().IsLikelyOptimizedTypedArray() && src1->IsRegOpnd())
         {
    @@ -9085,15 +9087,17 @@ Lowerer::LowerStElemI(IR::Instr * instr, Js::PropertyOperationFlags flags, bool
             {
                 helperMethod =
                     srcType == TyVar ? IR::HelperOp_SetElementI_Int32 :
    -                srcType == TyInt32 ? IR::HelperOp_SetNativeIntElementI_Int32 :
    -                IR::HelperOp_SetNativeFloatElementI_Int32;
    +                srcType == TyInt32 ? 
    +                    (allowConvert ? IR::HelperOp_SetNativeIntElementI_Int32 : IR::HelperOp_SetNativeIntElementI_Int32_NoConvert) :
    +                    (allowConvert ? IR::HelperOp_SetNativeFloatElementI_Int32 : IR::HelperOp_SetNativeFloatElementI_Int32_NoConvert) ;
             }
             else if (indexOpnd->GetType() == TyUint32)
             {
                 helperMethod =
                     srcType == TyVar ? IR::HelperOp_SetElementI_UInt32 :
    -                srcType == TyInt32 ? IR::HelperOp_SetNativeIntElementI_UInt32 :
    -                IR::HelperOp_SetNativeFloatElementI_UInt32;
    +                srcType == TyInt32 ? 
    +                    (allowConvert ? IR::HelperOp_SetNativeIntElementI_UInt32 : IR::HelperOp_SetNativeIntElementI_UInt32_NoConvert) :
    +                    (allowConvert ? IR::HelperOp_SetNativeFloatElementI_UInt32 : IR::HelperOp_SetNativeFloatElementI_UInt32_NoConvert) ;
             }
             else
             {
    @@ -9111,8 +9115,9 @@ Lowerer::LowerStElemI(IR::Instr * instr, Js::PropertyOperationFlags flags, bool
     
             if (srcType != TyVar)
             {
    -            helperMethod =
    -                srcType == TyInt32 ? IR::HelperOp_SetNativeIntElementI : IR::HelperOp_SetNativeFloatElementI;
    +            helperMethod = srcType == TyInt32 ? 
    +                (allowConvert ? IR::HelperOp_SetNativeIntElementI : IR::HelperOp_SetNativeIntElementI_NoConvert) : 
    +                (allowConvert ? IR::HelperOp_SetNativeFloatElementI : IR::HelperOp_SetNativeFloatElementI_NoConvert);
             }
         }
     
    
  • lib/Backend/Opnd.cpp+2 0 modified
    @@ -2538,6 +2538,7 @@ IndirOpnd::New(RegOpnd *baseOpnd, int32 offset, IRType type, Func *func, bool do
         indirOpnd->m_type = type;
         indirOpnd->SetIsJITOptimizedReg(false);
     
    +    indirOpnd->m_conversionAllowed = false;
     
         indirOpnd->m_kind = OpndKindIndir;
     
    @@ -2596,6 +2597,7 @@ IndirOpnd::CopyInternal(Func *func)
         newOpnd->canStoreTemp = this->canStoreTemp;
         newOpnd->SetOffset(m_offset, m_dontEncode);
         newOpnd->SetIsJITOptimizedReg(this->GetIsJITOptimizedReg());
    +    newOpnd->m_conversionAllowed = this->m_conversionAllowed;
     
     #if DBG_DUMP
         newOpnd->m_addrKind = m_addrKind;
    
  • lib/Backend/Opnd.h+3 0 modified
    @@ -1662,6 +1662,8 @@ class IndirOpnd: public Opnd
         byte                    GetScale() const;
         void                    SetScale(byte scale);
         bool                    TryGetIntConstIndexValue(bool trySym, IntConstType *pValue, bool *pIsNotInt);
    +    void                    AllowConversion(bool value) { m_conversionAllowed = value; }
    +    bool                    ConversionAllowed() const   { return m_conversionAllowed; }
     #if DBG_DUMP || defined(ENABLE_IR_VIEWER)
         const char16 *         GetDescription();
         IR::AddrOpndKind        GetAddrKind() const;
    @@ -1678,6 +1680,7 @@ class IndirOpnd: public Opnd
         RegOpnd *               m_indexOpnd;
         int32                   m_offset;
         byte                    m_scale;
    +    bool                    m_conversionAllowed;
         Func *                  m_func;  // We need the allocator to copy the base and index...
     
     #if DBG_DUMP || defined(ENABLE_IR_VIEWER)
    
  • lib/Common/ChakraCoreVersion.h+1 1 modified
    @@ -17,7 +17,7 @@
     // ChakraCore version number definitions (used in ChakraCore binary metadata)
     #define CHAKRA_CORE_MAJOR_VERSION 1
     #define CHAKRA_CORE_MINOR_VERSION 11
    -#define CHAKRA_CORE_PATCH_VERSION 9
    +#define CHAKRA_CORE_PATCH_VERSION 10
     #define CHAKRA_CORE_VERSION_RELEASE_QFE 0 // Redundant with PATCH_VERSION. Keep this value set to 0.
     
     // -------------
    
  • lib/Parser/Parse.cpp+0 14 modified
    @@ -5444,20 +5444,6 @@ void Parser::ParseFncDeclHelper(ParseNodeFnc * pnodeFnc, LPCOLESTR pNameHint, us
                         }
                         return false;
                     });
    -
    -                if (pnodeFnc->IsBodyAndParamScopeMerged() && !fDeclaration && pnodeFnc->pnodeName != nullptr)
    -                {
    -                    Assert(pnodeFnc->pnodeName->nop == knopVarDecl);
    -                    Symbol* funcSym = pnodeFnc->pnodeName->sym;
    -                    if (funcSym->GetPid()->GetTopRef()->GetFuncScopeId() > pnodeFnc->functionId)
    -                    {
    -                        // This is a function expression with name captured in the param scope. In non-eval, non-split cases the function
    -                        // name symbol is added to the body scope to make it accessible in the body. But if there is a function or var
    -                        // declaration with the same name in the body then adding to the body will fail. So in this case we have to add
    -                        // the name symbol to the param scope by splitting it.
    -                        pnodeFnc->ResetBodyAndParamScopeMerged();
    -                    }
    -                }
                 }
             }
     
    
  • lib/Runtime/ByteCode/ByteCodeGenerator.cpp+11 0 modified
    @@ -3091,6 +3091,17 @@ void ByteCodeGenerator::ProcessCapturedSym(Symbol *sym)
     
         Assert(sym->NeedsSlotAlloc(this, funcHome) || sym->GetIsGlobal() || sym->GetIsModuleImport() || sym->GetIsModuleExportStorage());
     
    +    if (sym->GetScope()->GetScopeType() == ScopeType_FuncExpr)
    +    {
    +        if ((funcHome->GetParamScope() && Scope::HasSymbolName(funcHome->GetParamScope(), sym->GetName())) ||
    +            (funcHome->IsBodyAndParamScopeMerged() && funcHome->GetBodyScope() && Scope::HasSymbolName(funcHome->GetBodyScope(), sym->GetName())))
    +        {
    +            // Make sure the function expression scope gets instantiated, since we can't merge the name symbol into another scope.
    +            // Make it an object, since that's the only case the code gen can currently handle.
    +            sym->GetScope()->SetIsObject();
    +        }
    +    }
    +
         // If this is not a local property, or not all its references can be tracked, or
         // it's not scoped to the function, or we're in debug mode, disable the delayed capture optimization.
         if (funcHome->IsGlobalFunction() ||
    
  • lib/Runtime/ByteCode/OpCodes.h+10 10 modified
    @@ -464,21 +464,21 @@ MACRO_WMS(              StEnvSlot,                  ElementSlotI2,  None)
     MACRO_WMS(              StInnerSlot,                ElementSlotI2,  None)
     MACRO_WMS(              StLocalSlot,                ElementSlotI1,  None)
     MACRO_EXTEND_WMS(       StParamSlot,                ElementSlotI1,  None)
    -MACRO_BACKEND_ONLY(     StSlotChkUndecl,            ElementSlot,    OpSideEffect)
    -MACRO_EXTEND_WMS(       StEnvSlotChkUndecl,         ElementSlotI2,  OpSideEffect)
    -MACRO_EXTEND_WMS(       StInnerSlotChkUndecl,       ElementSlotI2,  OpSideEffect)
    -MACRO_EXTEND_WMS(       StLocalSlotChkUndecl,       ElementSlotI1,  OpSideEffect)
    -MACRO_EXTEND_WMS(       StParamSlotChkUndecl,       ElementSlotI1,  OpSideEffect)
    +MACRO_BACKEND_ONLY(     StSlotChkUndecl,            ElementSlot,    OpSideEffect|OpNonIntTransfer) // Src1 is transferred to Dst, Src2 holds the same value as Dst to communicate Dst's liveness.
    +MACRO_EXTEND_WMS(       StEnvSlotChkUndecl,         ElementSlotI2,  OpSideEffect|OpNonIntTransfer)
    +MACRO_EXTEND_WMS(       StInnerSlotChkUndecl,       ElementSlotI2,  OpSideEffect|OpNonIntTransfer)
    +MACRO_EXTEND_WMS(       StLocalSlotChkUndecl,       ElementSlotI1,  OpSideEffect|OpNonIntTransfer)
    +MACRO_EXTEND_WMS(       StParamSlotChkUndecl,       ElementSlotI1,  OpSideEffect|OpNonIntTransfer)
     MACRO_EXTEND_WMS(       StObjSlot,                  ElementSlot,    OpSideEffect)
     MACRO_EXTEND_WMS(       StInnerObjSlot,             ElementSlotI2,  OpSideEffect)
     MACRO_EXTEND_WMS(       StLocalObjSlot,             ElementSlotI1,  OpSideEffect)
     MACRO_EXTEND_WMS(       StParamObjSlot,             ElementSlotI1,  OpSideEffect)
    -MACRO_EXTEND_WMS(       StLocalObjSlotChkUndecl,    ElementSlotI1,  OpSideEffect)
    -MACRO_EXTEND_WMS(       StParamObjSlotChkUndecl,    ElementSlotI1,  OpSideEffect)
    +MACRO_EXTEND_WMS(       StLocalObjSlotChkUndecl,    ElementSlotI1,  OpSideEffect|OpNonIntTransfer)
    +MACRO_EXTEND_WMS(       StParamObjSlotChkUndecl,    ElementSlotI1,  OpSideEffect|OpNonIntTransfer)
     MACRO_EXTEND_WMS(       StEnvObjSlot,               ElementSlotI2,  OpSideEffect)
    -MACRO_EXTEND_WMS(       StObjSlotChkUndecl,         ElementSlot,    OpSideEffect)
    -MACRO_EXTEND_WMS(       StInnerObjSlotChkUndecl,    ElementSlotI2,  OpSideEffect)
    -MACRO_EXTEND_WMS(       StEnvObjSlotChkUndecl,      ElementSlotI2,  OpSideEffect)
    +MACRO_EXTEND_WMS(       StObjSlotChkUndecl,         ElementSlot,    OpSideEffect|OpNonIntTransfer)
    +MACRO_EXTEND_WMS(       StInnerObjSlotChkUndecl,    ElementSlotI2,  OpSideEffect|OpNonIntTransfer)
    +MACRO_EXTEND_WMS(       StEnvObjSlotChkUndecl,      ElementSlotI2,  OpSideEffect|OpNonIntTransfer)
     MACRO_EXTEND_WMS(       StModuleSlot,               ElementSlotI2,  OpSideEffect)
     MACRO_BACKEND_ONLY(     LdAsmJsFunc,                ElementSlot,    OpTempNumberSources|OpCanCSE)
     MACRO_BACKEND_ONLY(     LdWasmFunc,                 ElementSlot,    OpSideEffect)
    
  • lib/Runtime/ByteCode/Scope.h+15 5 modified
    @@ -110,19 +110,28 @@ class Scope
             }
         }
     
    +    static bool HasSymbolName(Scope * scope, const JsUtil::CharacterBuffer<WCHAR>& name)
    +    {
    +        for (Symbol *sym = scope->m_symList; sym; sym = sym->GetNext())
    +        {
    +            if (sym->GetName() == name)
    +            {
    +                return true;
    +            }
    +        }
    +        return false;
    +    }
    +
         void AddSymbol(Symbol *sym)
         {
             if (enclosingScope == nullptr)
             {
                 sym->SetIsGlobal(true);
             }
             sym->SetScope(this);
    -        for (Symbol *symInList = m_symList; symInList; symInList = symInList->GetNext())
    +        if (HasSymbolName(this, sym->GetName()))
             {
    -            if (symInList->GetName() == sym->GetName())
    -            {
    -                return;
    -            }
    +            return;
             }
             sym->SetNext(m_symList);
             m_symList = sym;
    @@ -136,6 +145,7 @@ class Scope
                 sym->SetIsGlobal(true);
             }
             sym->SetScope(this);
    +        Assert(!HasSymbolName(this, sym->GetName()));
             sym->SetNext(m_symList);
             m_symList = sym;
             m_count++;
    
  • lib/Runtime/Language/JavascriptOperators.cpp+118 0 modified
    @@ -4644,6 +4644,120 @@ using namespace Js;
             return JavascriptOperators::SetProperty(receiver, object, propertyRecord->GetPropertyId(), value, scriptContext, flags);
         }
     
    +    BOOL JavascriptOperators::OP_SetNativeIntElementI_NoConvert(
    +        Var instance,
    +        Var aElementIndex,
    +        int32 iValue,
    +        ScriptContext* scriptContext,
    +        PropertyOperationFlags flags)
    +    {
    +        JIT_HELPER_REENTRANT_HEADER(Op_SetNativeIntElementI_NoConvert);
    +        JIT_HELPER_SAME_ATTRIBUTES(Op_SetNativeIntElementI_NoConvert, Op_SetNativeIntElementI);
    +        BOOL converted = OP_SetNativeIntElementI(instance, aElementIndex, iValue, scriptContext, flags);
    +        if (converted)
    +        {
    +            AssertMsg(false, "Unexpected native array conversion");
    +            Js::Throw::FatalInternalError();
    +        }
    +        return FALSE;
    +        JIT_HELPER_END(Op_SetNativeIntElementI_NoConvert);
    +    }
    +
    +    BOOL JavascriptOperators::OP_SetNativeIntElementI_UInt32_NoConvert(
    +        Var instance,
    +        uint32 aElementIndex,
    +        int32 iValue,
    +        ScriptContext* scriptContext,
    +        PropertyOperationFlags flags)
    +    {
    +        JIT_HELPER_REENTRANT_HEADER(Op_SetNativeIntElementI_UInt32_NoConvert);
    +        JIT_HELPER_SAME_ATTRIBUTES(Op_SetNativeIntElementI_UInt32_NoConvert, Op_SetNativeIntElementI_UInt32);
    +        BOOL converted = OP_SetNativeIntElementI_UInt32(instance, aElementIndex, iValue, scriptContext, flags);
    +        if (converted)
    +        {
    +            AssertMsg(false, "Unexpected native array conversion");
    +            Js::Throw::FatalInternalError();
    +        }
    +        return FALSE;
    +        JIT_HELPER_END(Op_SetNativeIntElementI_UInt32_NoConvert);
    +    }
    +
    +    BOOL JavascriptOperators::OP_SetNativeIntElementI_Int32_NoConvert(
    +        Var instance,
    +        int32 aElementIndex,
    +        int32 iValue,
    +        ScriptContext* scriptContext,
    +        PropertyOperationFlags flags)
    +    {
    +        JIT_HELPER_REENTRANT_HEADER(Op_SetNativeIntElementI_Int32_NoConvert);
    +        JIT_HELPER_SAME_ATTRIBUTES(Op_SetNativeIntElementI_Int32_NoConvert, Op_SetNativeIntElementI_Int32);
    +        BOOL converted = OP_SetNativeIntElementI_Int32(instance, aElementIndex, iValue, scriptContext, flags);
    +        if (converted)
    +        {
    +            AssertMsg(false, "Unexpected native array conversion");
    +            Js::Throw::FatalInternalError();
    +        }
    +        return FALSE;
    +        JIT_HELPER_END(Op_SetNativeIntElementI_Int32_NoConvert);
    +    }
    +
    +    BOOL JavascriptOperators::OP_SetNativeFloatElementI_NoConvert(
    +        Var instance,
    +        Var aElementIndex,
    +        ScriptContext* scriptContext,
    +        PropertyOperationFlags flags,
    +        double dValue)
    +    {
    +        JIT_HELPER_REENTRANT_HEADER(Op_SetNativeFloatElementI_NoConvert);
    +        JIT_HELPER_SAME_ATTRIBUTES(Op_SetNativeFloatElementI_NoConvert, Op_SetNativeFloatElementI);
    +        BOOL converted = OP_SetNativeFloatElementI(instance, aElementIndex, scriptContext, flags, dValue);
    +        if (converted)
    +        {
    +            AssertMsg(false, "Unexpected native array conversion");
    +            Js::Throw::FatalInternalError();
    +        }
    +        return FALSE;
    +        JIT_HELPER_END(Op_SetNativeFloatElementI_NoConvert);
    +    }
    +
    +    BOOL JavascriptOperators::OP_SetNativeFloatElementI_UInt32_NoConvert(
    +        Var instance,
    +        uint32 aElementIndex,
    +        ScriptContext* scriptContext,
    +        PropertyOperationFlags flags,
    +        double dValue)
    +    {
    +        JIT_HELPER_REENTRANT_HEADER(Op_SetNativeFloatElementI_UInt32_NoConvert);
    +        JIT_HELPER_SAME_ATTRIBUTES(Op_SetNativeFloatElementI_NoConvert, Op_SetNativeFloatElementI_UInt32);
    +        BOOL converted = OP_SetNativeFloatElementI_UInt32(instance, aElementIndex, scriptContext, flags, dValue);
    +        if (converted)
    +        {
    +            AssertMsg(false, "Unexpected native array conversion");
    +            Js::Throw::FatalInternalError();
    +        }
    +        return FALSE;
    +        JIT_HELPER_END(Op_SetNativeFloatElementI_UInt32_NoConvert);
    +    }
    +
    +    BOOL JavascriptOperators::OP_SetNativeFloatElementI_Int32_NoConvert(
    +        Var instance,
    +        int32 aElementIndex,
    +        ScriptContext* scriptContext,
    +        PropertyOperationFlags flags,
    +        double dValue)
    +    {
    +        JIT_HELPER_REENTRANT_HEADER(Op_SetNativeFloatElementI_Int32_NoConvert);
    +        JIT_HELPER_SAME_ATTRIBUTES(Op_SetNativeFloatElementI_NoConvert, Op_SetNativeFloatElementI_Int32);
    +        BOOL converted = OP_SetNativeFloatElementI_Int32(instance, aElementIndex, scriptContext, flags, dValue);
    +        if (converted)
    +        {
    +            AssertMsg(false, "Unexpected native array conversion");
    +            Js::Throw::FatalInternalError();
    +        }
    +        return FALSE;
    +        JIT_HELPER_END(Op_SetNativeFloatElementI_Int32_NoConvert);
    +    }
    +
         BOOL JavascriptOperators::OP_SetNativeIntElementI(
             Var instance,
             Var aElementIndex,
    @@ -9541,6 +9655,10 @@ using namespace Js;
                 Var result = CALL_ENTRYPOINT(threadContext, marshalledFunction->GetEntryPoint(), function, CallInfo(flags, 1), thisVar);
                 result = CrossSite::MarshalVar(requestContext, result);
     
    +            // Set implicit call flags so we bail out if we're trying to propagate the value forward, e.g., from a compare. Subsequent calls
    +            // to the getter may produce different results.
    +            threadContext->AddImplicitCallFlags(ImplicitCall_Accessor);
    +
                 return result;
             });
         }
    
  • lib/Runtime/Language/JavascriptOperators.h+6 0 modified
    @@ -392,6 +392,12 @@ namespace Js
             static BOOL OP_SetElementI_UInt32(Var instance, uint32 aElementIndex, Var aValue, ScriptContext* scriptContext, PropertyOperationFlags flags = PropertyOperation_None);
             static BOOL OP_SetElementI_Int32(Var instance, int32 aElementIndex, Var aValue, ScriptContext* scriptContext, PropertyOperationFlags flags = PropertyOperation_None);
             static BOOL SetElementIHelper(Var receiver, RecyclableObject* object, Var index, Var value, ScriptContext* scriptContext, PropertyOperationFlags flags);
    +        static BOOL OP_SetNativeIntElementI_NoConvert(Var instance, Var aElementIndex, int32 aValue, ScriptContext* scriptContext, PropertyOperationFlags flags = PropertyOperation_None);
    +        static BOOL OP_SetNativeIntElementI_UInt32_NoConvert(Var instance, uint32 aElementIndex, int32 aValue, ScriptContext* scriptContext, PropertyOperationFlags flags = PropertyOperation_None);
    +        static BOOL OP_SetNativeIntElementI_Int32_NoConvert(Var instance, int aElementIndex, int32 aValue, ScriptContext* scriptContext, PropertyOperationFlags flags = PropertyOperation_None);
    +        static BOOL OP_SetNativeFloatElementI_NoConvert(Var instance, Var aElementIndex, ScriptContext* scriptContext, PropertyOperationFlags flags, double value);
    +        static BOOL OP_SetNativeFloatElementI_UInt32_NoConvert(Var instance, uint32 aElementIndex, ScriptContext* scriptContext, PropertyOperationFlags flags, double value);
    +        static BOOL OP_SetNativeFloatElementI_Int32_NoConvert(Var instance, int aElementIndex, ScriptContext* scriptContext, PropertyOperationFlags flags, double value);
             static BOOL OP_SetNativeIntElementI(Var instance, Var aElementIndex, int32 aValue, ScriptContext* scriptContext, PropertyOperationFlags flags = PropertyOperation_None);
             static BOOL OP_SetNativeIntElementI_UInt32(Var instance, uint32 aElementIndex, int32 aValue, ScriptContext* scriptContext, PropertyOperationFlags flags = PropertyOperation_None);
             static BOOL OP_SetNativeIntElementI_Int32(Var instance, int aElementIndex, int32 aValue, ScriptContext* scriptContext, PropertyOperationFlags flags = PropertyOperation_None);
    
  • lib/Runtime/Library/JavascriptProxy.cpp+5 0 modified
    @@ -392,6 +392,8 @@ namespace Js
             }
             propertyDescriptor->SetValue(getGetResult);
     
    +        threadContext->AddImplicitCallFlags(Js::ImplicitCall_External);
    +
             return TRUE;
         }
     
    @@ -1907,6 +1909,9 @@ namespace Js
                     }
                 }
             }
    +
    +        threadContext->AddImplicitCallFlags(Js::ImplicitCall_External);
    +
             return TRUE;
     
         }
    
66ab97c09c49

CVE-2019-1052

https://github.com/chakra-core/ChakraCorewyrichteMay 16, 2019via ghsa
1 file changed · +1 1
  • lib/Backend/GlobOpt.cpp+1 1 modified
    @@ -1244,7 +1244,7 @@ void GlobOpt::InsertValueCompensation(
             {
                 IR::Instr *const newInstr =
                     IR::Instr::New(
    -                    Js::OpCode::Ld_I4,
    +                    Js::OpCode::Ld_A,
                         IR::RegOpnd::New(mergedHeadSegmentLengthSym, mergedHeadSegmentLengthSym->GetType(), func),
                         IR::RegOpnd::New(predecessorHeadSegmentLengthSym, predecessorHeadSegmentLengthSym->GetType(), func),
                         func);
    

Vulnerability mechanics

Generated on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.

References

6

News mentions

0

No linked articles in our index yet.