VYPR
High severityNVD Advisory· Published Jun 9, 2020· Updated Aug 4, 2024

CVE-2020-1073

CVE-2020-1073

Description

A remote code execution vulnerability exists in the way that the ChakraCore scripting engine handles objects in memory, aka 'Scripting Engine Memory Corruption Vulnerability'.

AI Insight

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

CVE-2020-1073 is a remote code execution vulnerability in ChakraCore due to memory corruption from improper handling of script engine objects.

Vulnerability

Overview CVE-2020-1073 is a remote code execution vulnerability in the ChakraCore scripting engine, specifically arising from how it handles objects in memory. The root cause is a memory corruption issue that occurs when the engine fails to properly manage object types during certain operations. [1] The vulnerability is triggered when a non-optimized StFld (store field) operation may change an object's type but is not detected during the loop prepass, leading to a maladjusted object type downstream. [4]

Exploitation

Exploitation of this vulnerability requires an attacker to craft a malicious script that leverages the memory corruption to execute arbitrary code. The attack surface is primarily through web browsers or any application that uses ChakraCore to process JavaScript, such as Microsoft Edge (legacy) or other embedded environments. The vulnerability can be triggered without authentication if the user visits a malicious webpage or opens a crafted file. [1]

Impact

Successful exploitation could allow an attacker to gain the same user rights as the current user. If the user has administrative privileges, the attacker could install programs, view, change, or delete data, or create new accounts with full user rights. [1] The vulnerability is classified as a remote code execution issue, indicating that an attacker can run arbitrary code on the target system.

Mitigation

Microsoft released a security update for ChakraCore to address this vulnerability, as documented in the commit that introduces helper functions to detect type changes and bail out if any transition occurs. [2] ChakraCore is an open-source project, and users are advised to apply the latest patches. For the broader ChakraCore ecosystem, note that Microsoft will provide security updates for ChakraCore 1.11 until March 2021, after which the project will transition to community maintenance. [3]

AI Insight generated on May 21, 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.201.11.20

Affected products

23
  • ghsa-coords
    Range: < 1.11.20
  • Microsoft/ChakraCorev5
    Range: unspecified
  • Microsoft/Microsoft Edge (EdgeHTML-based) on Windows 10 for 32-bit Systemsv5
    Range: unspecified
  • Microsoft/Microsoft Edge (EdgeHTML-based) on Windows 10 for x64-based Systemsv5
    Range: unspecified
  • Microsoft/Microsoft Edge (EdgeHTML-based) on Windows 10 Version 1607 for 32-bit Systemsv5
    Range: unspecified
  • Microsoft/Microsoft Edge (EdgeHTML-based) on Windows 10 Version 1607 for x64-based Systemsv5
    Range: unspecified
  • Microsoft/Microsoft Edge (EdgeHTML-based) on Windows 10 Version 1709 for 32-bit Systemsv5
    Range: unspecified
  • Microsoft/Microsoft Edge (EdgeHTML-based) on Windows 10 Version 1709 for ARM64-based Systemsv5
    Range: unspecified
  • Microsoft/Microsoft Edge (EdgeHTML-based) on Windows 10 Version 1709 for x64-based Systemsv5
    Range: unspecified
  • Microsoft/Microsoft Edge (EdgeHTML-based) on Windows 10 Version 1803 for 32-bit Systemsv5
    Range: unspecified
  • Microsoft/Microsoft Edge (EdgeHTML-based) on Windows 10 Version 1803 for ARM64-based Systemsv5
    Range: unspecified
  • Microsoft/Microsoft Edge (EdgeHTML-based) on Windows 10 Version 1803 for x64-based Systemsv5
    Range: unspecified
  • Microsoft/Microsoft Edge (EdgeHTML-based) on Windows 10 Version 1809 for 32-bit Systemsv5
    Range: unspecified
  • Microsoft/Microsoft Edge (EdgeHTML-based) on Windows 10 Version 1809 for ARM64-based Systemsv5
    Range: unspecified
  • Microsoft/Microsoft Edge (EdgeHTML-based) on Windows 10 Version 1809 for x64-based Systemsv5
    Range: unspecified
  • Microsoft/Microsoft Edge (EdgeHTML-based) on Windows 10 Version 1903 for 32-bit Systemsv5
    Range: unspecified
  • Microsoft/Microsoft Edge (EdgeHTML-based) on Windows 10 Version 1903 for ARM64-based Systemsv5
    Range: unspecified
  • Microsoft/Microsoft Edge (EdgeHTML-based) on Windows 10 Version 1903 for x64-based Systemsv5
    Range: unspecified
  • Microsoft/Microsoft Edge (EdgeHTML-based) on Windows 10 Version 1909 for 32-bit Systemsv5
    Range: unspecified
  • Microsoft/Microsoft Edge (EdgeHTML-based) on Windows 10 Version 1909 for ARM64-based Systemsv5
    Range: unspecified
  • Microsoft/Microsoft Edge (EdgeHTML-based) on Windows 10 Version 1909 for x64-based Systemsv5
    Range: unspecified
  • Microsoft/Microsoft Edge (EdgeHTML-based) on Windows Server 2016v5
    Range: unspecified
  • Microsoft/Microsoft Edge (EdgeHTML-based) on Windows Server 2019v5
    Range: unspecified

Patches

1
82d3c4556a3c

[CVE-2020-1073]

