Title: [240456] trunk/Source/_javascript_Core
Revision
240456
Author
[email protected]
Date
2019-01-24 16:49:44 -0800 (Thu, 24 Jan 2019)

Log Message

[JSC] SharedArrayBufferConstructor and ArrayBufferConstructor should not have their own IsoSubspace
https://bugs.webkit.org/show_bug.cgi?id=193774

Reviewed by Mark Lam.

We put all the instances of InternalFunction and its subclasses in IsoSubspace to make safer from UAF.
But since IsoSubspace requires the memory layout of instances is the same, we created different IsoSubspace
for subclasses of InternalFunction if sizeof(subclass) != sizeof(InternalFunction). One example is
ArrayBufferConstructor and SharedArrayBufferConstructor. But it is too costly to allocate 16KB page just
for these two constructor instances. They are only two instances per JSGlobalObject.

This patch makes sizeof(ArrayBufferConstructor) == sizeof(InternalFunction) so that they can use IsoSubspace
of InternalFunction. We introduce JSGenericArrayBufferConstructor, and it takes ArrayBufferSharingMode as
its template parameter. We define JSArrayBufferConstructor as JSGenericArrayBufferConstructor<ArrayBufferSharingMode::Default>
and JSSharedArrayBufferConstructor as JSGenericArrayBufferConstructor<ArrayBufferSharingMode::Shared> so that
we do not need to hold ArrayBufferSharingMode in the field of the constructor. This change removes IsoSubspace
for ArrayBufferConstructors, and reduces the memory usage.

* runtime/JSArrayBufferConstructor.cpp:
(JSC::JSGenericArrayBufferConstructor<sharingMode>::JSGenericArrayBufferConstructor):
(JSC::JSGenericArrayBufferConstructor<sharingMode>::finishCreation):
(JSC::JSGenericArrayBufferConstructor<sharingMode>::constructArrayBuffer):
(JSC::JSGenericArrayBufferConstructor<sharingMode>::createStructure):
(JSC::JSGenericArrayBufferConstructor<sharingMode>::info):
(JSC::JSArrayBufferConstructor::JSArrayBufferConstructor): Deleted.
(JSC::JSArrayBufferConstructor::finishCreation): Deleted.
(JSC::JSArrayBufferConstructor::create): Deleted.
(JSC::JSArrayBufferConstructor::createStructure): Deleted.
(JSC::constructArrayBuffer): Deleted.
* runtime/JSArrayBufferConstructor.h:
* runtime/JSGlobalObject.cpp:
(JSC::JSGlobalObject::init):
* runtime/JSGlobalObject.h:
* runtime/VM.cpp:
(JSC::VM::VM):
* runtime/VM.h:

Modified Paths

Diff

Modified: trunk/Source/_javascript_Core/ChangeLog (240455 => 240456)


--- trunk/Source/_javascript_Core/ChangeLog	2019-01-25 00:35:19 UTC (rev 240455)
+++ trunk/Source/_javascript_Core/ChangeLog	2019-01-25 00:49:44 UTC (rev 240456)
@@ -1,5 +1,44 @@
 2019-01-24  Yusuke Suzuki  <[email protected]>
 
