Skip to content

Commit 1f38e6b

Browse files
committed
[MERGE #5940 @MikeHolman] [CVE-2019-0652] Chakracore Tianfucup Arguments UaF - Tencent
Merge pull request #5940 from MikeHolman:deepcopybug
2 parents b184230 + ea97a60 commit 1f38e6b

19 files changed

+175
-6
lines changed

lib/Runtime/Types/DeferredTypeHandler.h

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,11 @@ namespace Js
2020
// be certain that the type has only writable data properties.
2121
}
2222

23+
DeferredTypeHandlerBase(DeferredTypeHandlerBase * typeHandler) : DynamicTypeHandler(typeHandler)
24+
{
25+
Assert(this->GetIsInlineSlotCapacityLocked() == typeHandler->GetIsInlineSlotCapacityLocked());
26+
Assert(this->GetHasOnlyWritableDataProperties() == typeHandler->GetHasOnlyWritableDataProperties());
27+
}
2328
public:
2429
void ConvertFunction(JavascriptFunction * instance, DynamicTypeHandler * handler);
2530
void Convert(DynamicObject * instance, DeferredInitializeMode mode, int initSlotCapacity, BOOL hasAccessor = false);
@@ -75,10 +80,15 @@ namespace Js
7580

7681
private:
7782
DeferredTypeHandler() : DeferredTypeHandlerBase(isPrototypeTemplate, _inlineSlotCapacity, _offsetOfInlineSlots), m_initializer(initializer) { }
83+
DeferredTypeHandler(DeferredTypeHandler * typeHandler) :
84+
DeferredTypeHandlerBase(typeHandler),
85+
m_initializer(typeHandler->m_initializer)
86+
{}
7887

7988
public:
8089
static DeferredTypeHandler *GetDefaultInstance() { return &defaultInstance; }
8190

91+
virtual DynamicTypeHandler * Clone(Recycler* recycler);
8292
virtual BOOL IsLockable() const override { return true; }
8393
virtual BOOL IsSharable() const override { return true; }
8494
virtual int GetPropertyCount() override;
@@ -156,6 +166,12 @@ namespace Js
156166
template <DeferredTypeInitializer initializer, typename DeferredTypeFilter, bool isPrototypeTemplate, uint16 _inlineSlotCapacity, uint16 _offsetOfInlineSlots>
157167
DeferredTypeHandler<initializer, DeferredTypeFilter, isPrototypeTemplate, _inlineSlotCapacity, _offsetOfInlineSlots> DeferredTypeHandler<initializer, DeferredTypeFilter, isPrototypeTemplate, _inlineSlotCapacity, _offsetOfInlineSlots>::defaultInstance;
158168

169+
template <DeferredTypeInitializer initializer, typename DeferredTypeFilter, bool isPrototypeTemplate, uint16 _inlineSlotCapacity, uint16 _offsetOfInlineSlots>
170+
DynamicTypeHandler * DeferredTypeHandler<initializer, DeferredTypeFilter, isPrototypeTemplate, _inlineSlotCapacity, _offsetOfInlineSlots>::Clone(Recycler * recycler)
171+
{
172+
return RecyclerNew(recycler, DeferredTypeHandler, this);
173+
}
174+
159175
template <DeferredTypeInitializer initializer, typename DeferredTypeFilter, bool isPrototypeTemplate, uint16 _inlineSlotCapacity, uint16 _offsetOfInlineSlots>
160176
int DeferredTypeHandler<initializer, DeferredTypeFilter, isPrototypeTemplate, _inlineSlotCapacity, _offsetOfInlineSlots>::GetPropertyCount()
161177
{

lib/Runtime/Types/DictionaryTypeHandler.cpp

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,24 @@ namespace Js
5353
CopyPropertyTypes(PropertyTypesWritableDataOnly | PropertyTypesWritableDataOnlyDetection | PropertyTypesInlineSlotCapacityLocked | PropertyTypesHasSpecialProperties, typeHandler->GetPropertyTypes());
5454
}
5555

