[MERGE #6087 @akroshg] April servicing update for ChakraCore

Merge pull request #6087 from akroshg:stage1904

Fixes
CVE-2019-0739
CVE-2019-0806
CVE-2019-0810
CVE-2019-0812
CVE-2019-0829
CVE-2019-0860
CVE-2019-0861
diff --git a/Build/NuGet/.pack-version b/Build/NuGet/.pack-version
index 29eb291..40faed9 100644
--- a/Build/NuGet/.pack-version
+++ b/Build/NuGet/.pack-version
@@ -1 +1 @@
-1.11.7
+1.11.8
diff --git a/lib/Backend/GlobOpt.cpp b/lib/Backend/GlobOpt.cpp
index f09edda..76af550 100644
--- a/lib/Backend/GlobOpt.cpp
+++ b/lib/Backend/GlobOpt.cpp
@@ -3258,10 +3258,14 @@
         }
         originalPropertySym = sym->AsPropertySym();
 
-        // Dont give a vale to 'arguments' property sym to prevent field copy prop of 'arguments'
+        // Don't give a value to 'arguments' property sym to prevent field copy prop of 'arguments'
         if (originalPropertySym->AsPropertySym()->m_propertyId == Js::PropertyIds::arguments &&
             originalPropertySym->AsPropertySym()->m_fieldKind == PropertyKindData)
         {
+            if (opnd->AsSymOpnd()->IsPropertySymOpnd())
+            {
+                this->FinishOptPropOp(instr, opnd->AsPropertySymOpnd());
+            }
             return nullptr;
         }
 
@@ -4813,7 +4817,7 @@
         }
         else
         {
-            return NewGenericValue(src1ValueInfo->Type().ToDefiniteAnyNumber(), dst);
+            return NewGenericValue(src1ValueInfo->Type().ToDefiniteAnyNumber().SetCanBeTaggedValue(true), dst);
         }
         break;
 
@@ -4874,7 +4878,7 @@
         {
             valueType = ValueType::Number;
         }
-        return CreateDstUntransferredValue(valueType, instr, src1Val, src2Val);
+        return CreateDstUntransferredValue(valueType.SetCanBeTaggedValue(true), instr, src1Val, src2Val);
     }
 
     case Js::OpCode::Add_A:
@@ -4908,12 +4912,12 @@
                     {
                         // If one of them is a float, the result probably is a float instead of just int
                         // but should always be a number.
-                        valueType = ValueType::Float;
+                        valueType = ValueType::Float.SetCanBeTaggedValue(true);
                     }
                     else
                     {
                         // Could be int, could be number
-                        valueType = ValueType::Number;
+                        valueType = ValueType::Number.SetCanBeTaggedValue(true);
                     }
                 }
                 else if (src1ValueInfo->IsLikelyFloat() || src2ValueInfo->IsLikelyFloat())
@@ -4937,7 +4941,7 @@
             && (src2Val && src2ValueInfo->IsNotString() && src2ValueInfo->IsPrimitive()))
         {
             // If src1 and src2 are not strings and primitive, add should yield a number.
-            valueType = ValueType::Number;
+            valueType = ValueType::Number.SetCanBeTaggedValue(true);
         }
         else if((src1Val && src1ValueInfo->IsLikelyString()) || (src2Val && src2ValueInfo->IsLikelyString()))
         {
@@ -4958,7 +4962,7 @@
             ValueType divValueType = GetDivValueType(instr, src1Val, src2Val, false);
             if (divValueType.IsLikelyInt() || divValueType.IsFloat())
             {
-                return CreateDstUntransferredValue(divValueType, instr, src1Val, src2Val);
+                return CreateDstUntransferredValue(divValueType.SetCanBeTaggedValue(true), instr, src1Val, src2Val);
             }
         }
         // fall-through
@@ -4990,11 +4994,11 @@
             // This should ideally be NewNumberAndLikelyFloatValue since we know the result is a number but not sure if it will
             // be a float value. However, that Number/LikelyFloat value type doesn't exist currently and all the necessary
             // checks are done for float values (tagged int checks, etc.) so it's sufficient to just create a float value here.
-            valueType = ValueType::Float;
+            valueType = ValueType::Float.SetCanBeTaggedValue(true);
         }
         else
         {
-            valueType = ValueType::Number;
+            valueType = ValueType::Number.SetCanBeTaggedValue(true);
         }
 
         return CreateDstUntransferredValue(valueType, instr, src1Val, src2Val);