https://github.com/chakra-core/ChakraCoreAnkur GargMay 13, 2020via ghsa
12 files changed · +286 39
  • lib/Backend/BackwardPass.cpp+43 0 modified
    @@ -935,6 +935,7 @@ BackwardPass::MergeSuccBlocksInfo(BasicBlock * block)
                             blockSucc->couldRemoveNegZeroBailoutForDef = nullptr;
                         }
                     }
    +                this->CombineTypeIDsWithFinalType(block, blockSucc);
                 }
     
                 if (blockSucc->noImplicitCallUses != nullptr)
    @@ -4733,6 +4734,7 @@ BackwardPass::ProcessNewScObject(IR::Instr* instr)
     #else
                         block->stackSymToFinalType->Clear(objSym->m_id);
     #endif
    +                    this->ClearTypeIDWithFinalType(objSym->m_id, block);
                     }
                 }
     
    @@ -5208,6 +5210,10 @@ BackwardPass::MayPropertyBeWrittenTo(Js::PropertyId propertyId)
     void
     BackwardPass::ProcessPropertySymOpndUse(IR::PropertySymOpnd * opnd)
     {
    +    if (opnd == this->currentInstr->GetDst() && this->HasTypeIDWithFinalType(this->currentBlock))
    +    {
    +        opnd->SetCantChangeType(true);
    +    }
     
         // If this operand doesn't participate in the type check sequence it's a pass-through.
         // We will not set any bits on the operand and we will ignore them when lowering.
    @@ -5440,6 +5446,7 @@ BackwardPass::TrackObjTypeSpecProperties(IR::PropertySymOpnd *opnd, BasicBlock *
                             this->currentInstr->ChangeEquivalentToMonoTypeCheckBailOut();
                         }
                         bucket->SetMonoGuardType(nullptr);
    +                    this->ClearTypeIDWithFinalType(objSym->m_id, block);
                     }
     
                     if (!opnd->IsTypeAvailable())
    @@ -5641,6 +5648,7 @@ BackwardPass::TrackAddPropertyTypes(IR::PropertySymOpnd *opnd, BasicBlock *block
         }
     
         pBucket->SetInitialType(typeWithoutProperty);
    +    this->SetTypeIDWithFinalType(propertySym->m_stackSym->m_id, block);
     
         if (!PHASE_OFF(Js::ObjTypeSpecStorePhase, this->func))
         {
    @@ -5728,6 +5736,7 @@ BackwardPass::TrackAddPropertyTypes(IR::PropertySymOpnd *opnd, BasicBlock *block
     #else
             block->stackSymToFinalType->Clear(propertySym->m_stackSym->m_id);
     #endif
    +        this->ClearTypeIDWithFinalType(propertySym->m_stackSym->m_id, block);
         }
     }
     
    @@ -5933,6 +5942,40 @@ BackwardPass::ForEachAddPropertyCacheBucket(Fn fn)
         NEXT_HASHTABLE_ENTRY;
     }
     
    +void
    +BackwardPass::SetTypeIDWithFinalType(int symID, BasicBlock *block)
    +{
    +    BVSparse<JitArenaAllocator> *bv = block->EnsureTypeIDsWithFinalType(this->tempAlloc);
    +    bv->Set(symID);
    +}
    +
    +void
    +BackwardPass::ClearTypeIDWithFinalType(int symID, BasicBlock *block)
    +{
    +    BVSparse<JitArenaAllocator> *bv = block->typeIDsWithFinalType;
    +    if (bv != nullptr)
    +    {
    +        bv->Clear(symID);
    +    }
    +}
    +
    +bool
    +BackwardPass::HasTypeIDWithFinalType(BasicBlock *block) const
    +{
    +    return block->typeIDsWithFinalType != nullptr && !block->typeIDsWithFinalType->IsEmpty();
    +}
    +
    +void
    +BackwardPass::CombineTypeIDsWithFinalType(BasicBlock *block, BasicBlock *blockSucc)
    +{
    +    BVSparse<JitArenaAllocator> *bvSucc = blockSucc->typeIDsWithFinalType;
    +    if (bvSucc != nullptr && !bvSucc->IsEmpty())
    +    {
    +        BVSparse<JitArenaAllocator> *bv = block->EnsureTypeIDsWithFinalType(this->tempAlloc);
    +        bv->Or(bvSucc);
    +    }
    +}
    +
     bool
     BackwardPass::TransitionUndoesObjectHeaderInlining(AddPropertyCacheBucket *data) const
     {
    
  • lib/Backend/BackwardPass.h+5 0 modified
    @@ -149,6 +149,11 @@ class BackwardPass
         void InsertTypeTransitionsAtPotentialKills();
         bool TransitionUndoesObjectHeaderInlining(AddPropertyCacheBucket *data) const;
     
    +    void SetTypeIDWithFinalType(int symId, BasicBlock *block);
    +    void ClearTypeIDWithFinalType(int symId, BasicBlock *block);
    +    bool HasTypeIDWithFinalType(BasicBlock *block) const;
    +    void CombineTypeIDsWithFinalType(BasicBlock *block, BasicBlock *blockSucc);
    +
         template<class Fn> void ForEachAddPropertyCacheBucket(Fn fn);
         static ObjTypeGuardBucket MergeGuardedProperties(ObjTypeGuardBucket bucket1, ObjTypeGuardBucket bucket2);
         static ObjWriteGuardBucket MergeWriteGuards(ObjWriteGuardBucket bucket1, ObjWriteGuardBucket bucket2);
    
  • lib/Backend/FlowGraph.cpp+10 0 modified
    @@ -3399,6 +3399,16 @@ BasicBlock::CreateLoopTopBailOutInfo(GlobOpt * globOpt)
         return bailOutInfo;
     }
     
    +BVSparse<JitArenaAllocator> *
    +BasicBlock::EnsureTypeIDsWithFinalType(JitArenaAllocator *alloc)
    +{
    +    if (typeIDsWithFinalType == nullptr)
    +    {
    +         typeIDsWithFinalType = JitAnew(alloc, BVSparse<JitArenaAllocator>, alloc);
    +    }
    +    return typeIDsWithFinalType;
    +}
    +
     IR::Instr *
     FlowGraph::RemoveInstr(IR::Instr *instr, GlobOpt * globOpt)
     {
    
  • lib/Backend/FlowGraph.h+4 0 modified
    @@ -349,6 +349,8 @@ class BasicBlock
         bool IsLandingPad();
         BailOutInfo * CreateLoopTopBailOutInfo(GlobOpt * globOpt);
     
    +    BVSparse<JitArenaAllocator> *EnsureTypeIDsWithFinalType(JitArenaAllocator *alloc);
    +
         // GlobOpt Stuff
     public:
         bool         PathDepBranchFolding(GlobOpt* globOptState);
    @@ -400,6 +402,7 @@ class BasicBlock
         HashTable<AddPropertyCacheBucket> *     stackSymToFinalType;
         HashTable<ObjTypeGuardBucket> *         stackSymToGuardedProperties; // Dead store pass only
         HashTable<ObjWriteGuardBucket> *        stackSymToWriteGuardsMap; // Backward pass only
    +    BVSparse<JitArenaAllocator> *           typeIDsWithFinalType;
         BVSparse<JitArenaAllocator> *           noImplicitCallUses;
         BVSparse<JitArenaAllocator> *           noImplicitCallNoMissingValuesUses;
         BVSparse<JitArenaAllocator> *           noImplicitCallNativeArrayUses;
    @@ -443,6 +446,7 @@ class BasicBlock
             stackSymToFinalType(nullptr),
             stackSymToGuardedProperties(nullptr),
             stackSymToWriteGuardsMap(nullptr),
    +        typeIDsWithFinalType(nullptr),
             noImplicitCallUses(nullptr),
             noImplicitCallNoMissingValuesUses(nullptr),
             noImplicitCallNativeArrayUses(nullptr),
    
  • lib/Backend/GlobOptFields.cpp+1 0 modified
    @@ -392,6 +392,7 @@ GlobOpt::ProcessFieldKills(IR::Instr *instr, BVSparse<JitArenaAllocator> *bv, bo
     
         case Js::OpCode::InitSetFld:
         case Js::OpCode::InitGetFld:
    +    case Js::OpCode::InitClassMember:
         case Js::OpCode::InitClassMemberGet:
         case Js::OpCode::InitClassMemberSet:
             sym = instr->GetDst()->AsSymOpnd()->m_sym;
    
  • lib/Backend/JnHelperMethodList.h+11 0 modified
    @@ -254,6 +254,17 @@ HELPERCALLCHK(Op_PatchPutValueWithThisPtrNoLocalFastPathPolymorphic, ((void (*)(
     HELPERCALLCHK(Op_PatchPutRootValueNoLocalFastPath, ((void (*)(Js::FunctionBody *const, Js::InlineCache *const, const Js::InlineCacheIndex, Js::Var, Js::PropertyId, Js::Var, Js::PropertyOperationFlags))Js::JavascriptOperators::PatchPutRootValueNoLocalFastPath<true, Js::InlineCache>), AttrCanThrow)
     HELPERCALLCHK(Op_PatchPutRootValueNoLocalFastPathPolymorphic, ((void (*)(Js::FunctionBody *const, Js::PolymorphicInlineCache *const, const Js::InlineCacheIndex, Js::Var, Js::PropertyId, Js::Var, Js::PropertyOperationFlags))Js::JavascriptOperators::PatchPutRootValueNoLocalFastPath<true, Js::PolymorphicInlineCache>), AttrCanThrow)
     
    +HELPERCALLCHK(Op_PatchInitValueCantChangeType, ((bool (*)(Js::FunctionBody *const, Js::InlineCache *const, const Js::InlineCacheIndex, Js::RecyclableObject*, Js::PropertyId, Js::Var))Js::JavascriptOperators::PatchInitValueCantChangeType<Js::InlineCache>), AttrCanThrow)
    +HELPERCALLCHK(Op_PatchInitValuePolymorphicCantChangeType, ((bool (*)(Js::FunctionBody *const, Js::PolymorphicInlineCache *const, const Js::InlineCacheIndex, Js::RecyclableObject*, Js::PropertyId, Js::Var))Js::JavascriptOperators::PatchInitValueCantChangeType<Js::PolymorphicInlineCache>), AttrCanThrow)
    +HELPERCALLCHK(Op_PatchPutValueCantChangeType, ((bool (*)(Js::FunctionBody *const, Js::InlineCache *const, const Js::InlineCacheIndex, Js::Var, Js::PropertyId, Js::Var, Js::PropertyOperationFlags))Js::JavascriptOperators::PatchPutValueCantChangeType<Js::InlineCache>), AttrCanThrow)
    +HELPERCALLCHK(Op_PatchPutValueWithThisPtrCantChangeType, ((bool (*)(Js::FunctionBody *const, Js::InlineCache *const, const Js::InlineCacheIndex, Js::Var, Js::PropertyId, Js::Var, Js::Var, Js::PropertyOperationFlags))Js::JavascriptOperators::PatchPutValueWithThisPtrCantChangeType<Js::InlineCache>), AttrCanThrow)
    +HELPERCALLCHK(Op_PatchPutValuePolymorphicCantChangeType, ((bool (*)(Js::FunctionBody *const, Js::PolymorphicInlineCache *const, const Js::InlineCacheIndex, Js::Var, Js::PropertyId, Js::Var, Js::PropertyOperationFlags))Js::JavascriptOperators::PatchPutValueCantChangeType<Js::PolymorphicInlineCache>), AttrCanThrow)
    +HELPERCALLCHK(Op_PatchPutValueWithThisPtrPolymorphicCantChangeType, ((bool (*)(Js::FunctionBody *const, Js::PolymorphicInlineCache *const, const Js::InlineCacheIndex, Js::Var, Js::PropertyId, Js::Var, Js::Var, Js::PropertyOperationFlags))Js::JavascriptOperators::PatchPutValueWithThisPtrCantChangeType<Js::PolymorphicInlineCache>), AttrCanThrow)
    +HELPERCALLCHK(Op_PatchPutValueNoLocalFastPathCantChangeType, ((bool (*)(Js::FunctionBody *const, Js::InlineCache *const, const Js::InlineCacheIndex, Js::Var, Js::PropertyId, Js::Var, Js::PropertyOperationFlags))Js::JavascriptOperators::PatchPutValueNoLocalFastPathCantChangeType<Js::InlineCache>), AttrCanThrow)
    +HELPERCALLCHK(Op_PatchPutValueWithThisPtrNoLocalFastPathCantChangeType, ((bool (*)(Js::FunctionBody *const, Js::InlineCache *const, const Js::InlineCacheIndex, Js::Var, Js::PropertyId, Js::Var, Js::Var, Js::PropertyOperationFlags))Js::JavascriptOperators::PatchPutValueWithThisPtrNoLocalFastPathCantChangeType<Js::InlineCache>), AttrCanThrow)
    +HELPERCALLCHK(Op_PatchPutValueNoLocalFastPathPolymorphicCantChangeType, ((bool (*)(Js::FunctionBody *const, Js::PolymorphicInlineCache *const, const Js::InlineCacheIndex, Js::Var, Js::PropertyId, Js::Var, Js::PropertyOperationFlags))Js::JavascriptOperators::PatchPutValueNoLocalFastPathCantChangeType<Js::PolymorphicInlineCache>), AttrCanThrow)
    +HELPERCALLCHK(Op_PatchPutValueWithThisPtrNoLocalFastPathPolymorphicCantChangeType, ((bool (*)(Js::FunctionBody *const, Js::PolymorphicInlineCache *const, const Js::InlineCacheIndex, Js::Var, Js::PropertyId, Js::Var, Js::Var, Js::PropertyOperationFlags))Js::JavascriptOperators::PatchPutValueWithThisPtrNoLocalFastPathCantChangeType<Js::PolymorphicInlineCache>), AttrCanThrow)
    +
     HELPERCALLCHK(Op_PatchInitValueCheckLayout, ((bool (*)(Js::FunctionBody *const, Js::InlineCache *const, const Js::InlineCacheIndex, Js::RecyclableObject*, Js::PropertyId, Js::Var))Js::JavascriptOperators::PatchInitValueCheckLayout<Js::InlineCache>), AttrCanThrow)
     HELPERCALLCHK(Op_PatchInitValuePolymorphicCheckLayout, ((bool (*)(Js::FunctionBody *const, Js::PolymorphicInlineCache *const, const Js::InlineCacheIndex, Js::RecyclableObject*, Js::PropertyId, Js::Var))Js::JavascriptOperators::PatchInitValueCheckLayout<Js::PolymorphicInlineCache>), AttrCanThrow)
     HELPERCALLCHK(Op_PatchPutValueCheckLayout, ((bool (*)(Js::FunctionBody *const, Js::InlineCache *const, const Js::InlineCacheIndex, Js::Var, Js::PropertyId, Js::Var, Js::PropertyOperationFlags))Js::JavascriptOperators::PatchPutValueCheckLayout<Js::InlineCache>), AttrCanThrow)
    
  • lib/Backend/Lower.cpp+112 37 modified
    @@ -7112,48 +7112,14 @@ Lowerer::LowerStFld(
         if (dst->AsSymOpnd()->IsPropertySymOpnd())
         {
             propertySymOpnd = dst->AsPropertySymOpnd();
    -        if (stFldInstr->HasBailOutInfo() && !propertySymOpnd->IsTypeCheckSeqCandidate() && propertySymOpnd->TypeCheckRequired())
    +        if (stFldInstr->HasBailOutInfo() && !propertySymOpnd->IsTypeCheckSeqCandidate() &&
    +                (propertySymOpnd->CantChangeType() || propertySymOpnd->TypeCheckRequired()))
             {
                 IR::Instr * instrBailTarget = stFldInstr->ShareBailOut();
                 LowerBailTarget(instrBailTarget);
                 doCheckLayout = true;
                 bailOutInfo = stFldInstr->GetBailOutInfo();
    -            switch (helperMethod)
    -            {
    -                case IR::HelperOp_PatchPutValue:
    -                    helperMethod = IR::HelperOp_PatchPutValueCheckLayout;
    -                    break;
    -                case IR::HelperOp_PatchPutValuePolymorphic:
    -                    helperMethod = IR::HelperOp_PatchPutValuePolymorphicCheckLayout;
    -                    break;
    -                case IR::HelperOp_PatchPutValueNoLocalFastPath:
    -                    helperMethod = IR::HelperOp_PatchPutValueNoLocalFastPathCheckLayout;
    -                    break;
    -                case IR::HelperOp_PatchPutValueNoLocalFastPathPolymorphic:
    -                    helperMethod = IR::HelperOp_PatchPutValueNoLocalFastPathPolymorphicCheckLayout;
    -                    break;
    -                case IR::HelperOp_PatchPutValueWithThisPtr:
    -                    helperMethod = IR::HelperOp_PatchPutValueWithThisPtrCheckLayout;
    -                    break;
    -                case IR::HelperOp_PatchPutValueWithThisPtrPolymorphic:
    -                    helperMethod = IR::HelperOp_PatchPutValueWithThisPtrPolymorphicCheckLayout;
    -                    break;
    -                case IR::HelperOp_PatchPutValueWithThisPtrNoLocalFastPath:
    -                    helperMethod = IR::HelperOp_PatchPutValueWithThisPtrNoLocalFastPathCheckLayout;
    -                    break;
    -                case IR::HelperOp_PatchPutValueWithThisPtrNoLocalFastPathPolymorphic:
    -                    helperMethod = IR::HelperOp_PatchPutValueWithThisPtrNoLocalFastPathPolymorphicCheckLayout;
    -                    break;
    -                case IR::HelperOp_PatchInitValue:
    -                    helperMethod = IR::HelperOp_PatchInitValueCheckLayout;
    -                    break;
    -                case IR::HelperOp_PatchInitValuePolymorphic:
    -                    helperMethod = IR::HelperOp_PatchInitValuePolymorphicCheckLayout;
    -                    break;
    -                default:
    -                    AssertOrFailFast(false);
    -                    break;
    -            }
    +            MapStFldHelper(propertySymOpnd, helperMethod, polymorphicHelperMethod);
             }
         }
     
    @@ -7221,6 +7187,115 @@ Lowerer::LowerStFld(
         return instrPrev;
     }
     
    +void
    +Lowerer::MapStFldHelper(IR::PropertySymOpnd * propertySymOpnd, IR::JnHelperMethod &helperMethod, IR::JnHelperMethod &polymorphicHelperMethod)
    +{
    +    Assert(propertySymOpnd->CantChangeType() || propertySymOpnd->TypeCheckRequired());
    +
    +    if (propertySymOpnd->CantChangeType())
    +    {
    +        switch (helperMethod)
    +        {
    +            case IR::HelperOp_PatchPutValue:
    +                helperMethod = IR::HelperOp_PatchPutValueCantChangeType;
    +                polymorphicHelperMethod = IR::HelperOp_PatchPutValuePolymorphicCantChangeType;
    +                break;
    +            case IR::HelperOp_PatchPutValuePolymorphic:
    +                helperMethod = polymorphicHelperMethod = IR::HelperOp_PatchPutValuePolymorphicCantChangeType;
    +                break;
    +            case IR::HelperOp_PatchPutValueNoLocalFastPath:
    +                helperMethod = IR::HelperOp_PatchPutValueNoLocalFastPathCantChangeType;
    +                polymorphicHelperMethod = IR::HelperOp_PatchPutValueNoLocalFastPathPolymorphicCantChangeType;
    +                break;
    +            case IR::HelperOp_PatchPutValueNoLocalFastPathPolymorphic:
    +                helperMethod = polymorphicHelperMethod = IR::HelperOp_PatchPutValueNoLocalFastPathPolymorphicCantChangeType;
    +                break;
    +            case IR::HelperOp_PatchPutValueWithThisPtr:
    +                helperMethod = IR::HelperOp_PatchPutValueWithThisPtrCantChangeType;
    +                polymorphicHelperMethod = IR::HelperOp_PatchPutValueWithThisPtrPolymorphicCantChangeType;
    +                break;
    +            case IR::HelperOp_PatchPutValueWithThisPtrPolymorphic:
    +                helperMethod = polymorphicHelperMethod = IR::HelperOp_PatchPutValueWithThisPtrPolymorphicCantChangeType;
    +                break;
    +            case IR::HelperOp_PatchPutValueWithThisPtrNoLocalFastPath:
    +                helperMethod = IR::HelperOp_PatchPutValueWithThisPtrNoLocalFastPathCantChangeType;
    +                polymorphicHelperMethod = IR::HelperOp_PatchPutValueWithThisPtrNoLocalFastPathPolymorphicCantChangeType;
    +                break;
    +            case IR::HelperOp_PatchPutValueWithThisPtrNoLocalFastPathPolymorphic:
    +                helperMethod = polymorphicHelperMethod = IR::HelperOp_PatchPutValueWithThisPtrNoLocalFastPathPolymorphicCantChangeType;
    +                break;
    +            case IR::HelperOp_PatchInitValue:
    +                helperMethod = IR::HelperOp_PatchInitValueCantChangeType;
    +                polymorphicHelperMethod = IR::HelperOp_PatchInitValuePolymorphicCantChangeType;
    +                break;
    +            case IR::HelperOp_PatchInitValuePolymorphic:
    +                helperMethod = polymorphicHelperMethod = IR::HelperOp_PatchInitValuePolymorphicCantChangeType;
    +                break;
    +            case IR::HelperOp_PatchPutRootValue:
    +            case IR::HelperOp_PatchPutRootValuePolymorphic:
    +            case IR::HelperOp_PatchPutRootValueNoLocalFastPath:
    +            case IR::HelperOp_PatchPutRootValueNoLocalFastPathPolymorphic:
    +                // No helper method change is needed here, because the global object doesn't participate in final type opt, so it can't alias
    +                // an object that does.
    +                break;
    +            default:
    +                AssertOrFailFast(false);
    +                break;
    +        }
    +    }
    +    else
    +    {
    +        switch (helperMethod)
    +        {
    +            case IR::HelperOp_PatchPutValue:
    +                helperMethod = IR::HelperOp_PatchPutValueCheckLayout;
    +                polymorphicHelperMethod = IR::HelperOp_PatchPutValuePolymorphicCheckLayout;
    +                break;
    +            case IR::HelperOp_PatchPutValuePolymorphic:
    +                helperMethod = polymorphicHelperMethod = IR::HelperOp_PatchPutValuePolymorphicCheckLayout;
    +                break;
    +            case IR::HelperOp_PatchPutValueNoLocalFastPath:
    +                helperMethod = IR::HelperOp_PatchPutValueNoLocalFastPathCheckLayout;
    +                polymorphicHelperMethod = IR::HelperOp_PatchPutValueNoLocalFastPathPolymorphicCheckLayout;
    +                break;
    +            case IR::HelperOp_PatchPutValueNoLocalFastPathPolymorphic:
    +                helperMethod = polymorphicHelperMethod = IR::HelperOp_PatchPutValueNoLocalFastPathPolymorphicCheckLayout;
    +                break;
    +            case IR::HelperOp_PatchPutValueWithThisPtr:
    +                helperMethod = IR::HelperOp_PatchPutValueWithThisPtrCheckLayout;
    +                polymorphicHelperMethod = IR::HelperOp_PatchPutValueWithThisPtrPolymorphicCheckLayout;
    +                break;
    +            case IR::HelperOp_PatchPutValueWithThisPtrPolymorphic:
    +                helperMethod = polymorphicHelperMethod = IR::HelperOp_PatchPutValueWithThisPtrPolymorphicCheckLayout;
    +                break;
    +            case IR::HelperOp_PatchPutValueWithThisPtrNoLocalFastPath:
    +                helperMethod = IR::HelperOp_PatchPutValueWithThisPtrNoLocalFastPathCheckLayout;
    +                polymorphicHelperMethod = IR::HelperOp_PatchPutValueWithThisPtrNoLocalFastPathPolymorphicCheckLayout;
    +                break;
    +            case IR::HelperOp_PatchPutValueWithThisPtrNoLocalFastPathPolymorphic:
    +                helperMethod = polymorphicHelperMethod = IR::HelperOp_PatchPutValueWithThisPtrNoLocalFastPathPolymorphicCheckLayout;
    +                break;
    +            case IR::HelperOp_PatchInitValue:
    +                helperMethod = IR::HelperOp_PatchInitValueCheckLayout;
    +                polymorphicHelperMethod = IR::HelperOp_PatchInitValuePolymorphicCheckLayout;
    +                break;
    +            case IR::HelperOp_PatchInitValuePolymorphic:
    +                helperMethod = polymorphicHelperMethod = IR::HelperOp_PatchInitValuePolymorphicCheckLayout;
    +                break;
    +            case IR::HelperOp_PatchPutRootValue:
    +            case IR::HelperOp_PatchPutRootValuePolymorphic:
    +            case IR::HelperOp_PatchPutRootValueNoLocalFastPath:
    +            case IR::HelperOp_PatchPutRootValueNoLocalFastPathPolymorphic:
    +                // No helper method change is needed here, because the global object doesn't participate in final type opt, so it can't alias
    +                // an object that does.
    +                break;
    +            default:
    +                AssertOrFailFast(false);
    +                break;
    +        }
    +    }
    +}
    +
     IR::Instr* Lowerer::GenerateCompleteStFld(IR::Instr* instr, bool emitFastPath, IR::JnHelperMethod monoHelperAfterFastPath, IR::JnHelperMethod polyHelperAfterFastPath,
         IR::JnHelperMethod monoHelperWithoutFastPath, IR::JnHelperMethod polyHelperWithoutFastPath, bool withPutFlags, Js::PropertyOperationFlags flags)
     {
    
  • lib/Backend/Lower.h+1 0 modified
    @@ -204,6 +204,7 @@ class Lowerer
         void            GenerateStackScriptFunctionInit(IR::RegOpnd * regOpnd, Js::FunctionInfoPtrPtr nestedInfo, IR::Opnd * envOpnd, IR::Instr * insertBeforeInstr);
         IR::Instr *     LowerProfiledStFld(IR::JitProfilingInstr * instr, Js::PropertyOperationFlags flags);
         IR::Instr *     LowerStFld(IR::Instr * stFldInstr, IR::JnHelperMethod helperMethod, IR::JnHelperMethod polymorphicHelperMethod, bool withInlineCache, IR::LabelInstr *ppBailOutLabel = nullptr, bool isHelper = false, bool withPutFlags = false, Js::PropertyOperationFlags flags = Js::PropertyOperation_None);
    +    void            MapStFldHelper(IR::PropertySymOpnd * propertySymOpnd, IR::JnHelperMethod &helperMethod, IR::JnHelperMethod &polymorphicHelperMethod);
         IR::Instr *     LowerScopedStFld(IR::Instr * stFldInstr, IR::JnHelperMethod helperMethod, bool withInlineCache,
                                     bool withPropertyOperationFlags = false, Js::PropertyOperationFlags flags = Js::PropertyOperation_None);
         void            LowerProfiledLdElemI(IR::JitProfilingInstr *const instr);
    
  • lib/Backend/Opnd.h+11 0 modified
    @@ -636,6 +636,7 @@ class PropertySymOpnd sealed : public SymOpnd
                 // Note that even usesFixedValue cannot live on ObjTypeSpecFldInfo, because we may share a cache between
                 // e.g. Object.prototype and new Object(), and only the latter actually uses the fixed value, even though both have it.
                 bool usesFixedValue: 1;
    +            bool cantChangeType: 1;
     
                 union
                 {
    @@ -1035,6 +1036,16 @@ class PropertySymOpnd sealed : public SymOpnd
             this->typeCheckRequired = value;
         }
     
    +    bool CantChangeType() const
    +    {
    +        return this->cantChangeType;
    +    }
    +
    +    void SetCantChangeType(bool value)
    +    {
    +        this->cantChangeType = value;
    +    }
    +
         uint16 GetObjTypeSpecFlags() const
         {
             return this->objTypeSpecFlags;
    
  • lib/Runtime/ByteCode/OpCodes.h+2 2 modified
    @@ -513,8 +513,8 @@ MACRO_WMS(              StArrSegItem_CI4,       ElementUnsigned1,      OpSideEff
     MACRO(                  StArrSegItem_A,         Auxiliary,      OpSideEffect)
     MACRO_WMS(              DeleteElemI_A,          ElementI,       OpSideEffect|OpHasImplicitCall|OpPostOpDbgBailOut)                  // Remove from instance's indirect element / field, checked
     MACRO_WMS(              DeleteElemIStrict_A,    ElementI,       OpSideEffect|OpHasImplicitCall|OpPostOpDbgBailOut)                  // Remove from instance's indirect element / field, checked
    -MACRO_EXTEND_WMS(       InitSetFld,             ElementC,       OpSideEffect|OpOpndHasImplicitCall|OpFastFldInstr|OpPostOpDbgBailOut)   // Set in Object Literal Syntax {set prop(args){}};
    -MACRO_EXTEND_WMS(       InitGetFld,             ElementC,       OpSideEffect|OpOpndHasImplicitCall|OpFastFldInstr|OpPostOpDbgBailOut)   // Get in Object Literal Syntax {get prop(){}};
    +MACRO_EXTEND_WMS(       InitSetFld,             ElementC,       OpSideEffect|OpOpndHasImplicitCall|OpPostOpDbgBailOut)                  // Set in Object Literal Syntax {set prop(args){}};
    +MACRO_EXTEND_WMS(       InitGetFld,             ElementC,       OpSideEffect|OpOpndHasImplicitCall|OpPostOpDbgBailOut)                  // Get in Object Literal Syntax {get prop(){}};
     MACRO_EXTEND_WMS(       InitSetElemI,           ElementI,       OpSideEffect|OpOpndHasImplicitCall|OpPostOpDbgBailOut)                  // Set in Object Literal Syntax {set [expr](args){}};
     MACRO_EXTEND_WMS(       InitGetElemI,           ElementI,       OpSideEffect|OpOpndHasImplicitCall|OpPostOpDbgBailOut)                  // Get in Object Literal Syntax {get [expr](args){}};
     MACRO_EXTEND_WMS(       InitComputedProperty,   ElementI,       OpSideEffect|OpOpndHasImplicitCall|OpPostOpDbgBailOut)                  // Data property in Object Literal Syntax { [expr] : expr};
    
  • lib/Runtime/Language/JavascriptOperators.cpp+80 0 modified
    @@ -8687,6 +8687,86 @@ using namespace Js;
             }
         }
     
    +    template <class TInlineCache>
    +    inline bool JavascriptOperators::PatchPutValueCantChangeType(FunctionBody *const functionBody, TInlineCache *const inlineCache, const InlineCacheIndex inlineCacheIndex, Var instance, PropertyId propertyId, Var newValue, PropertyOperationFlags flags)
    +    {
    +        JIT_HELPER_REENTRANT_HEADER(Op_PatchPutValueCantChangeType);
    +        JIT_HELPER_SAME_ATTRIBUTES(Op_PatchPutValueCantChangeType, Op_PatchPutValue);
    +
    +        Type * oldType = DynamicObject::Is(instance) ? DynamicObject::FromVar(instance)->GetType() : nullptr;
    +        PatchPutValueWithThisPtr<true, TInlineCache>(functionBody, inlineCache, inlineCacheIndex, instance, propertyId, newValue, instance, flags);
    +        return (oldType != nullptr && oldType != DynamicObject::FromVar(instance)->GetType());
    +
    +        JIT_HELPER_END(Op_PatchPutValueCantChangeType);
    +    }
    +    JIT_HELPER_TEMPLATE(Op_PatchPutValueCantChangeType, Op_PatchPutValuePolymorphicCantChangeType);
    +    template bool JavascriptOperators::PatchPutValueCantChangeType<InlineCache>(FunctionBody *const functionBody, InlineCache *const inlineCache, const InlineCacheIndex inlineCacheIndex, Var instance, PropertyId propertyId, Var newValue, PropertyOperationFlags flags);
    +    template bool JavascriptOperators::PatchPutValueCantChangeType<PolymorphicInlineCache>(FunctionBody *const functionBody, PolymorphicInlineCache *const inlineCache, const InlineCacheIndex inlineCacheIndex, Var instance, PropertyId propertyId, Var newValue, PropertyOperationFlags flags);
    +
    +    template <class TInlineCache>
    +    inline bool JavascriptOperators::PatchPutValueWithThisPtrCantChangeType(FunctionBody *const functionBody, TInlineCache *const inlineCache, const InlineCacheIndex inlineCacheIndex, Var instance, PropertyId propertyId, Var newValue, Var thisInstance, PropertyOperationFlags flags)
    +    {
    +        JIT_HELPER_REENTRANT_HEADER(Op_PatchPutValueWithThisPtrCantChangeType);
    +        JIT_HELPER_SAME_ATTRIBUTES(Op_PatchPutValueWithThisPtrCantChangeType, Op_PatchPutValueWithThisPtr);
    +
    +        Type * oldType = DynamicObject::Is(instance) ? DynamicObject::FromVar(instance)->GetType() : nullptr;
    +        PatchPutValueWithThisPtr<true, TInlineCache>(functionBody, inlineCache, inlineCacheIndex, instance, propertyId, newValue, thisInstance, flags);
    +        return (oldType != nullptr && oldType != DynamicObject::FromVar(instance)->GetType());
    +
    +        JIT_HELPER_END(Op_PatchPutValueWithThisPtrCantChangeType);
    +    }
    +    JIT_HELPER_TEMPLATE(Op_PatchPutValueWithThisPtrCantChangeType, Op_PatchPutValueWithThisPtrPolymorphicCantChangeType);
    +    template bool JavascriptOperators::PatchPutValueWithThisPtrCantChangeType<InlineCache>(FunctionBody *const functionBody, InlineCache *const inlineCache, const InlineCacheIndex inlineCacheIndex, Var instance, PropertyId propertyId, Var newValue, Var thisInstance, PropertyOperationFlags flags);
    +    template bool JavascriptOperators::PatchPutValueWithThisPtrCantChangeType<PolymorphicInlineCache>(FunctionBody *const functionBody, PolymorphicInlineCache *const inlineCache, const InlineCacheIndex inlineCacheIndex, Var instance, PropertyId propertyId, Var newValue, Var thisInstance, PropertyOperationFlags flags);
    +
    +    template <class TInlineCache>
    +    inline bool JavascriptOperators::PatchPutValueNoLocalFastPathCantChangeType(FunctionBody *const functionBody, TInlineCache *const inlineCache, const InlineCacheIndex inlineCacheIndex, Var instance, PropertyId propertyId, Var newValue, PropertyOperationFlags flags)
    +    {
    +        JIT_HELPER_REENTRANT_HEADER(Op_PatchPutValueNoLocalFastPathCantChangeType);
    +        JIT_HELPER_SAME_ATTRIBUTES(Op_PatchPutValueNoLocalFastPathCantChangeType, Op_PatchPutValueNoLocalFastPath);
    +
    +        Type * oldType = DynamicObject::Is(instance) ? DynamicObject::FromVar(instance)->GetType() : nullptr;
    +        PatchPutValueWithThisPtrNoLocalFastPath<true, TInlineCache>(functionBody, inlineCache, inlineCacheIndex, instance, propertyId, newValue, instance, flags);
    +        return (oldType != nullptr && oldType != DynamicObject::FromVar(instance)->GetType());
    +
    +        JIT_HELPER_END(Op_PatchPutValueNoLocalFastPathCantChangeType);
    +    }
    +    JIT_HELPER_TEMPLATE(Op_PatchPutValueNoLocalFastPathCantChangeType, Op_PatchPutValueNoLocalFastPathPolymorphicCantChangeType);
    +    template bool JavascriptOperators::PatchPutValueNoLocalFastPathCantChangeType<InlineCache>(FunctionBody *const functionBody, InlineCache *const inlineCache, const InlineCacheIndex inlineCacheIndex, Var instance, PropertyId propertyId, Var newValue, PropertyOperationFlags flags);
    +    template bool JavascriptOperators::PatchPutValueNoLocalFastPathCantChangeType<PolymorphicInlineCache>(FunctionBody *const functionBody, PolymorphicInlineCache *const inlineCache, const InlineCacheIndex inlineCacheIndex, Var instance, PropertyId propertyId, Var newValue, PropertyOperationFlags flags);
    +
    +    template <class TInlineCache>
    +    inline bool JavascriptOperators::PatchPutValueWithThisPtrNoLocalFastPathCantChangeType(FunctionBody *const functionBody, TInlineCache *const inlineCache, const InlineCacheIndex inlineCacheIndex, Var instance, PropertyId propertyId, Var newValue, Var thisInstance, PropertyOperationFlags flags)
    +    {
    +        JIT_HELPER_REENTRANT_HEADER(Op_PatchPutValueWithThisPtrNoLocalFastPathCantChangeType);
    +        JIT_HELPER_SAME_ATTRIBUTES(Op_PatchPutValueWithThisPtrNoLocalFastPathCantChangeType, Op_PatchPutValueWithThisPtrNoLocalFastPath);
    +
    +        Type * oldType = DynamicObject::Is(instance) ? DynamicObject::FromVar(instance)->GetType() : nullptr;
    +        PatchPutValueWithThisPtrNoLocalFastPath<true, TInlineCache>(functionBody, inlineCache, inlineCacheIndex, instance, propertyId, newValue, thisInstance, flags);
    +        return (oldType != nullptr && oldType != DynamicObject::FromVar(instance)->GetType());
    +
    +        JIT_HELPER_END(Op_PatchPutValueWithThisPtrNoLocalFastPathCantChangeType);
    +    }
    +    JIT_HELPER_TEMPLATE(Op_PatchPutValueWithThisPtrNoLocalFastPathCantChangeType, Op_PatchPutValueWithThisPtrNoLocalFastPathPolymorphicCantChangeType);
    +    template bool JavascriptOperators::PatchPutValueWithThisPtrNoLocalFastPathCantChangeType<InlineCache>(FunctionBody *const functionBody, InlineCache *const inlineCache, const InlineCacheIndex inlineCacheIndex, Var instance, PropertyId propertyId, Var newValue, Var thisInstance, PropertyOperationFlags flags);
    +    template bool JavascriptOperators::PatchPutValueWithThisPtrNoLocalFastPathCantChangeType<PolymorphicInlineCache>(FunctionBody *const functionBody, PolymorphicInlineCache *const inlineCache, const InlineCacheIndex inlineCacheIndex, Var instance, PropertyId propertyId, Var newValue, Var thisInstance, PropertyOperationFlags flags);
    +
    +    template <class TInlineCache>
    +    inline bool JavascriptOperators::PatchInitValueCantChangeType(FunctionBody *const functionBody, TInlineCache *const inlineCache, const InlineCacheIndex inlineCacheIndex, RecyclableObject* object, PropertyId propertyId, Var newValue)
    +    {
    +        JIT_HELPER_REENTRANT_HEADER(Op_PatchInitValueCantChangeType);
    +        JIT_HELPER_SAME_ATTRIBUTES(Op_PatchInitValueCantChangeType, Op_PatchInitValue);
    +
    +        Type * oldType = DynamicObject::Is(object) ? DynamicObject::FromVar(object)->GetType() : nullptr;
    +        PatchInitValue<true, TInlineCache>(functionBody, inlineCache, inlineCacheIndex, object, propertyId, newValue);
    +        return (oldType != nullptr && oldType != DynamicObject::FromVar(object)->GetType());
    +
    +        JIT_HELPER_END(Op_PatchInitValueCantChangeType);
    +    }
    +    JIT_HELPER_TEMPLATE(Op_PatchInitValueCantChangeType, Op_PatchInitValuePolymorphicCantChangeType);
    +    template bool JavascriptOperators::PatchInitValueCantChangeType<InlineCache>(FunctionBody *const functionBody, InlineCache *const inlineCache, const InlineCacheIndex inlineCacheIndex, RecyclableObject* object, PropertyId propertyId, Var newValue);
    +    template bool JavascriptOperators::PatchInitValueCantChangeType<PolymorphicInlineCache>(FunctionBody *const functionBody, PolymorphicInlineCache *const inlineCache, const InlineCacheIndex inlineCacheIndex, RecyclableObject* object, PropertyId propertyId, Var newValue);
    +
         template <class TInlineCache>
         inline bool JavascriptOperators::PatchPutValueCheckLayout(FunctionBody *const functionBody, TInlineCache *const inlineCache, const InlineCacheIndex inlineCacheIndex, Var instance, PropertyId propertyId, Var newValue, PropertyOperationFlags flags)
         {
    
  • lib/Runtime/Language/JavascriptOperators.h+6 0 modified
    @@ -575,6 +575,12 @@ namespace Js
             template <bool IsFromFullJit, class TInlineCache> static void PatchInitValue(FunctionBody *const functionBody, TInlineCache *const inlineCache, const InlineCacheIndex inlineCacheIndex, RecyclableObject* object, PropertyId propertyId, Var newValue);
             static void PatchInitValueNoFastPath(FunctionBody *const functionBody, InlineCache *const inlineCache, const InlineCacheIndex inlineCacheIndex, RecyclableObject* object, PropertyId propertyId, Var newValue);
     
    +        template <class TInlineCache> static bool PatchPutValueCantChangeType(FunctionBody *const functionBody, TInlineCache *const inlineCache, const InlineCacheIndex inlineCacheIndex, Var obj, PropertyId propertyId, Var newValue, PropertyOperationFlags flags = PropertyOperation_None);
    +        template <class TInlineCache> static bool PatchPutValueWithThisPtrCantChangeType(FunctionBody *const functionBody, TInlineCache *const inlineCache, const InlineCacheIndex inlineCacheIndex, Var obj, PropertyId propertyId, Var newValue, Var thisInstance, PropertyOperationFlags flags = PropertyOperation_None);
    +        template <class TInlineCache> static bool PatchPutValueNoLocalFastPathCantChangeType(FunctionBody *const functionBody, TInlineCache *const inlineCache, const InlineCacheIndex inlineCacheIndex, Var instance, PropertyId propertyId, Var newValue, PropertyOperationFlags flags = PropertyOperation_None);
    +        template <class TInlineCache> static bool PatchPutValueWithThisPtrNoLocalFastPathCantChangeType(FunctionBody *const functionBody, TInlineCache *const inlineCache, const InlineCacheIndex inlineCacheIndex, Var instance, PropertyId propertyId, Var newValue, Var thisInstance, PropertyOperationFlags flags = PropertyOperation_None);
    +        template <class TInlineCache> static bool PatchInitValueCantChangeType(FunctionBody *const functionBody, TInlineCache *const inlineCache, const InlineCacheIndex inlineCacheIndex, RecyclableObject* object, PropertyId propertyId, Var newValue);
    +
             template <class TInlineCache> static bool PatchPutValueCheckLayout(FunctionBody *const functionBody, TInlineCache *const inlineCache, const InlineCacheIndex inlineCacheIndex, Var obj, PropertyId propertyId, Var newValue, PropertyOperationFlags flags = PropertyOperation_None);
             template <class TInlineCache> static bool PatchPutValueWithThisPtrCheckLayout(FunctionBody *const functionBody, TInlineCache *const inlineCache, const InlineCacheIndex inlineCacheIndex, Var obj, PropertyId propertyId, Var newValue, Var thisInstance, PropertyOperationFlags flags = PropertyOperation_None);
             template <class TInlineCache> static bool PatchPutValueNoLocalFastPathCheckLayout(FunctionBody *const functionBody, TInlineCache *const inlineCache, const InlineCacheIndex inlineCacheIndex, Var instance, PropertyId propertyId, Var newValue, PropertyOperationFlags flags = PropertyOperation_None);
    

Vulnerability mechanics

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

References

5

News mentions

0

No linked articles in our index yet.