Kaynağa Gözat

[1.11>master] [MERGE #5936 @MikeHolman] February 2019 Security Update

Merge pull request #5936 from MikeHolman:servicing/1902_1_11

February 2019 Security Update that addresses the following issues in ChakraCore:

CVE-2019-0590
CVE-2019-0591
CVE-2019-0593
CVE-2019-0605
CVE-2019-0607
CVE-2019-0610
CVE-2019-0640
CVE-2019-0642
CVE-2019-0644
CVE-2019-0648
CVE-2019-0649
CVE-2019-0651
CVE-2019-0655
CVE-2019-0658
Michael Holman 7 yıl önce
ebeveyn
işleme
b43772c080

+ 1 - 13
lib/Backend/CodeGenWorkItem.cpp

@@ -210,19 +210,7 @@ void CodeGenWorkItem::OnWorkItemProcessFail(NativeCodeGenerator* codeGen)
 #if PDATA_ENABLED & defined(_WIN32)
         if (this->entryPointInfo)
         {
-            XDataAllocation * xdataAllocation = this->entryPointInfo->GetNativeEntryPointData()->GetXDataInfo();
-            if (xdataAllocation)
-            {
-                void* functionTable = xdataAllocation->functionTable;
-                if (functionTable)
-                {
-                    if (!DelayDeletingFunctionTable::AddEntry(functionTable))
-                    {
-                        PHASE_PRINT_TESTTRACE1(Js::XDataPhase, _u("[%d]OnWorkItemProcessFail: Failed to add to slist, table: %llx\n"), GetCurrentThreadId(), functionTable);
-                        DelayDeletingFunctionTable::DeleteFunctionTable(functionTable);
-                    }
-                }
-            }
+            this->entryPointInfo->GetNativeEntryPointData()->CleanupXDataInfo();
         }
 #endif
         codeGen->FreeNativeCodeGenAllocation(this->allocation->allocation->address);

+ 2 - 2
lib/Backend/Func.cpp

@@ -1665,14 +1665,14 @@ Func::LinkCtorCacheToPropertyId(Js::PropertyId propertyId, JITTimeConstructorCac
 
 JITTimeConstructorCache* Func::GetConstructorCache(const Js::ProfileId profiledCallSiteId)
 {
-    Assert(profiledCallSiteId < GetJITFunctionBody()->GetProfiledCallSiteCount());
+    AssertOrFailFast(profiledCallSiteId < GetJITFunctionBody()->GetProfiledCallSiteCount());
     Assert(this->constructorCaches != nullptr);
     return this->constructorCaches[profiledCallSiteId];
 }
 
 void Func::SetConstructorCache(const Js::ProfileId profiledCallSiteId, JITTimeConstructorCache* constructorCache)
 {
-    Assert(profiledCallSiteId < GetJITFunctionBody()->GetProfiledCallSiteCount());
+    AssertOrFailFast(profiledCallSiteId < GetJITFunctionBody()->GetProfiledCallSiteCount());
     Assert(constructorCache != nullptr);
     Assert(this->constructorCaches != nullptr);
     Assert(this->constructorCaches[profiledCallSiteId] == nullptr);

+ 1 - 1
lib/Backend/FunctionJITTimeInfo.cpp

@@ -327,11 +327,11 @@ FunctionJITTimeInfo::GetRuntimeInfo() const
 ObjTypeSpecFldInfo *
 FunctionJITTimeInfo::GetObjTypeSpecFldInfo(uint index) const
 {
-    AssertOrFailFast(index < GetBody()->GetInlineCacheCount());
     if (m_data.objTypeSpecFldInfoArray == nullptr)
     {
         return nullptr;
     }
+    AssertOrFailFast(index < m_data.objTypeSpecFldInfoCount);
 
     return reinterpret_cast<ObjTypeSpecFldInfo *>(m_data.objTypeSpecFldInfoArray[index]);
 }

+ 15 - 10
lib/Backend/GlobOpt.cpp

@@ -2770,11 +2770,14 @@ GlobOpt::OptTagChecks(IR::Instr *instr)
                     ChangeValueType(nullptr, value, valueType.SetCanBeTaggedValue(false), true /*preserveSubClassInfo*/);
                     return false;
                 }
-                if (this->byteCodeUses)
+                if (!this->IsLoopPrePass())
                 {
-                    this->InsertByteCodeUses(instr);
+                    if (this->byteCodeUses)
+                    {
+                        this->InsertByteCodeUses(instr);
+                    }
+                    this->currentBlock->RemoveInstr(instr);
                 }
-                this->currentBlock->RemoveInstr(instr);
                 return true;
             }
 
@@ -5469,7 +5472,8 @@ GlobOpt::GetPrepassValueTypeForDst(
     IR::Instr *const instr,
     Value *const src1Value,
     Value *const src2Value,
-    bool const isValueInfoPrecise) const
+    bool const isValueInfoPrecise,
+    bool const isSafeToTransferInPrepass) const
 {
     // Values with definite types can be created in the loop prepass only when it is guaranteed that the value type will be the
     // same on any iteration of the loop. The heuristics currently used are:
@@ -5486,13 +5490,13 @@ GlobOpt::GetPrepassValueTypeForDst(
     Assert(IsLoopPrePass());
     Assert(instr);
 
-    if(!desiredValueType.IsDefinite())
-    {
-        return desiredValueType;
-    }
-
     if(!isValueInfoPrecise)
     {
+        if(!desiredValueType.IsDefinite())
+        {
+            return isSafeToTransferInPrepass ? desiredValueType : desiredValueType.SetCanBeTaggedValue(true);
+        }
+
         // If the desired value type is not precise, the value type of the destination is derived from the value types of the
         // sources. Since the value type of a source sym is not definite, the destination value type also cannot be definite.
         if(desiredValueType.IsInt() && OpCodeAttr::IsInt32(instr->m_opcode))
@@ -5505,6 +5509,7 @@ GlobOpt::GetPrepassValueTypeForDst(
             // The op always produces a number, but not always an int
             return desiredValueType.ToDefiniteAnyNumber();
         }
+        // Note: ToLikely() also sets CanBeTaggedValue
         return desiredValueType.ToLikely();
     }
 
@@ -5781,7 +5786,7 @@ GlobOpt::ValueNumberTransferDstInPrepass(IR::Instr *const instr, Value *const sr
     bool isSafeToTransferInPrepass = false;
     isValueInfoPrecise = IsPrepassSrcValueInfoPrecise(instr, src1Val, nullptr, &isSafeToTransferInPrepass);
     
-    const ValueType valueType(GetPrepassValueTypeForDst(src1ValueInfo->Type(), instr, src1Val, nullptr, isValueInfoPrecise));
+    const ValueType valueType(GetPrepassValueTypeForDst(src1ValueInfo->Type(), instr, src1Val, nullptr, isValueInfoPrecise, isSafeToTransferInPrepass));
     if(isValueInfoPrecise || isSafeToTransferInPrepass)
     {
         Assert(valueType == src1ValueInfo->Type());

+ 1 - 1
lib/Backend/GlobOpt.h

@@ -559,7 +559,7 @@ private:
     bool                    AreFromSameBytecodeFunc(IR::RegOpnd const* src1, IR::RegOpnd const* dst) const;
     Value *                 ValueNumberDst(IR::Instr **pInstr, Value *src1Val, Value *src2Val);
     Value *                 ValueNumberLdElemDst(IR::Instr **pInstr, Value *srcVal);
-    ValueType               GetPrepassValueTypeForDst(const ValueType desiredValueType, IR::Instr *const instr, Value *const src1Value, Value *const src2Value, bool const isValueInfoPreciseRef = false) const;
+    ValueType               GetPrepassValueTypeForDst(const ValueType desiredValueType, IR::Instr *const instr, Value *const src1Value, Value *const src2Value, bool const isValueInfoPreciseRef = false, bool const isSafeToTransferInPrepass = false) const;
     bool                    IsPrepassSrcValueInfoPrecise(IR::Opnd *const src, Value *const srcValue, bool * canTransferValueNumberToDst = nullptr) const;
     bool                    IsPrepassSrcValueInfoPrecise(IR::Instr *const instr, Value *const src1Value, Value *const src2Value, bool * canTransferValueNumberToDst = nullptr) const;
     bool                    IsSafeToTransferInPrepass(StackSym * const sym, ValueInfo *const srcValueInfo) const;

+ 31 - 20
lib/Backend/GlobOptFields.cpp

@@ -228,6 +228,11 @@ GlobOpt::KillLiveElems(IR::IndirOpnd * indirOpnd, BVSparse<JitArenaAllocator> *
         this->KillAllFields(bv); // This also kills all property type values, as the same bit-vector tracks those stack syms
         SetAnyPropertyMayBeWrittenTo();
     }
+    else if (inGlobOpt && indexOpnd && !indexOpnd->GetValueType().IsInt() && !currentBlock->globOptData.IsInt32TypeSpecialized(indexOpnd->m_sym))
+    {
+        // 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);
+    }
 }
 
 void
@@ -397,7 +402,8 @@ GlobOpt::ProcessFieldKills(IR::Instr *instr, BVSparse<JitArenaAllocator> *bv, bo
         KillLiveFields(this->lengthEquivBv, bv);
         if (inGlobOpt)
         {
-            KillObjectHeaderInlinedTypeSyms(this->currentBlock, false);
+            // Deleting an item, or pushing a property to a non-array, may change object layout
+            KillAllObjectTypes(bv);
         }
         break;
 
@@ -414,27 +420,32 @@ GlobOpt::ProcessFieldKills(IR::Instr *instr, BVSparse<JitArenaAllocator> *bv, bo
     case Js::OpCode::CallDirect:
         fnHelper = instr->GetSrc1()->AsHelperCallOpnd()->m_fnHelper;
 
-        // Kill length field for built-ins that can update it.
-        if(fnHelper == IR::JnHelperMethod::HelperArray_Shift 
-           || fnHelper == IR::JnHelperMethod::HelperArray_Splice
-           || fnHelper == IR::JnHelperMethod::HelperArray_Unshift)
+        switch (fnHelper)
         {
-            if (nullptr != this->lengthEquivBv)
-            {
-                KillLiveFields(this->lengthEquivBv, bv);
-            }
-            if (inGlobOpt)
-            {
-                KillObjectHeaderInlinedTypeSyms(this->currentBlock, false);
-            }
-        }
+            case IR::JnHelperMethod::HelperArray_Shift:
+            case IR::JnHelperMethod::HelperArray_Splice:
+            case IR::JnHelperMethod::HelperArray_Unshift:
+                // Kill length field for built-ins that can update it.
+                if (nullptr != this->lengthEquivBv)
+                {
+                    KillLiveFields(this->lengthEquivBv, bv);
+                }
+                // fall through
 
-        if ((fnHelper == IR::JnHelperMethod::HelperRegExp_Exec)
-           || (fnHelper == IR::JnHelperMethod::HelperString_Match)
-           || (fnHelper == IR::JnHelperMethod::HelperString_Replace))
-        {
-            // Consider: We may not need to kill all fields here.
-            this->KillAllFields(bv);
+            case IR::JnHelperMethod::HelperArray_Reverse:
+                // Deleting an item may change object layout
+                if (inGlobOpt)
+                {
+                    KillAllObjectTypes(bv);
+                }
+                break;
+
+            case IR::JnHelperMethod::HelperRegExp_Exec:
+            case IR::JnHelperMethod::HelperString_Match:
+            case IR::JnHelperMethod::HelperString_Replace:
+                // Consider: We may not need to kill all fields here.
+                this->KillAllFields(bv);
+                break;
         }
         break;
 

+ 9 - 1
lib/Backend/IRBuilder.cpp

@@ -724,6 +724,8 @@ IRBuilder::Build()
                     if (!this->RegIsTemp(dstRegSlot) && !this->RegIsConstant(dstRegSlot))
                     {
                         SymID symId = dstSym->m_id;
+
+                        AssertOrFailFast(symId < m_stSlots->Length());
                         if (this->m_stSlots->Test(symId))
                         {
                             // For jitted loop bodies that are in a try block, we consider any symbol that has a
@@ -4076,7 +4078,12 @@ IRBuilder::EnsureLoopBodyLoadSlot(SymID symId, bool isCatchObjectSym)
         return;
     }
     StackSym * symDst = StackSym::FindOrCreate(symId, (Js::RegSlot)symId, m_func);
-    if (symDst->m_isCatchObjectSym || this->m_ldSlots->TestAndSet(symId))
+    if (symDst->m_isCatchObjectSym)
+    {
+        return;
+    }
+    AssertOrFailFast(symId < m_ldSlots->Length());
+    if (this->m_ldSlots->TestAndSet(symId))
     {
         return;
     }
@@ -4120,6 +4127,7 @@ IRBuilder::SetLoopBodyStSlot(SymID symID, bool isCatchObjectSym)
             return;
         }
     }
+    AssertOrFailFast(symID < m_stSlots->Length());
     this->m_stSlots->Set(symID);
 }
 

+ 4 - 2
lib/Backend/IRBuilderAsmJs.cpp

@@ -3570,7 +3570,10 @@ IRBuilderAsmJs::BuildAsmJsLoopBodySlotOpnd(Js::RegSlot regSlot, IRType opndType)
 void
 IRBuilderAsmJs::EnsureLoopBodyAsmJsLoadSlot(Js::RegSlot regSlot, IRType type)
 {
-    if (GetJitLoopBodyData().GetLdSlots()->TestAndSet(regSlot))
+    BVFixed* ldSlotsBV = GetJitLoopBodyData().GetLdSlots();
+
+    AssertOrFailFast(regSlot < ldSlotsBV->Length());
+    if (ldSlotsBV->TestAndSet(regSlot))
     {
         return;
     }
@@ -3592,7 +3595,6 @@ void
 IRBuilderAsmJs::EnsureLoopBodyAsmJsStoreSlot(Js::RegSlot regSlot, IRType type)
 {
     Assert(!RegIsTemp(regSlot) || RegIsJitLoopYield(regSlot));
-    GetJitLoopBodyData().GetStSlots()->Set(regSlot);
     EnsureLoopBodyAsmJsLoadSlot(regSlot, type);
 }
 

+ 7 - 4
lib/Backend/IRBuilderAsmJs.h

@@ -26,7 +26,6 @@ struct JitLoopBodyData
 {
 private:
     BVFixed* m_ldSlots = nullptr;
-    BVFixed* m_stSlots = nullptr;
     StackSym* m_loopBodyRetIPSym = nullptr;
     BVFixed* m_yieldRegs = nullptr;
     uint32 m_loopCurRegs[WAsmJs::LIMIT];
@@ -36,7 +35,6 @@ public:
     {
         Assert(ldSlots && stSlots && loopBodyRetIPSym);
         m_ldSlots = ldSlots;
-        m_stSlots = stSlots;
         m_loopBodyRetIPSym = loopBodyRetIPSym;
     }
     // Use m_yieldRegs initialization to determine if m_loopCurRegs is initialized
@@ -57,14 +55,19 @@ public:
     }
     bool IsYieldReg(Js::RegSlot reg) const
     {
-        return  m_yieldRegs && m_yieldRegs->Test(reg);
+        if (!m_yieldRegs)
+        {
+            return false;
+        }
+        AssertOrFailFast(reg < m_yieldRegs->Length());
+        return m_yieldRegs->Test(reg);
     }
     void SetRegIsYield(Js::RegSlot reg)
     {
         Assert(m_yieldRegs);
+        AssertOrFailFast(reg < m_yieldRegs->Length());
         m_yieldRegs->Set(reg);
     }
-    BVFixed* GetStSlots() const { return m_stSlots; }
     BVFixed* GetLdSlots() const { return m_ldSlots; }
     StackSym* GetLoopBodyRetIPSym() const { return m_loopBodyRetIPSym; }
 

+ 3 - 9
lib/Backend/NativeEntryPointData.cpp

@@ -321,20 +321,14 @@ NativeEntryPointData::CleanupXDataInfo()
 {
     if (this->xdataInfo != nullptr)
     {
+        XDataAllocator::Unregister(this->xdataInfo);
 #ifdef _WIN32
         if (this->xdataInfo->functionTable
-            && !DelayDeletingFunctionTable::AddEntry(this->xdataInfo->functionTable))
+            && !DelayDeletingFunctionTable::AddEntry(this->xdataInfo))
         {
-            DelayDeletingFunctionTable::DeleteFunctionTable(this->xdataInfo->functionTable);
+            DelayDeletingFunctionTable::DeleteFunctionTable(this->xdataInfo);
         }
 #endif
-        XDataAllocator::Unregister(this->xdataInfo);
-#if defined(_M_ARM)
-        if (JITManager::GetJITManager()->IsOOPJITEnabled())
-#endif
-        {
-            HeapDelete(this->xdataInfo);
-        }
         this->xdataInfo = nullptr;
     }
 }

+ 1 - 3
lib/Backend/NativeEntryPointData.h

@@ -71,6 +71,7 @@ public:
 
 #if PDATA_ENABLED
     XDataAllocation* GetXDataInfo() { return this->xdataInfo; }
+    void CleanupXDataInfo();
     void SetXDataInfo(XDataAllocation* xdataInfo) { this->xdataInfo = xdataInfo; }   
 #endif
 private:
@@ -79,9 +80,6 @@ private:
     void FreePropertyGuards();
 
     void FreeNativeCode(Js::ScriptContext * scriptContext, bool isShutdown);
-#if PDATA_ENABLED
-    void CleanupXDataInfo();
-#endif
 
     FieldNoBarrier(Js::JavascriptMethod) nativeAddress;
     FieldNoBarrier(Js::JavascriptMethod) thunkAddress;

+ 1 - 2
lib/Backend/PDataManager.cpp

@@ -51,8 +51,7 @@ void PDataManager::UnregisterPdata(RUNTIME_FUNCTION* pdata)
 {
     if (AutoSystemInfo::Data.IsWin8OrLater())
     {
-        // TODO: need to move to background?
-        DelayDeletingFunctionTable::DeleteFunctionTable(pdata);
+        NtdllLibrary::Instance->DeleteGrowableFunctionTable(pdata);
     }
     else
     {

+ 2 - 0
lib/Common/Memory/Chakra.Common.Memory.vcxproj

@@ -26,6 +26,8 @@
     <ClCompile>
       <AdditionalIncludeDirectories>
         $(MSBuildThisFileDirectory);
+        $(MSBuildThisFileDirectory)..\..\JITClient;
+        $(ChakraJITIDLIntDir);
         $(MSBuildThisFileDirectory)..;
         %(AdditionalIncludeDirectories)
       </AdditionalIncludeDirectories>

+ 14 - 6
lib/Common/Memory/DelayDeletingFunctionTable.cpp

@@ -7,6 +7,7 @@
 #include "Memory/XDataAllocator.h"
 #if PDATA_ENABLED && defined(_WIN32)
 #include "Core/DelayLoadLibrary.h"
+#include "JITClient.h"
 #include <malloc.h>
 
 CriticalSection DelayDeletingFunctionTable::cs;
@@ -34,14 +35,14 @@ DelayDeletingFunctionTable::~DelayDeletingFunctionTable()
 }
 
 
-bool DelayDeletingFunctionTable::AddEntry(FunctionTableHandle ft)
+bool DelayDeletingFunctionTable::AddEntry(XDataAllocation* xdata)
 {
     if (Head)
     {
         FunctionTableNode* node = (FunctionTableNode*)_aligned_malloc(sizeof(FunctionTableNode), MEMORY_ALLOCATION_ALIGNMENT);
         if (node)
         {
-            node->functionTable = ft;
+            node->xdata = xdata;
             InterlockedPushEntrySList(Head, &(node->itemEntry));
             return true;
         }
@@ -61,7 +62,7 @@ void DelayDeletingFunctionTable::Clear()
         while (entry)
         {
             FunctionTableNode* list = (FunctionTableNode*)entry;
-            DeleteFunctionTable(list->functionTable);
+            DeleteFunctionTable(list->xdata);
             _aligned_free(entry);
             entry = InterlockedPopEntrySList(Head);
         }
@@ -73,9 +74,16 @@ bool DelayDeletingFunctionTable::IsEmpty()
     return QueryDepthSList(Head) == 0;
 }
 
-void DelayDeletingFunctionTable::DeleteFunctionTable(void* functionTable)
+void DelayDeletingFunctionTable::DeleteFunctionTable(XDataAllocation* xdata)
 {
-    NtdllLibrary::Instance->DeleteGrowableFunctionTable(functionTable);
-}
+    NtdllLibrary::Instance->DeleteGrowableFunctionTable(xdata->functionTable);
 
+#if defined(_M_ARM)
+    if (JITManager::GetJITManager()->IsOOPJITEnabled())
 #endif
+    {
+        HeapDelete(xdata);
+    }
+}
+
+#endif

+ 42 - 6
lib/Common/Memory/SectionAllocWrapper.cpp

@@ -6,7 +6,10 @@
 
 #if _WIN32
 #if ENABLE_OOP_NATIVE_CODEGEN
-#include "../Core/DelayLoadLibrary.h"
+#include "Core/DelayLoadLibrary.h"
+
+#include "XDataAllocator.h"
+#include "CustomHeap.h"
 
 #ifdef NTDDI_WIN10_RS2
 #if (NTDDI_VERSION >= NTDDI_WIN10_RS2)
@@ -603,6 +606,19 @@ SectionAllocWrapper::AllocPages(LPVOID requestAddress, size_t pageCount, DWORD a
         {
             return nullptr;
         }
+
+        // pages could be filled with debugbreak
+        // zero one page at a time to minimize working set impact while zeroing
+        for (size_t i = 0; i < dwSize / AutoSystemInfo::PageSize; ++i)
+        {
+            LPVOID localAddr = AllocLocal((char*)requestAddress + i * AutoSystemInfo::PageSize, AutoSystemInfo::PageSize);
+            if (localAddr == nullptr)
+            {
+                return nullptr;
+            }
+            ZeroMemory(localAddr, AutoSystemInfo::PageSize);
+            FreeLocal(localAddr);
+        }
         address = requestAddress;
     }
 
@@ -677,10 +693,10 @@ BOOL SectionAllocWrapper::Free(LPVOID lpAddress, size_t dwSize, DWORD dwFreeType
             {
                 return FALSE;
             }
-            ZeroMemory(localAddr, AutoSystemInfo::PageSize);
+
+            CustomHeap::FillDebugBreak((BYTE*)localAddr, AutoSystemInfo::PageSize);
             FreeLocal(localAddr);
         }
-        UnlockMemory(this->process, lpAddress, dwSize);
     }
 
     return TRUE;
@@ -928,6 +944,19 @@ LPVOID PreReservedSectionAllocWrapper::AllocPages(LPVOID lpAddress, DECLSPEC_GUA
 
             addressToReserve = (char*)lpAddress;
             freeSegmentsBVIndex = (uint)((addressToReserve - (char*)this->preReservedStartAddress) / AutoSystemInfo::Data.GetAllocationGranularityPageSize());
+
+            // pages could be filled with debugbreak
+            // zero one page at a time to minimize working set impact while zeroing
+            for (size_t i = 0; i < dwSize / AutoSystemInfo::PageSize; ++i)
+            {
+                LPVOID localAddr = AllocLocal((char*)lpAddress + i * AutoSystemInfo::PageSize, AutoSystemInfo::PageSize);
+                if (localAddr == nullptr)
+                {
+                    return nullptr;
+                }
+                ZeroMemory(localAddr, AutoSystemInfo::PageSize);
+                FreeLocal(localAddr);
+            }
 #if DBG
             uint numOfSegments = (uint)ceil((double)dwSize / (double)AutoSystemInfo::Data.GetAllocationGranularityPageSize());
             Assert(numOfSegments != 0);
@@ -978,12 +1007,17 @@ PreReservedSectionAllocWrapper::Free(LPVOID lpAddress, size_t dwSize, DWORD dwFr
         {
             return FALSE;
         }
-        ZeroMemory(localAddr, AutoSystemInfo::PageSize);
+        if ((dwFreeType & MEM_RELEASE) == MEM_RELEASE)
+        {
+            ZeroMemory(localAddr, AutoSystemInfo::PageSize);
+        }
+        else
+        {
+            CustomHeap::FillDebugBreak((BYTE*)localAddr, AutoSystemInfo::PageSize);
+        }
         FreeLocal(localAddr);
     }
 
-    UnlockMemory(this->process, lpAddress, dwSize);
-
     size_t requestedNumOfSegments = dwSize / AutoSystemInfo::Data.GetAllocationGranularityPageSize();
     Assert(requestedNumOfSegments <= MAXUINT32);
 
@@ -1000,6 +1034,8 @@ PreReservedSectionAllocWrapper::Free(LPVOID lpAddress, size_t dwSize, DWORD dwFr
         AssertMsg(freeSegmentsBVIndex < PreReservedAllocationSegmentCount, "Invalid Index ?");
         freeSegments.SetRange(freeSegmentsBVIndex, static_cast<uint>(requestedNumOfSegments));
         PreReservedHeapTrace(_u("MEM_RELEASE: Address: 0x%p of size: 0x%x * 0x%x bytes\n"), lpAddress, requestedNumOfSegments, AutoSystemInfo::Data.GetAllocationGranularityPageSize());
+
+        UnlockMemory(this->process, lpAddress, dwSize);
     }
 
     return TRUE;

+ 4 - 4
lib/Common/Memory/XDataAllocator.h

@@ -16,7 +16,7 @@
 struct FunctionTableNode
 {
     SLIST_ENTRY itemEntry;
-    FunctionTableHandle functionTable;
+    XDataAllocation* xdata;
 };
 
 struct DelayDeletingFunctionTable
@@ -28,9 +28,9 @@ struct DelayDeletingFunctionTable
     DelayDeletingFunctionTable();
     ~DelayDeletingFunctionTable();
 
-    static bool AddEntry(FunctionTableHandle ft);
+    static bool AddEntry(XDataAllocation* xdata);
     static void Clear();
     static bool IsEmpty();
-    static void DeleteFunctionTable(void* functionTable);
+    static void DeleteFunctionTable(XDataAllocation* xdata);
 };
-#endif
+#endif

+ 11 - 20
lib/Parser/RegexParser.cpp

@@ -2494,32 +2494,23 @@ namespace UnifiedRegex
             case 'W':
                 return false;
             case 'c':
-                if (standardEncodedChars->IsLetter(ECLookahead())) // terminating 0 is not a letter
+                if (!standardEncodedChars->IsLetter(ECLookahead())) //Letter set [A-Z, a-z]
+                {
+                    // Fail in unicode mode for non-letter escaped control characters according to 262 Annex-B RegExp grammar spec #prod-annexB-Term 
+                    DeferredFailIfUnicode(JSERR_RegExpInvalidEscape);
+                }
+
+                if (standardEncodedChars->IsWord(ECLookahead())) // word set [A-Z,a-z,0-9,_], terminating 0 is not a word character
                 {
                     singleton = UTC(Chars<EncodedChar>::CTU(ECLookahead()) % 32);
                     ECConsume();
                 }
                 else
                 {
-                    DeferredFailIfUnicode(JSERR_RegExpInvalidEscape); // Fail in unicode mode for non-letter escaped control characters according to 262 Annex-B RegExp grammar spec #prod-annexB-Term 
-
-                    if (!IsEOF())
-                    {
-                        EncodedChar ecLookahead = ECLookahead();
-                        switch (ecLookahead)
-                        {
-                        case '-':
-                        case ']':
-                            singleton = c;
-                            break;
-                        default:
-                            singleton = UTC(Chars<EncodedChar>::CTU(ecLookahead) % 32);
-                            ECConsume();
-                            break;
-                        }
-                    }
-                    else
-                        singleton = c;
+                    // If the lookahead is a non-alphanumeric and not an underscore ('_'), then treat '\' and 'c' separately.
+                    //#sec-regular-expression-patterns-semantics 
+                    ECRevert(1); //Put cursor back at 'c' and treat it as a non-escaped character.
+                    singleton = '\\';
                 }
                 return true;
             case 'x':

+ 6 - 0
lib/Runtime/ByteCode/ByteCodeGenerator.cpp

@@ -2964,6 +2964,12 @@ FuncInfo* PostVisitFunction(ParseNodeFnc* pnodeFnc, ByteCodeGenerator* byteCodeG
         Scope::MergeParamAndBodyScopes(pnodeFnc);
         Scope::RemoveParamScope(pnodeFnc);
     }
+    else
+    {
+        // A param and body scope exist for the same function, they
+        // should both either be using scope slots or scope objects.
+        Assert_FailFast(top->bodyScope->GetIsObject() == top->paramScope->GetIsObject());
+    }
 
     FuncInfo* const parentFunc = byteCodeGenerator->TopFuncInfo();
 

+ 10 - 3
lib/Runtime/ByteCode/Scope.cpp

@@ -69,11 +69,18 @@ void Scope::SetIsObject()
         });
     }
 
