瀏覽代碼

[CVE-2017-8751]Type confusion casting undefined with TypeOfPrototypeObjectDictionary type

Suwei Chen 8 年之前
父節點
當前提交
dbc1dbc0bd

+ 3 - 0
lib/Runtime/InternalPropertyList.h

@@ -6,6 +6,9 @@
 // They become nameless compile time known PropertyRecords, stored as static
 // fields on the InternalPropertyRecords class.
 
+// NOTE: When new property is added here, please evaluate if the property;s value needs to be restored to nullptr
+// when it gets reset to undefined inside DynamicObject::ResetObject()
+
 INTERNALPROPERTY(TypeOfPrototypeObjectInlined)     // Used to store the type of the prototype object in the prototype objects slots. Only DynamicTypes having TypeIds_Object are saved in this slot.
 // Used to store the type of the prototype object in the prototype objects slots. Everything else (except ExternalType) are stored in this slot as Dictionary.
 // Key in the Dictionary is combination of Type and TypeId and value is dynamicType object.

+ 0 - 2
lib/Runtime/Library/JavascriptWeakMap.cpp

@@ -37,8 +37,6 @@ namespace Js
 
         if (key->GetScriptContext()->GetLibrary()->GetUndefined() == weakMapKeyData)
         {
-            // Assert to find out where this can happen.
-            Assert(false);
             return nullptr;
         }
 

+ 7 - 0
lib/Runtime/Types/DynamicObject.cpp

@@ -715,6 +715,13 @@ namespace Js
             mutationBpValue = nullptr;
         }
 
+        // If value of TypeOfPrototypeObjectDictionary was set undefined above, reset it to nullptr so we don't type cast it wrongly to TypeTransitionMap* or we don't marshal the non-Var dictionary below
+        Var typeTransitionMap = nullptr;
+        if (this->GetInternalProperty(this, InternalPropertyIds::TypeOfPrototypeObjectDictionary, &typeTransitionMap, nullptr, this->GetScriptContext()))
+        {
+            this->SetInternalProperty(InternalPropertyIds::TypeOfPrototypeObjectDictionary, nullptr, PropertyOperation_Force, nullptr);
+        }
+
         if (keepProperties)
         {
             this->GetTypeHandler()->MarshalAllPropertiesToScriptContext(this, this->GetScriptContext(), false);

+ 2 - 2
lib/Runtime/Types/PathTypeHandler.cpp

@@ -1550,9 +1550,9 @@ namespace Js
         char16 reason[1024];
         swprintf_s(reason, 1024, _u("Cache not populated."));
 #endif
-        if (useCache && newPrototype->GetInternalProperty(newPrototype, Js::InternalPropertyIds::TypeOfPrototypeObjectDictionary, (Js::Var*)&oldTypeToPromotedTypeMap, nullptr, scriptContext))
+        if (useCache && newPrototype->GetInternalProperty(newPrototype, Js::InternalPropertyIds::TypeOfPrototypeObjectDictionary, (Js::Var*)&oldTypeToPromotedTypeMap, nullptr, scriptContext) && oldTypeToPromotedTypeMap != nullptr)
         {
-            Assert(oldTypeToPromotedTypeMap && (Js::Var)oldTypeToPromotedTypeMap != scriptContext->GetLibrary()->GetUndefined());
+            AssertOrFailFast((Js::Var)oldTypeToPromotedTypeMap != scriptContext->GetLibrary()->GetUndefined());
             oldTypeToPromotedTypeMap = reinterpret_cast<TypeTransitionMap*>(oldTypeToPromotedTypeMap);
 
             if (oldTypeToPromotedTypeMap->TryGetValue(oldType, &cachedDynamicType))