diff --git a/lib/Backend/GlobOptFields.cpp b/lib/Backend/GlobOptFields.cpp
index 6a8007d..dbddb24 100644
--- a/lib/Backend/GlobOptFields.cpp
+++ b/lib/Backend/GlobOptFields.cpp
@@ -237,10 +237,17 @@
         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))
+    else if (inGlobOpt)
     {
-        // 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);
+        Value * indexValue = indexOpnd ? this->currentBlock->globOptData.FindValue(indexOpnd->GetSym()) : nullptr;
+        ValueInfo * indexValueInfo = indexValue ? indexValue->GetValueInfo() : nullptr;
+        int indexLowerBound = 0;
+
+        if (indirOpnd->GetOffset() < 0 || (indexOpnd && (!indexValueInfo || !indexValueInfo->TryGetIntConstantLowerBound(&indexLowerBound, false) || indexLowerBound < 0)))
+        {
+            // 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);
+        }
     }
 }
 
@@ -487,7 +494,9 @@
     case Js::OpCode::NewScObjectNoCtor:
         if (inGlobOpt)
         {
-            KillObjectHeaderInlinedTypeSyms(this->currentBlock, false);
+            // Opcodes that make an object into a prototype may break object-header-inlining and final type opt.
+            // Kill all known object layouts.
+            KillAllObjectTypes(bv);
         }
         break;
 
diff --git a/lib/Backend/JITType.cpp b/lib/Backend/JITType.cpp
index a207dc5..a235bd0 100644
--- a/lib/Backend/JITType.cpp
+++ b/lib/Backend/JITType.cpp
@@ -35,7 +35,7 @@
 
         Js::DynamicTypeHandler * handler = dynamicType->GetTypeHandler();
         data->handler.isObjectHeaderInlinedTypeHandler = handler->IsObjectHeaderInlinedTypeHandler();
-        data->handler.isLocked = handler->GetIsLocked();
+        data->handler.flags = handler->GetFlags();
         data->handler.inlineSlotCapacity = handler->GetInlineSlotCapacity();
         data->handler.offsetOfInlineSlots = handler->GetOffsetOfInlineSlots();
         data->handler.slotCapacity = handler->GetSlotCapacity();
diff --git a/lib/Backend/JITTypeHandler.cpp b/lib/Backend/JITTypeHandler.cpp
index aca726b..dbecfb9 100644
--- a/lib/Backend/JITTypeHandler.cpp
+++ b/lib/Backend/JITTypeHandler.cpp
@@ -19,7 +19,13 @@
 bool
 JITTypeHandler::IsLocked() const
 {
-    return m_data.isLocked != FALSE;
+    return Js::DynamicTypeHandler::GetIsLocked(m_data.flags);
+}
+
+bool
+JITTypeHandler::IsPrototype() const
+{
+    return Js::DynamicTypeHandler::GetIsPrototype(m_data.flags);
 }
 
 uint16
diff --git a/lib/Backend/JITTypeHandler.h b/lib/Backend/JITTypeHandler.h
index c6e909f..9d2cc35 100644
--- a/lib/Backend/JITTypeHandler.h
+++ b/lib/Backend/JITTypeHandler.h
@@ -12,6 +12,7 @@
 
     bool IsObjectHeaderInlinedTypeHandler() const;
     bool IsLocked() const;
+    bool IsPrototype() const;
 
     uint16 GetInlineSlotCapacity() const;
     uint16 GetOffsetOfInlineSlots() const;
diff --git a/lib/Backend/Lower.cpp b/lib/Backend/Lower.cpp
index cb3efbe..a5d19c4 100644
--- a/lib/Backend/Lower.cpp
+++ b/lib/Backend/Lower.cpp
@@ -6223,7 +6223,7 @@
 
     // Load the value from the slot, getting the slot ID from the cache.
     uint16 index = propertySymOpnd->GetSlotIndex();