-    if (this->GetScopeType() == ScopeType_FunctionBody && funcInfo && !funcInfo->IsBodyAndParamScopeMerged()
-         && funcInfo->paramScope && !funcInfo->paramScope->GetIsObject())
+    // If the scope is split (there exists a body and param scope), then it is required that the
+    // body and param scope are marked as both requiring either a scope object or a scope slot.
+    if ((this->GetScopeType() == ScopeType_FunctionBody || this->GetScopeType() == ScopeType_Parameter)
+        && funcInfo && !funcInfo->IsBodyAndParamScopeMerged())
     {
-        // If this is split scope then mark the param scope also as an object
+        // The scope is split and one of the scopes (param or body) is being set 
+        // as an object, therefore set both the param and body scopes as objects.
+        Assert(funcInfo->paramScope);
         funcInfo->paramScope->SetIsObject();
+
+        Assert(funcInfo->bodyScope);
+        funcInfo->bodyScope->SetIsObject();
     }
 }
 

+ 44 - 27
lib/Runtime/Library/JavascriptArray.cpp

@@ -973,14 +973,13 @@ using namespace Js;
     Var JavascriptArray::OP_NewScIntArray(AuxArray<int32> *ints, ScriptContext* scriptContext)
     {
         JIT_HELPER_NOT_REENTRANT_HEADER(ScrArr_OP_NewScIntArray, reentrancylock, scriptContext->GetThreadContext());
-        uint32 count = ints->count;
-        JavascriptArray *arr = scriptContext->GetLibrary()->CreateArrayLiteral(count);
-        SparseArraySegment<Var> *head = SparseArraySegment<Var>::From(arr->head);
-        Assert(count > 0 && count == head->length);
-        for (uint i = 0; i < count; i++)
-        {
-            head->elements[i] = JavascriptNumber::ToVar(ints->elements[i], scriptContext);
-        }
+
+        JavascriptNativeIntArray *arr = scriptContext->GetLibrary()->CreateNativeIntArrayLiteral(ints->count);
+
+        SparseArraySegment<int32> * segment = (SparseArraySegment<int32>*)arr->GetHead();
+
+        JavascriptOperators::AddIntsToArraySegment(segment, ints);
+
         return arr;
         JIT_HELPER_END(ScrArr_OP_NewScIntArray);
     }
