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.
| Package | Affected versions | Patched versions |
|---|---|---|
Microsoft.ChakraCoreNuGet | < 1.11.20 | 1.11.20 |
Affected products
23- Microsoft/ChakraCorev5Range: unspecified
- Microsoft/Microsoft Edge (EdgeHTML-based) on Windows 10 for 32-bit Systemsv5Range: unspecified
- Microsoft/Microsoft Edge (EdgeHTML-based) on Windows 10 for x64-based Systemsv5Range: unspecified
- Microsoft/Microsoft Edge (EdgeHTML-based) on Windows 10 Version 1607 for 32-bit Systemsv5Range: unspecified
- Microsoft/Microsoft Edge (EdgeHTML-based) on Windows 10 Version 1607 for x64-based Systemsv5Range: unspecified
- Microsoft/Microsoft Edge (EdgeHTML-based) on Windows 10 Version 1709 for 32-bit Systemsv5Range: unspecified
- Microsoft/Microsoft Edge (EdgeHTML-based) on Windows 10 Version 1709 for ARM64-based Systemsv5Range: unspecified
- Microsoft/Microsoft Edge (EdgeHTML-based) on Windows 10 Version 1709 for x64-based Systemsv5Range: unspecified
- Microsoft/Microsoft Edge (EdgeHTML-based) on Windows 10 Version 1803 for 32-bit Systemsv5Range: unspecified
- Microsoft/Microsoft Edge (EdgeHTML-based) on Windows 10 Version 1803 for ARM64-based Systemsv5Range: unspecified
- Microsoft/Microsoft Edge (EdgeHTML-based) on Windows 10 Version 1803 for x64-based Systemsv5Range: unspecified
- Microsoft/Microsoft Edge (EdgeHTML-based) on Windows 10 Version 1809 for 32-bit Systemsv5Range: unspecified
- Microsoft/Microsoft Edge (EdgeHTML-based) on Windows 10 Version 1809 for ARM64-based Systemsv5Range: unspecified
- Microsoft/Microsoft Edge (EdgeHTML-based) on Windows 10 Version 1809 for x64-based Systemsv5Range: unspecified
- Microsoft/Microsoft Edge (EdgeHTML-based) on Windows 10 Version 1903 for 32-bit Systemsv5Range: unspecified
- Microsoft/Microsoft Edge (EdgeHTML-based) on Windows 10 Version 1903 for ARM64-based Systemsv5Range: unspecified
- Microsoft/Microsoft Edge (EdgeHTML-based) on Windows 10 Version 1903 for x64-based Systemsv5Range: unspecified
- Microsoft/Microsoft Edge (EdgeHTML-based) on Windows 10 Version 1909 for 32-bit Systemsv5Range: unspecified
- Microsoft/Microsoft Edge (EdgeHTML-based) on Windows 10 Version 1909 for ARM64-based Systemsv5Range: unspecified
- Microsoft/Microsoft Edge (EdgeHTML-based) on Windows 10 Version 1909 for x64-based Systemsv5Range: unspecified
- Microsoft/Microsoft Edge (EdgeHTML-based) on Windows Server 2016v5Range: unspecified
- Microsoft/Microsoft Edge (EdgeHTML-based) on Windows Server 2019v5Range: unspecified
Patches
112 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- github.com/advisories/GHSA-g3m9-qrfj-xw4gghsaADVISORY
- nvd.nist.gov/vuln/detail/CVE-2020-1073ghsaADVISORY
- github.com/chakra-core/ChakraCore/commit/82d3c4556a3cba13f0115fc98a91263b15fa6d07ghsaWEB
- github.com/chakra-core/ChakraCore/pull/6464ghsaWEB
- portal.msrc.microsoft.com/en-US/security-guidance/advisory/CVE-2020-1073ghsax_refsource_MISCWEB
News mentions
0No linked articles in our index yet.