-    Assert(index != -1);
+    AssertOrFailFast(index != (uint16)-1);
 
     if (opndSlotArray->IsRegOpnd())
     {
@@ -7204,7 +7204,7 @@
 
     // Store the value to the slot, getting the slot index from the cache.
     uint16 index = propertySymOpnd->GetSlotIndex();
-    Assert(index != -1);
+    AssertOrFailFast(index != (uint16)-1);
 
 #if defined(RECYCLER_WRITE_BARRIER_JIT) && (defined(_M_IX86) || defined(_M_AMD64))
     if (opndSlotArray->IsRegOpnd())
@@ -7353,6 +7353,19 @@
     {
         Assert(labelTypeCheckFailed == nullptr && labelBothTypeChecksFailed == nullptr);
         AssertMsg(!instrStFld->HasBailOutInfo(), "Why does a direct field store have bailout?");
+
+        if (propertySymOpnd->HasInitialType() && propertySymOpnd->HasFinalType())
+        {
+            bool isPrototypeTypeHandler = propertySymOpnd->GetInitialType()->GetTypeHandler()->IsPrototype();
+            if (isPrototypeTypeHandler)
+            {
+                LoadScriptContext(instrStFld);
+                m_lowererMD.LoadHelperArgument(instrStFld, IR::IntConstOpnd::New(propertySymOpnd->GetPropertyId(), TyInt32, m_func, true));
+                IR::Instr * invalidateCallInstr = IR::Instr::New(Js::OpCode::Call, m_func);
+                instrStFld->InsertBefore(invalidateCallInstr);
+                m_lowererMD.ChangeToHelperCall(invalidateCallInstr, IR::HelperInvalidateProtoCaches);
+            }
+        }
         instrStFld->Remove();
         return true;
     }
@@ -8177,6 +8190,16 @@
 
     // Now do the store.
     GenerateDirectFieldStore(instrStFld, propertySymOpnd);
+
+    bool isPrototypeTypeHandler = initialType->GetTypeHandler()->IsPrototype();
+    if (isPrototypeTypeHandler)
+    {
+        LoadScriptContext(instrStFld);
+        m_lowererMD.LoadHelperArgument(instrStFld, IR::IntConstOpnd::New(propertySymOpnd->GetPropertyId(), TyInt32, m_func, true));
+        IR::Instr * invalidateCallInstr = IR::Instr::New(Js::OpCode::Call, m_func);
+        instrStFld->InsertBefore(invalidateCallInstr);
+        m_lowererMD.ChangeToHelperCall(invalidateCallInstr, IR::HelperInvalidateProtoCaches);
+    }
 }
 
 bool
diff --git a/lib/Common/ChakraCoreVersion.h b/lib/Common/ChakraCoreVersion.h
index 80ab6ed..0ade5e4 100644
--- a/lib/Common/ChakraCoreVersion.h
+++ b/lib/Common/ChakraCoreVersion.h
@@ -17,7 +17,7 @@
 // ChakraCore version number definitions (used in ChakraCore binary metadata)
 #define CHAKRA_CORE_MAJOR_VERSION 1
 #define CHAKRA_CORE_MINOR_VERSION 11
-#define CHAKRA_CORE_PATCH_VERSION 7
+#define CHAKRA_CORE_PATCH_VERSION 8
 #define CHAKRA_CORE_VERSION_RELEASE_QFE 0 // Redundant with PATCH_VERSION. Keep this value set to 0.
 
 // -------------
diff --git a/lib/JITIDL/JITTypes.h b/lib/JITIDL/JITTypes.h
index 600a38b..8bc85a7 100644
--- a/lib/JITIDL/JITTypes.h
+++ b/lib/JITIDL/JITTypes.h
@@ -90,7 +90,7 @@
 typedef struct TypeHandlerIDL
 {
     IDL_Field(boolean) isObjectHeaderInlinedTypeHandler;
-    IDL_Field(boolean) isLocked;
+    IDL_Field(unsigned char) flags;
 
     IDL_Field(unsigned short) inlineSlotCapacity;
     IDL_Field(unsigned short) offsetOfInlineSlots;
diff --git a/lib/Runtime/Language/JavascriptOperators.cpp b/lib/Runtime/Language/JavascriptOperators.cpp
index 8d6d2ca..90f94b6 100644
--- a/lib/Runtime/Language/JavascriptOperators.cpp
+++ b/lib/Runtime/Language/JavascriptOperators.cpp
@@ -9582,6 +9582,11 @@
 
             Var result = CALL_ENTRYPOINT(threadContext, marshalledFunction->GetEntryPoint(), function, CallInfo(flags, 2), thisVar, putValue);
             Assert(result);
+
+            // Set implicit call flags so we bail out if we're trying to propagate the stored value forward. We can't count on the getter/setter
+            // to produce the stored value on a LdFld.
+            threadContext->AddImplicitCallFlags(ImplicitCall_Accessor);
+
             return nullptr;
         });
     }