+        [JSC] SharedArrayBufferConstructor and ArrayBufferConstructor should not have their own IsoSubspace
+        https://bugs.webkit.org/show_bug.cgi?id=193774
+
+        Reviewed by Mark Lam.
+
+        We put all the instances of InternalFunction and its subclasses in IsoSubspace to make safer from UAF.
+        But since IsoSubspace requires the memory layout of instances is the same, we created different IsoSubspace
+        for subclasses of InternalFunction if sizeof(subclass) != sizeof(InternalFunction). One example is
+        ArrayBufferConstructor and SharedArrayBufferConstructor. But it is too costly to allocate 16KB page just
+        for these two constructor instances. They are only two instances per JSGlobalObject.
+
+        This patch makes sizeof(ArrayBufferConstructor) == sizeof(InternalFunction) so that they can use IsoSubspace
+        of InternalFunction. We introduce JSGenericArrayBufferConstructor, and it takes ArrayBufferSharingMode as
+        its template parameter. We define JSArrayBufferConstructor as JSGenericArrayBufferConstructor<ArrayBufferSharingMode::Default>
+        and JSSharedArrayBufferConstructor as JSGenericArrayBufferConstructor<ArrayBufferSharingMode::Shared> so that
+        we do not need to hold ArrayBufferSharingMode in the field of the constructor. This change removes IsoSubspace
+        for ArrayBufferConstructors, and reduces the memory usage.
+
+        * runtime/JSArrayBufferConstructor.cpp:
+        (JSC::JSGenericArrayBufferConstructor<sharingMode>::JSGenericArrayBufferConstructor):
+        (JSC::JSGenericArrayBufferConstructor<sharingMode>::finishCreation):
+        (JSC::JSGenericArrayBufferConstructor<sharingMode>::constructArrayBuffer):
+        (JSC::JSGenericArrayBufferConstructor<sharingMode>::createStructure):
+        (JSC::JSGenericArrayBufferConstructor<sharingMode>::info):
+        (JSC::JSArrayBufferConstructor::JSArrayBufferConstructor): Deleted.
+        (JSC::JSArrayBufferConstructor::finishCreation): Deleted.
+        (JSC::JSArrayBufferConstructor::create): Deleted.
+        (JSC::JSArrayBufferConstructor::createStructure): Deleted.
+        (JSC::constructArrayBuffer): Deleted.
+        * runtime/JSArrayBufferConstructor.h:
+        * runtime/JSGlobalObject.cpp:
+        (JSC::JSGlobalObject::init):
+        * runtime/JSGlobalObject.h:
+        * runtime/VM.cpp:
+        (JSC::VM::VM):
+        * runtime/VM.h:
+
+2019-01-24  Yusuke Suzuki  <[email protected]>
+
         stress/const-semantics.js fails a dfg-eager / ftl-eager run with an ASAN release build.
         https://bugs.webkit.org/show_bug.cgi?id=190693
 

Modified: trunk/Source/_javascript_Core/runtime/JSArrayBufferConstructor.cpp (240455 => 240456)


--- trunk/Source/_javascript_Core/runtime/JSArrayBufferConstructor.cpp	2019-01-25 00:35:19 UTC (rev 240455)
+++ trunk/Source/_javascript_Core/runtime/JSArrayBufferConstructor.cpp	2019-01-25 00:49:44 UTC (rev 240456)
@@ -38,29 +38,35 @@
 namespace JSC {
 
 static EncodedJSValue JSC_HOST_CALL arrayBufferFuncIsView(ExecState*);
+static EncodedJSValue JSC_HOST_CALL callArrayBuffer(ExecState*);
 
+template<>
 const ClassInfo JSArrayBufferConstructor::s_info = {
     "Function", &Base::s_info, nullptr, nullptr,
     CREATE_METHOD_TABLE(JSArrayBufferConstructor)
 };
 
-static EncodedJSValue JSC_HOST_CALL callArrayBuffer(ExecState*);
-static EncodedJSValue JSC_HOST_CALL constructArrayBuffer(ExecState*);
+template<>
+const ClassInfo JSSharedArrayBufferConstructor::s_info = {
+    "Function", &Base::s_info, nullptr, nullptr,
+    CREATE_METHOD_TABLE(JSSharedArrayBufferConstructor)
+};
 
-JSArrayBufferConstructor::JSArrayBufferConstructor(VM& vm, Structure* structure, ArrayBufferSharingMode sharingMode)
-    : Base(vm, structure, callArrayBuffer, constructArrayBuffer)
-    , m_sharingMode(sharingMode)
+template<ArrayBufferSharingMode sharingMode>
+JSGenericArrayBufferConstructor<sharingMode>::JSGenericArrayBufferConstructor(VM& vm, Structure* structure)
+    : Base(vm, structure, callArrayBuffer, JSGenericArrayBufferConstructor<sharingMode>::constructArrayBuffer)
 {
 }
 
-void JSArrayBufferConstructor::finishCreation(VM& vm, JSArrayBufferPrototype* prototype, GetterSetter* speciesSymbol)
+template<ArrayBufferSharingMode sharingMode>
+void JSGenericArrayBufferConstructor<sharingMode>::finishCreation(VM& vm, JSArrayBufferPrototype* prototype, GetterSetter* speciesSymbol)
 {
-    Base::finishCreation(vm, arrayBufferSharingModeName(m_sharingMode));
+    Base::finishCreation(vm, arrayBufferSharingModeName(sharingMode));
     putDirectWithoutTransition(vm, vm.propertyNames->prototype, prototype, PropertyAttribute::DontEnum | PropertyAttribute::DontDelete | PropertyAttribute::ReadOnly);
     putDirectWithoutTransition(vm, vm.propertyNames->length, jsNumber(1), PropertyAttribute::DontEnum | PropertyAttribute::ReadOnly);
     putDirectNonIndexAccessor(vm, vm.propertyNames->speciesSymbol, speciesSymbol, PropertyAttribute::Accessor | PropertyAttribute::ReadOnly | PropertyAttribute::DontEnum);
 
-    if (m_sharingMode == ArrayBufferSharingMode::Default) {
+    if (sharingMode == ArrayBufferSharingMode::Default) {
         JSGlobalObject* globalObject = this->globalObject(vm);
         JSC_NATIVE_FUNCTION_WITHOUT_TRANSITION(vm.propertyNames->isView, arrayBufferFuncIsView, static_cast<unsigned>(PropertyAttribute::DontEnum), 1);
         JSC_NATIVE_FUNCTION_WITHOUT_TRANSITION(vm.propertyNames->builtinNames().isViewPrivateName(), arrayBufferFuncIsView, static_cast<unsigned>(PropertyAttribute::DontEnum), 1);
@@ -67,31 +73,15 @@
     }
 }
 
-JSArrayBufferConstructor* JSArrayBufferConstructor::create(VM& vm, Structure* structure, JSArrayBufferPrototype* prototype, GetterSetter* speciesSymbol, ArrayBufferSharingMode sharingMode)
+template<ArrayBufferSharingMode sharingMode>
+EncodedJSValue JSC_HOST_CALL JSGenericArrayBufferConstructor<sharingMode>::constructArrayBuffer(ExecState* exec)
 {
-    JSArrayBufferConstructor* result =
-        new (NotNull, allocateCell<JSArrayBufferConstructor>(vm.heap))
-        JSArrayBufferConstructor(vm, structure, sharingMode);
-    result->finishCreation(vm, prototype, speciesSymbol);
-    return result;
-}
-
-Structure* JSArrayBufferConstructor::createStructure(
-    VM& vm, JSGlobalObject* globalObject, JSValue prototype)
-{
-    return Structure::create(
-        vm, globalObject, prototype, TypeInfo(InternalFunctionType, StructureFlags), info());
-}
-
-static EncodedJSValue JSC_HOST_CALL constructArrayBuffer(ExecState* exec)
-{
     VM& vm = exec->vm();
     auto scope = DECLARE_THROW_SCOPE(vm);
 
-    JSArrayBufferConstructor* constructor =
-        jsCast<JSArrayBufferConstructor*>(exec->jsCallee());
+    JSGenericArrayBufferConstructor* constructor = jsCast<JSGenericArrayBufferConstructor*>(exec->jsCallee());
 
-    Structure* arrayBufferStructure = InternalFunction::createSubclassStructure(exec, exec->newTarget(), constructor->globalObject(vm)->arrayBufferStructure(constructor->sharingMode()));
+    Structure* arrayBufferStructure = InternalFunction::createSubclassStructure(exec, exec->newTarget(), constructor->globalObject(vm)->arrayBufferStructure(sharingMode));
     RETURN_IF_EXCEPTION(scope, { });
 
     unsigned length;
@@ -109,14 +99,26 @@
     if (!buffer)
         return JSValue::encode(throwOutOfMemoryError(exec, scope));
     
-    if (constructor->sharingMode() == ArrayBufferSharingMode::Shared)
+    if (sharingMode == ArrayBufferSharingMode::Shared)
         buffer->makeShared();
-    ASSERT(constructor->sharingMode() == buffer->sharingMode());
+    ASSERT(sharingMode == buffer->sharingMode());
 
     JSArrayBuffer* result = JSArrayBuffer::create(vm, arrayBufferStructure, WTFMove(buffer));
     return JSValue::encode(result);
 }
 
+template<ArrayBufferSharingMode sharingMode>
+Structure* JSGenericArrayBufferConstructor<sharingMode>::createStructure(VM& vm, JSGlobalObject* globalObject, JSValue prototype)
+{
+    return Structure::create(vm, globalObject, prototype, TypeInfo(InternalFunctionType, StructureFlags), info());
+}
+
+template<ArrayBufferSharingMode sharingMode>
+const ClassInfo* JSGenericArrayBufferConstructor<sharingMode>::info()
+{
+    return &JSGenericArrayBufferConstructor<sharingMode>::s_info;
+}
+
 static EncodedJSValue JSC_HOST_CALL callArrayBuffer(ExecState* exec)
 {
     VM& vm = exec->vm();
@@ -131,7 +133,10 @@
 {
     return JSValue::encode(jsBoolean(jsDynamicCast<JSArrayBufferView*>(exec->vm(), exec->argument(0))));
 }
-    
 
+// Instantiate JSGenericArrayBufferConstructors.
+template class JSGenericArrayBufferConstructor<ArrayBufferSharingMode::Shared>;
+template class JSGenericArrayBufferConstructor<ArrayBufferSharingMode::Default>;
+
 } // namespace JSC
 

Modified: trunk/Source/_javascript_Core/runtime/JSArrayBufferConstructor.h (240455 => 240456)


--- trunk/Source/_javascript_Core/runtime/JSArrayBufferConstructor.h	2019-01-25 00:35:19 UTC (rev 240455)
+++ trunk/Source/_javascript_Core/runtime/JSArrayBufferConstructor.h	2019-01-25 00:49:44 UTC (rev 240456)
@@ -33,31 +33,35 @@
 class JSArrayBufferPrototype;
 class GetterSetter;
 
-class JSArrayBufferConstructor final : public InternalFunction {
+template<ArrayBufferSharingMode sharingMode>
+class JSGenericArrayBufferConstructor final : public InternalFunction {
 public:
-    typedef InternalFunction Base;
+    using Base = InternalFunction;
 
-    template<typename CellType>
-    static IsoSubspace* subspaceFor(VM& vm)
-    {
-        return &vm.arrayBufferConstructorSpace;
-    }
-
 protected:
-    JSArrayBufferConstructor(VM&, Structure*, ArrayBufferSharingMode);
+    JSGenericArrayBufferConstructor(VM&, Structure*);
     void finishCreation(VM&, JSArrayBufferPrototype*, GetterSetter* speciesSymbol);
 
+    static EncodedJSValue JSC_HOST_CALL constructArrayBuffer(ExecState*);
+
 public:
-    static JSArrayBufferConstructor* create(VM&, Structure*, JSArrayBufferPrototype*, GetterSetter* speciesSymbol, ArrayBufferSharingMode);
-    
-    DECLARE_INFO;
-    
+    static JSGenericArrayBufferConstructor* create(VM& vm, Structure* structure, JSArrayBufferPrototype* prototype, GetterSetter* speciesSymbol)
+    {
+        JSGenericArrayBufferConstructor* result =
+            new (NotNull, allocateCell<JSGenericArrayBufferConstructor>(vm.heap)) JSGenericArrayBufferConstructor(vm, structure);
+        result->finishCreation(vm, prototype, speciesSymbol);
+        return result;
+    }
+
     static Structure* createStructure(VM&, JSGlobalObject*, JSValue prototype);
     
-    ArrayBufferSharingMode sharingMode() const { return m_sharingMode; }
-
-private:
-    ArrayBufferSharingMode m_sharingMode;
+    static const ClassInfo s_info; // This is never accessed directly, since that would break linkage on some compilers.
+    static const ClassInfo* info();
 };
 
+using JSArrayBufferConstructor = JSGenericArrayBufferConstructor<ArrayBufferSharingMode::Default>;
+using JSSharedArrayBufferConstructor = JSGenericArrayBufferConstructor<ArrayBufferSharingMode::Shared>;
+static_assert(sizeof(JSArrayBufferConstructor::Base) == sizeof(JSArrayBufferConstructor), "");
+static_assert(sizeof(JSSharedArrayBufferConstructor::Base) == sizeof(JSSharedArrayBufferConstructor), "");
+
 } // namespace JSC

Modified: trunk/Source/_javascript_Core/runtime/JSGlobalObject.cpp (240455 => 240456)


--- trunk/Source/_javascript_Core/runtime/JSGlobalObject.cpp	2019-01-25 00:35:19 UTC (rev 240455)
+++ trunk/Source/_javascript_Core/runtime/JSGlobalObject.cpp	2019-01-25 00:49:44 UTC (rev 240456)
@@ -676,12 +676,12 @@
     
     m_regExpConstructor.set(vm, this, RegExpConstructor::create(vm, RegExpConstructor::createStructure(vm, this, m_functionPrototype.get()), m_regExpPrototype.get(), m_speciesGetterSetter.get()));
     
-    JSArrayBufferConstructor* arrayBufferConstructor = JSArrayBufferConstructor::create(vm, JSArrayBufferConstructor::createStructure(vm, this, m_functionPrototype.get()), m_arrayBufferPrototype.get(), m_speciesGetterSetter.get(), ArrayBufferSharingMode::Default);
+    JSArrayBufferConstructor* arrayBufferConstructor = JSArrayBufferConstructor::create(vm, JSArrayBufferConstructor::createStructure(vm, this, m_functionPrototype.get()), m_arrayBufferPrototype.get(), m_speciesGetterSetter.get());
     m_arrayBufferPrototype->putDirectWithoutTransition(vm, vm.propertyNames->constructor, arrayBufferConstructor, static_cast<unsigned>(PropertyAttribute::DontEnum));
 
 #if ENABLE(SHARED_ARRAY_BUFFER)
-    JSArrayBufferConstructor* sharedArrayBufferConstructor = nullptr;
-    sharedArrayBufferConstructor = JSArrayBufferConstructor::create(vm, JSArrayBufferConstructor::createStructure(vm, this, m_functionPrototype.get()), m_sharedArrayBufferPrototype.get(), m_speciesGetterSetter.get(), ArrayBufferSharingMode::Shared);
+    JSSharedArrayBufferConstructor* sharedArrayBufferConstructor = nullptr;
+    sharedArrayBufferConstructor = JSSharedArrayBufferConstructor::create(vm, JSSharedArrayBufferConstructor::createStructure(vm, this, m_functionPrototype.get()), m_sharedArrayBufferPrototype.get(), m_speciesGetterSetter.get());
     m_sharedArrayBufferPrototype->putDirectWithoutTransition(vm, vm.propertyNames->constructor, sharedArrayBufferConstructor, static_cast<unsigned>(PropertyAttribute::DontEnum));
 
     AtomicsObject* atomicsObject = AtomicsObject::create(vm, this, AtomicsObject::createStructure(vm, this, m_objectPrototype.get()));

Modified: trunk/Source/_javascript_Core/runtime/JSGlobalObject.h (240455 => 240456)


--- trunk/Source/_javascript_Core/runtime/JSGlobalObject.h	2019-01-25 00:35:19 UTC (rev 240455)
+++ trunk/Source/_javascript_Core/runtime/JSGlobalObject.h	2019-01-25 00:49:44 UTC (rev 240456)
@@ -82,7 +82,6 @@
 class InputCursor;
 class IntlObject;
 class JSArrayBuffer;
-class JSArrayBufferConstructor;
 class JSArrayBufferPrototype;
 class JSCallee;
 class JSGlobalObjectDebuggable;
@@ -93,7 +92,6 @@
 class JSPromiseConstructor;
 class JSPromisePrototype;
 class JSSharedArrayBuffer;
-class JSSharedArrayBufferConstructor;
 class JSSharedArrayBufferPrototype;
 class JSTypedArrayViewConstructor;
 class JSTypedArrayViewPrototype;

Modified: trunk/Source/_javascript_Core/runtime/VM.cpp (240455 => 240456)


--- trunk/Source/_javascript_Core/runtime/VM.cpp	2019-01-25 00:35:19 UTC (rev 240455)
+++ trunk/Source/_javascript_Core/runtime/VM.cpp	2019-01-25 00:49:44 UTC (rev 240456)
@@ -292,7 +292,6 @@
     , destructibleObjectSpace("JSDestructibleObject", heap, destructibleObjectHeapCellType.get(), fastMallocAllocator.get())
     , eagerlySweptDestructibleObjectSpace("Eagerly Swept JSDestructibleObject", heap, destructibleObjectHeapCellType.get(), fastMallocAllocator.get())
     , segmentedVariableObjectSpace("JSSegmentedVariableObjectSpace", heap, segmentedVariableObjectHeapCellType.get(), fastMallocAllocator.get())
-    , arrayBufferConstructorSpace ISO_SUBSPACE_INIT(heap, destructibleObjectHeapCellType.get(), JSArrayBufferConstructor)
     , asyncFunctionSpace ISO_SUBSPACE_INIT(heap, cellJSValueOOBHeapCellType.get(), JSAsyncFunction)
     , asyncGeneratorFunctionSpace ISO_SUBSPACE_INIT(heap, cellJSValueOOBHeapCellType.get(), JSAsyncGeneratorFunction)
     , boundFunctionSpace ISO_SUBSPACE_INIT(heap, cellJSValueOOBHeapCellType.get(), JSBoundFunction)

Modified: trunk/Source/_javascript_Core/runtime/VM.h (240455 => 240456)


--- trunk/Source/_javascript_Core/runtime/VM.h	2019-01-25 00:35:19 UTC (rev 240455)
+++ trunk/Source/_javascript_Core/runtime/VM.h	2019-01-25 00:49:44 UTC (rev 240456)
@@ -367,7 +367,6 @@
     CompleteSubspace eagerlySweptDestructibleObjectSpace;
     CompleteSubspace segmentedVariableObjectSpace;
     
-    IsoSubspace arrayBufferConstructorSpace;
     IsoSubspace asyncFunctionSpace;
     IsoSubspace asyncGeneratorFunctionSpace;
     IsoSubspace boundFunctionSpace;
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to