@@ -1033,7 +1032,16 @@ using namespace Js;
             return arr;
         }
 
-        return OP_NewScIntArray(ints, scriptContext);
+        JavascriptArray *arr = scriptContext->GetLibrary()->CreateArrayLiteral(count);
+        SparseArraySegment<Var> *head = SparseArraySegment<Var>::From(arr->head);
+        Assert(count > 0 && count == head->length);
+
+        for (uint i = 0; i < count; i++)
+        {
+            head->elements[i] = JavascriptNumber::ToVar(ints->elements[i], scriptContext);
+        }
+
+        return arr;
         JIT_HELPER_END(ScrArr_ProfiledNewScIntArray);
     }
 #endif
@@ -1041,23 +1049,13 @@ using namespace Js;
     Var JavascriptArray::OP_NewScFltArray(AuxArray<double> *doubles, ScriptContext* scriptContext)
     {
         JIT_HELPER_NOT_REENTRANT_HEADER(ScrArr_OP_NewScFltArray, reentrancylock, scriptContext->GetThreadContext());
-        uint32 count = doubles->count;
-        JavascriptArray *arr = scriptContext->GetLibrary()->CreateArrayLiteral(count);
-        SparseArraySegment<Var> *head = SparseArraySegment<Var>::From(arr->head);
-        Assert(count > 0 && count == head->length);
-        for (uint i = 0; i < count; i++)
-        {
-            double dval = doubles->elements[i];
-            int32 ival;
-            if (JavascriptNumber::TryGetInt32Value(dval, &ival) && !TaggedInt::IsOverflow(ival))
-            {
-                head->elements[i] = TaggedInt::ToVarUnchecked(ival);
-            }
-            else
-            {
-                head->elements[i] = JavascriptNumber::ToVarNoCheck(dval, scriptContext);
-            }
-        }
+
+        JavascriptNativeFloatArray *arr = scriptContext->GetLibrary()->CreateNativeFloatArrayLiteral(doubles->count);
+
+        SparseArraySegment<double> * segment = (SparseArraySegment<double>*)arr->GetHead();
+
+        JavascriptOperators::AddFloatsToArraySegment(segment, doubles);
+
         return arr;
         JIT_HELPER_END(ScrArr_OP_NewScFltArray);
     }