diff --git a/lib/Runtime/Library/JavascriptRegExpConstructor.cpp b/lib/Runtime/Library/JavascriptRegExpConstructor.cpp
index e1d347b..2be4848 100644
--- a/lib/Runtime/Library/JavascriptRegExpConstructor.cpp
+++ b/lib/Runtime/Library/JavascriptRegExpConstructor.cpp
@@ -360,6 +360,10 @@
                 EnsureValues(); // The last match info relies on the last input. Use it before it is changed.
                 this->lastInput = tempInput;
             }
+
+            // Set implicit call flags since we are not necessarily making the original stored value available on re-load
+            // and are killing the store that backs two exposed properties.
+            this->GetScriptContext()->GetThreadContext()->AddImplicitCallFlags(ImplicitCall_Accessor);
             *result = true;
             return true;
         case PropertyIds::lastMatch:
diff --git a/lib/Runtime/Types/DictionaryTypeHandler.cpp b/lib/Runtime/Types/DictionaryTypeHandler.cpp
index 5da831b..e002554 100644
--- a/lib/Runtime/Types/DictionaryTypeHandler.cpp
+++ b/lib/Runtime/Types/DictionaryTypeHandler.cpp
@@ -139,7 +139,7 @@
                 PropertyString* propertyString = scriptContext->GetPropertyString(*propertyId);
                 *propertyStringName = propertyString;
                 T dataSlot = descriptor.template GetDataPropertyIndex<false>();
-                if (dataSlot != NoSlots && (attribs & PropertyWritable))
+                if (dataSlot != NoSlots && (attribs & PropertyWritable) && type == typeToEnumerate)
                 {
                     PropertyValueInfo::SetCacheInfo(info, propertyString, propertyString->GetLdElemInlineCache(), false);
                     SetPropertyValueInfo(info, instance, dataSlot, &descriptor);
diff --git a/lib/Runtime/Types/SimpleTypeHandler.cpp b/lib/Runtime/Types/SimpleTypeHandler.cpp
index 32e6d3f..dd08d12 100644
--- a/lib/Runtime/Types/SimpleTypeHandler.cpp
+++ b/lib/Runtime/Types/SimpleTypeHandler.cpp
@@ -328,7 +328,7 @@
                 *propertyStringName = propStr;
 
                 PropertyValueInfo::SetCacheInfo(info, propStr, propStr->GetLdElemInlineCache(), false);
-                if ((attribs & PropertyWritable) == PropertyWritable)
+                if ((attribs & PropertyWritable) == PropertyWritable && type == typeToEnumerate)
                 {
                     PropertyValueInfo::Set(info, instance, index, attribs);
                 }
diff --git a/lib/Runtime/Types/TypeHandler.h b/lib/Runtime/Types/TypeHandler.h
index 0feb677..6034bf3 100644
--- a/lib/Runtime/Types/TypeHandler.h
+++ b/lib/Runtime/Types/TypeHandler.h
@@ -348,13 +348,17 @@
              (v) Seal
             (vi) Freeze
         */
-        bool GetIsLocked() const { return (this->flags & IsLockedFlag) != 0; }
+        bool GetIsLocked() const { return GetIsLocked(this->flags); }
+        static bool GetIsLocked(byte flags) { return (flags & IsLockedFlag) != 0; }
 
         bool GetIsShared() const { return (this->flags & IsSharedFlag) != 0; }
         bool GetMayBecomeShared() const { return (this->flags & MayBecomeSharedFlag) != 0; }
         bool GetIsOrMayBecomeShared() const { return (this->flags & (MayBecomeSharedFlag | IsSharedFlag)) != 0; }
         bool GetHasKnownSlot0() const { return (this->flags & HasKnownSlot0Flag) != 0; }
-        bool GetIsPrototype() const { return (this->flags & IsPrototypeFlag) != 0; }
+
+        bool GetIsPrototype() const { return GetIsPrototype(this->flags); }
+        static bool GetIsPrototype(byte flags) { return (flags & IsPrototypeFlag) != 0; }
+
         bool GetIsInlineSlotCapacityLocked() const { return (this->propertyTypes & PropertyTypesInlineSlotCapacityLocked) != 0; }
 
         void LockTypeHandler() { Assert(IsLockable()); SetFlags(IsLockedFlag); }