56+
template <typename T>
57+
DictionaryTypeHandlerBase<T>::DictionaryTypeHandlerBase(Recycler* recycler, DictionaryTypeHandlerBase * typeHandler) :
58+
DynamicTypeHandler(typeHandler),
59+
nextPropertyIndex(typeHandler->nextPropertyIndex)
60+
#if ENABLE_FIXED_FIELDS
61+
, singletonInstance(nullptr)
62+
#endif
63+
{
64+
Assert(this->GetIsInlineSlotCapacityLocked() == typeHandler->GetIsInlineSlotCapacityLocked());
65+
propertyMap = typeHandler->propertyMap->Clone();
66+
}
67+
68+
template <typename T>
69+
DynamicTypeHandler * DictionaryTypeHandlerBase<T>::Clone(Recycler * recycler)
70+
{
71+
return RecyclerNew(recycler, DictionaryTypeHandlerBase, recycler, this);
72+
}
73+
5674
template <typename T>
5775
int DictionaryTypeHandlerBase<T>::GetPropertyCount()
5876
{

lib/Runtime/Types/DictionaryTypeHandler.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ namespace Js
4646
DictionaryTypeHandlerBase(Recycler* recycler);
4747
DictionaryTypeHandlerBase(Recycler* recycler, int slotCapacity, uint16 inlineSlotCapacity, uint16 offsetOfInlineSlots);
4848
DictionaryTypeHandlerBase(DictionaryTypeHandlerBase* typeHandler);
49+
DictionaryTypeHandlerBase(Recycler* recycler, DictionaryTypeHandlerBase * typeHandler);
4950
DEFINE_VTABLE_CTOR_NO_REGISTER(DictionaryTypeHandlerBase, DynamicTypeHandler);
5051

5152
// Create a new type handler for a future DynamicObject. This is for public usage. "initialCapacity" indicates desired slotCapacity, subject to alignment round up.
@@ -62,6 +63,8 @@ namespace Js
6263
// Create a new type handler for a future DynamicObject. This is for public usage. "initialCapacity" indicates desired slotCapacity, subject to alignment round up.
6364
static DictionaryTypeHandlerBase* New(Recycler * recycler, int initialCapacity, uint16 inlineSlotCapacity, uint16 offsetOfInlineSlots);
6465

66+
virtual DynamicTypeHandler * Clone(Recycler * recycler);
67+
6568
BOOL IsBigDictionaryTypeHandler();
6669

6770
virtual BOOL IsLockable() const override { return false; }

lib/Runtime/Types/DynamicObject.cpp

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,14 @@ namespace Js
5151
auxSlots(instance->auxSlots),
5252
objectArray(instance->objectArray) // copying the array should copy the array flags and array call site index as well
5353
{
54+
if (deepCopy)
55+
{
56+
if (!instance->GetDynamicType()->ShareType())
57+
{
58+
this->type = instance->DuplicateTypeAndTypeHandler();
59+
}
60+
}
61+
5462
DynamicTypeHandler * typeHandler = this->GetTypeHandler();
5563

5664
// TODO: stack allocate aux Slots
@@ -526,6 +534,13 @@ namespace Js
526534
return RecyclerNew(GetRecycler(), DynamicType, this->GetDynamicType());
527535
}
528536

537+
DynamicType* DynamicObject::DuplicateTypeAndTypeHandler()
538+
{
539+
DynamicType * newType = DuplicateType();
540+
newType->typeHandler = newType->DuplicateTypeHandler();
541+
return newType;
542+
}
543+
529544
void DynamicObject::PrepareForConversionToNonPathType()
530545
{
531546
// Nothing to do in base class

lib/Runtime/Types/DynamicObject.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -304,6 +304,7 @@ namespace Js
304304
virtual BOOL IsCrossSiteObject() const { return FALSE; }
305305

306306
virtual DynamicType* DuplicateType();
307+
DynamicType* DuplicateTypeAndTypeHandler();
307308
virtual void PrepareForConversionToNonPathType();
308309
static bool IsTypeHandlerCompatibleForObjectHeaderInlining(DynamicTypeHandler * oldTypeHandler, DynamicTypeHandler * newTypeHandler);
309310

lib/Runtime/Types/DynamicType.cpp

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -150,7 +150,7 @@ namespace Js
150150
Assert(this->GetTypeHandler()->IsSharable());
151151
return true;
152152
}
153-
if (this->GetTypeHandler()->IsSharable())
153+
if (this->GetTypeHandler()->IsSharable() && this->GetTypeHandler()->GetMayBecomeShared())
154154
{
155155
LockType();
156156
this->GetTypeHandler()->ShareTypeHandler(this->GetScriptContext());
@@ -160,6 +160,11 @@ namespace Js
160160
return false;
161161
}
162162

163+
DynamicTypeHandler * DynamicType::DuplicateTypeHandler()
164+
{
165+
return GetTypeHandler()->Clone(this->GetRecycler());
166+
}
167+
163168
bool
164169
DynamicType::SetHasNoEnumerableProperties(bool value)
165170
{

lib/Runtime/Types/DynamicType.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ namespace Js
4040

4141
public:
4242
DynamicTypeHandler * GetTypeHandler() const { return typeHandler; }
43+
DynamicTypeHandler * DuplicateTypeHandler();
4344

4445
void SetPrototype(RecyclableObject* newPrototype) { this->prototype = newPrototype; }
4546
bool GetIsLocked() const { return this->isLocked; }

lib/Runtime/Types/ES5ArrayTypeHandler.cpp

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,28 @@ namespace Js
1414
indexPropertyMap = RecyclerNew(recycler, InnerMap, recycler);
1515
}
1616

17+
IndexPropertyDescriptorMap::IndexPropertyDescriptorMap(Recycler* recycler, const IndexPropertyDescriptorMap * const indexPropertyDescriptorMap)
18+
: recycler(recycler), lastIndexAt(indexPropertyDescriptorMap->lastIndexAt)
19+
{
20+
indexList = indexPropertyDescriptorMap->CopyIndexList();
21+
indexPropertyMap = indexPropertyDescriptorMap->indexPropertyMap->Clone();
22+
}
23+
24+
IndexPropertyDescriptorMap * IndexPropertyDescriptorMap::Clone(Recycler * recycler)
25+
{
26+
return RecyclerNew(recycler, IndexPropertyDescriptorMap, recycler, this);
27+
}
28+
29+
uint32 * IndexPropertyDescriptorMap::CopyIndexList() const
30+
{
31+
uint32 * newList = RecyclerNewArrayLeaf(recycler, uint32, Count());
32+
for (int i = 0; i < Count(); i++)
33+
{
34+
newList[i] = this->indexList[i];
35+
}
36+
return newList;
37+
}
38+
1739
void IndexPropertyDescriptorMap::Add(uint32 key, const IndexPropertyDescriptor& value)
1840
{
1941
if (indexPropertyMap->Count() >= (INT_MAX / 2))
@@ -215,6 +237,21 @@ namespace Js
215237
indexPropertyMap = RecyclerNew(recycler, IndexPropertyDescriptorMap, recycler);
216238
}
217239

240+
template <class T>
241+
ES5ArrayTypeHandlerBase<T>::ES5ArrayTypeHandlerBase(Recycler* recycler, ES5ArrayTypeHandlerBase<T>* typeHandler)
242+
: DictionaryTypeHandlerBase<T>(recycler, typeHandler)
243+
{
244+
dataItemAttributes = typeHandler->dataItemAttributes;
245+
lengthWritable = typeHandler->lengthWritable;
246+
indexPropertyMap = typeHandler->indexPropertyMap->Clone(recycler);
247+
}
248+
249+
template <class T>
250+
DynamicTypeHandler * ES5ArrayTypeHandlerBase<T>::Clone(Recycler * recycler)
251+
{
252+
return RecyclerNew(recycler, ES5ArrayTypeHandlerBase, recycler, this);
253+
}
254+
218255
template <class T>
219256
void ES5ArrayTypeHandlerBase<T>::SetIsPrototype(DynamicObject * instance)
220257
{

lib/Runtime/Types/ES5ArrayTypeHandler.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,9 +43,11 @@ namespace Js
4343

4444
private:
4545
void EnsureIndexList();
46+
uint32 * CopyIndexList() const;
4647

4748
public:
4849
IndexPropertyDescriptorMap(Recycler* recycler);
50+
IndexPropertyDescriptorMap(Recycler* recycler, const IndexPropertyDescriptorMap * const indexPropertyDescriptorMap);
4951

5052
void Add(uint32 key, const IndexPropertyDescriptor& descriptor);
5153
bool TryGetLastIndex(uint32* lastIndex);
@@ -73,6 +75,7 @@ namespace Js
7375
{
7476
return indexPropertyMap->TryGetReference(key, value);
7577
}
78+
IndexPropertyDescriptorMap * Clone(Recycler * recycler);
7679

7780
private:
7881
static int __cdecl CompareIndex(const void* left, const void* right)
@@ -110,6 +113,7 @@ namespace Js
110113
ES5ArrayTypeHandlerBase(Recycler* recycler);
111114
ES5ArrayTypeHandlerBase(Recycler* recycler, int slotCapacity, uint16 inlineSlotCapacity, uint16 offsetOfInlineSlots);
112115
ES5ArrayTypeHandlerBase(Recycler* recycler, DictionaryTypeHandlerBase<T>* typeHandler);
116+
ES5ArrayTypeHandlerBase(Recycler* recycler, ES5ArrayTypeHandlerBase * typeHandler);
113117
DEFINE_VTABLE_CTOR_NO_REGISTER(ES5ArrayTypeHandlerBase, DictionaryTypeHandlerBase<T>);
114118

115119
// This constructor is used to grow small ES5ArrayTypeHandler into BigES5ArrayTypeHandler. We simply take over all own fields here
@@ -158,6 +162,7 @@ namespace Js
158162
BOOL GetItemAccessors(ES5Array* arr, DynamicObject* instance, uint32 index, Var* getter, Var* setter);
159163

160164
public:
165+
virtual DynamicTypeHandler * Clone(Recycler * recyler);
161166
virtual BOOL HasProperty(DynamicObject* instance, PropertyId propertyId, bool *noRedecl = nullptr, _Inout_opt_ PropertyValueInfo* info = nullptr) override;
162167
virtual BOOL HasProperty(DynamicObject* instance, JavascriptString* propertyNameString) override;
163168
virtual BOOL GetProperty(DynamicObject* instance, Var originalInstance, PropertyId propertyId, Var* value, PropertyValueInfo* info, ScriptContext* requestContext) override;

lib/Runtime/Types/MissingPropertyTypeHandler.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,11 @@ namespace Js
1515
MissingPropertyTypeHandler::MissingPropertyTypeHandler() :
1616
DynamicTypeHandler(1, 1, (uint16)sizeof(DynamicObject)) {}
1717

18+
DynamicTypeHandler * MissingPropertyTypeHandler::Clone(Recycler * recycler)
19+
{
20+
return RecyclerNew(recycler, MissingPropertyTypeHandler);
21+
}
22+
1823
PropertyId MissingPropertyTypeHandler::GetPropertyId(ScriptContext* scriptContext, PropertyIndex index)
1924
{
2025
return Constants::NoProperty;

0 commit comments

Comments
 (0)