@@ -1080,7 +1078,26 @@ using namespace Js;
             return arr;
         }
 
-        return OP_NewScFltArray(doubles, scriptContext);
+        uint32 count = doubles->count;
+        JavascriptArray *arr = scriptContext->GetLibrary()->CreateArrayLiteral(count);
+        SparseArraySegment<Var> *head = SparseArraySegment<Var>::From(arr->head);
+        Assert(count > 0 && count == head->length);
+
+        for (uint i = 0; i < count; i++)
+        {
+            double dval = doubles->elements[i];
+            int32 ival;
+            if (JavascriptNumber::TryGetInt32Value(dval, &ival) && !TaggedInt::IsOverflow(ival))
+            {
+                head->elements[i] = TaggedInt::ToVarUnchecked(ival);
+            }
+            else
+            {
+                head->elements[i] = JavascriptNumber::ToVarNoCheck(dval, scriptContext);
+            }
+        }
+
+        return arr;
         JIT_HELPER_END(ScrArr_ProfiledNewScFltArray);
     }
 

+ 5 - 3
lib/Runtime/Library/JavascriptPromise.cpp

@@ -1125,15 +1125,17 @@ namespace Js
             sourcePromise->reactions->Prepend(pair);
             break;
         case PromiseStatusCode_HasResolution:
-            EnqueuePromiseReactionTask(resolveReaction, sourcePromise->result, scriptContext);
+            EnqueuePromiseReactionTask(resolveReaction, CrossSite::MarshalVar(scriptContext, sourcePromise->result), scriptContext);
             break;
         case PromiseStatusCode_HasRejection:
+        {
             if (!sourcePromise->GetIsHandled())
             {
-                scriptContext->GetLibrary()->CallNativeHostPromiseRejectionTracker(sourcePromise, sourcePromise->result, true);
+                scriptContext->GetLibrary()->CallNativeHostPromiseRejectionTracker(sourcePromise, CrossSite::MarshalVar(scriptContext, sourcePromise->result), true);
             }
-            EnqueuePromiseReactionTask(rejectReaction, sourcePromise->result, scriptContext);
+            EnqueuePromiseReactionTask(rejectReaction, CrossSite::MarshalVar(scriptContext, sourcePromise->result), scriptContext);
             break;
+        }
         default:
             AssertMsg(false, "Promise status is in an invalid state");
             break;

+ 2 - 2
lib/Runtime/Library/WebAssemblyInstance.cpp

@@ -245,10 +245,10 @@ Var WebAssemblyInstance::CreateExportObject(WebAssemblyModule * wasmModule, Scri
                 case Wasm::WasmTypes::I64:
                     JavascriptError::ThrowTypeErrorVar(wasmModule->GetScriptContext(), WASMERR_InvalidTypeConversion, _u("i64"), _u("Var"));
                 case Wasm::WasmTypes::F32:
-                    obj = JavascriptNumber::New(cnst.f32, scriptContext);
+                    obj = JavascriptNumber::NewWithCheck(cnst.f32, scriptContext);
                     break;
                 case Wasm::WasmTypes::F64:
-                    obj = JavascriptNumber::New(cnst.f64, scriptContext);
+                    obj = JavascriptNumber::NewWithCheck(cnst.f64, scriptContext);
                     break;
 #ifdef ENABLE_WASM_SIMD
                 case Wasm::WasmTypes::V128: