Changeset 239256 in webkit


Ignore:
Timestamp:
Dec 15, 2018 9:49:01 PM (5 years ago)
Author:
yusukesuzuki@slowstart.org
Message:

Null pointer dereference in JSC::WriteBarrierBase()
https://bugs.webkit.org/show_bug.cgi?id=191252

Reviewed by Keith Miller.

Source/JavaScriptCore:

JSPromiseDeferred::create can return nullptr and an exception if stack overflow happens.
We would like to make it RELEASE_ASSERT since the current module mechanism is not immune
to stack overflow.

This patch renames JSPromiseDeferred::create to JSPromiseDeferred::tryCreate to tell that
it can return nullptr. And we insert error checks or assertions after this call.

  • jsc.cpp:

(GlobalObject::moduleLoaderImportModule):
(GlobalObject::moduleLoaderFetch):

  • runtime/Completion.cpp:

(JSC::rejectPromise):

  • runtime/JSGlobalObjectFunctions.cpp:

(JSC::globalFuncImportModule):

  • runtime/JSInternalPromiseDeferred.cpp:

(JSC::JSInternalPromiseDeferred::tryCreate):
(JSC::JSInternalPromiseDeferred::create): Deleted.

  • runtime/JSInternalPromiseDeferred.h:
  • runtime/JSModuleLoader.cpp:

(JSC::JSModuleLoader::importModule):
(JSC::JSModuleLoader::resolve):
(JSC::JSModuleLoader::fetch):
(JSC::moduleLoaderParseModule):

  • runtime/JSPromise.h:
  • runtime/JSPromiseDeferred.cpp:

(JSC::JSPromiseDeferred::tryCreate):

  • runtime/JSPromiseDeferred.h:
  • wasm/js/WebAssemblyPrototype.cpp:

(JSC::webAssemblyCompileFunc):
(JSC::webAssemblyInstantiateFunc):
(JSC::webAssemblyCompileStreamingInternal):
(JSC::webAssemblyInstantiateStreamingInternal):

Source/WebCore:

  • bindings/js/JSCustomElementRegistryCustom.cpp:

(WebCore::JSCustomElementRegistry::whenDefined):

  • bindings/js/JSDOMPromiseDeferred.cpp:

(WebCore::createDeferredPromise):

  • bindings/js/JSDOMPromiseDeferred.h:

(WebCore::DeferredPromise::create):
(WebCore::callPromiseFunction):

  • bindings/js/JSDOMWindowBase.cpp:

(WebCore::JSDOMWindowBase::moduleLoaderFetch):
(WebCore::JSDOMWindowBase::moduleLoaderImportModule):

  • bindings/js/ScriptModuleLoader.cpp:

(WebCore::ScriptModuleLoader::fetch):
(WebCore::rejectPromise):

Location:
trunk/Source
Files:
17 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/JavaScriptCore/ChangeLog

    r239255 r239256  
     12018-12-15  Yusuke Suzuki  <yusukesuzuki@slowstart.org>
     2
     3        Null pointer dereference in JSC::WriteBarrierBase()
     4        https://bugs.webkit.org/show_bug.cgi?id=191252
     5
     6        Reviewed by Keith Miller.
     7
     8        JSPromiseDeferred::create can return nullptr and an exception if stack overflow happens.
     9        We would like to make it RELEASE_ASSERT since the current module mechanism is not immune
     10        to stack overflow.
     11
     12        This patch renames JSPromiseDeferred::create to JSPromiseDeferred::tryCreate to tell that
     13        it can return nullptr. And we insert error checks or assertions after this call.
     14
     15        * jsc.cpp:
     16        (GlobalObject::moduleLoaderImportModule):
     17        (GlobalObject::moduleLoaderFetch):
     18        * runtime/Completion.cpp:
     19        (JSC::rejectPromise):
     20        * runtime/JSGlobalObjectFunctions.cpp:
     21        (JSC::globalFuncImportModule):
     22        * runtime/JSInternalPromiseDeferred.cpp:
     23        (JSC::JSInternalPromiseDeferred::tryCreate):
     24        (JSC::JSInternalPromiseDeferred::create): Deleted.
     25        * runtime/JSInternalPromiseDeferred.h:
     26        * runtime/JSModuleLoader.cpp:
     27        (JSC::JSModuleLoader::importModule):
     28        (JSC::JSModuleLoader::resolve):
     29        (JSC::JSModuleLoader::fetch):
     30        (JSC::moduleLoaderParseModule):
     31        * runtime/JSPromise.h:
     32        * runtime/JSPromiseDeferred.cpp:
     33        (JSC::JSPromiseDeferred::tryCreate):
     34        * runtime/JSPromiseDeferred.h:
     35        * wasm/js/WebAssemblyPrototype.cpp:
     36        (JSC::webAssemblyCompileFunc):
     37        (JSC::webAssemblyInstantiateFunc):
     38        (JSC::webAssemblyCompileStreamingInternal):
     39        (JSC::webAssemblyInstantiateStreamingInternal):
     40
    1412018-12-15  Darin Adler  <darin@apple.com>
    242
  • trunk/Source/JavaScriptCore/jsc.cpp

    r239254 r239256  
    807807    auto throwScope = DECLARE_THROW_SCOPE(vm);
    808808
    809     auto* deferred = JSInternalPromiseDeferred::create(exec, globalObject);
     809    auto* deferred = JSInternalPromiseDeferred::tryCreate(exec, globalObject);
    810810    RETURN_IF_EXCEPTION(throwScope, nullptr);
    811811
     
    10011001    VM& vm = globalObject->vm();
    10021002    auto throwScope = DECLARE_THROW_SCOPE(vm);
    1003     JSInternalPromiseDeferred* deferred = JSInternalPromiseDeferred::create(exec, globalObject);
     1003    JSInternalPromiseDeferred* deferred = JSInternalPromiseDeferred::tryCreate(exec, globalObject);
    10041004    RETURN_IF_EXCEPTION(throwScope, nullptr);
    10051005
  • trunk/Source/JavaScriptCore/runtime/Completion.cpp

    r236904 r239256  
    155155    JSValue exception = scope.exception()->value();
    156156    scope.clearException();
    157     JSInternalPromiseDeferred* deferred = JSInternalPromiseDeferred::create(exec, globalObject);
     157    JSInternalPromiseDeferred* deferred = JSInternalPromiseDeferred::tryCreate(exec, globalObject);
     158    scope.releaseAssertNoException();
    158159    deferred->reject(exec, exception);
     160    scope.releaseAssertNoException();
    159161    return deferred->promise();
    160162}
  • trunk/Source/JavaScriptCore/runtime/JSGlobalObjectFunctions.cpp

    r238391 r239256  
    788788    auto* globalObject = exec->lexicalGlobalObject();
    789789
    790     auto* promise = JSPromiseDeferred::create(exec, globalObject);
     790    auto* promise = JSPromiseDeferred::tryCreate(exec, globalObject);
    791791    RETURN_IF_EXCEPTION(throwScope, encodedJSValue());
    792792
  • trunk/Source/JavaScriptCore/runtime/JSInternalPromiseDeferred.cpp

    r236372 r239256  
    3838const ClassInfo JSInternalPromiseDeferred::s_info = { "JSInternalPromiseDeferred", &Base::s_info, nullptr, nullptr, CREATE_METHOD_TABLE(JSInternalPromiseDeferred) };
    3939
    40 JSInternalPromiseDeferred* JSInternalPromiseDeferred::create(ExecState* exec, JSGlobalObject* globalObject)
     40JSInternalPromiseDeferred* JSInternalPromiseDeferred::tryCreate(ExecState* exec, JSGlobalObject* globalObject)
    4141{
    4242    VM& vm = exec->vm();
  • trunk/Source/JavaScriptCore/runtime/JSInternalPromiseDeferred.h

    r214218 r239256  
    3737    static const unsigned StructureFlags = Base::StructureFlags | StructureIsImmortal;
    3838
    39     JS_EXPORT_PRIVATE static JSInternalPromiseDeferred* create(ExecState*, JSGlobalObject*);
     39    JS_EXPORT_PRIVATE static JSInternalPromiseDeferred* tryCreate(ExecState*, JSGlobalObject*);
    4040
    4141    static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue prototype)
  • trunk/Source/JavaScriptCore/runtime/JSModuleLoader.cpp

    r238391 r239256  
    239239        RELEASE_AND_RETURN(throwScope, globalObject->globalObjectMethodTable()->moduleLoaderImportModule(globalObject, exec, this, moduleName, parameters, referrer));
    240240
    241     auto* deferred = JSInternalPromiseDeferred::create(exec, globalObject);
     241    auto* deferred = JSInternalPromiseDeferred::tryCreate(exec, globalObject);
    242242    RETURN_IF_EXCEPTION(throwScope, nullptr);
    243243
     
    272272    auto throwScope = DECLARE_THROW_SCOPE(vm);
    273273
    274     JSInternalPromiseDeferred* deferred = JSInternalPromiseDeferred::create(exec, exec->lexicalGlobalObject());
     274    JSInternalPromiseDeferred* deferred = JSInternalPromiseDeferred::tryCreate(exec, exec->lexicalGlobalObject());
    275275    RETURN_IF_EXCEPTION(throwScope, nullptr);
    276276
     
    302302        RELEASE_AND_RETURN(throwScope, globalObject->globalObjectMethodTable()->moduleLoaderFetch(globalObject, exec, this, key, parameters, scriptFetcher));
    303303
    304     JSInternalPromiseDeferred* deferred = JSInternalPromiseDeferred::create(exec, globalObject);
     304    JSInternalPromiseDeferred* deferred = JSInternalPromiseDeferred::tryCreate(exec, globalObject);
    305305    RETURN_IF_EXCEPTION(throwScope, nullptr);
    306306
     
    363363    auto throwScope = DECLARE_THROW_SCOPE(vm);
    364364
    365     JSInternalPromiseDeferred* deferred = JSInternalPromiseDeferred::create(exec, exec->lexicalGlobalObject());
     365    JSInternalPromiseDeferred* deferred = JSInternalPromiseDeferred::tryCreate(exec, exec->lexicalGlobalObject());
    366366    RETURN_IF_EXCEPTION(throwScope, encodedJSValue());
    367367
  • trunk/Source/JavaScriptCore/runtime/JSPromise.h

    r236372 r239256  
    3232class JSPromise : public JSNonFinalObject {
    3333public:
    34     typedef JSNonFinalObject Base;
     34    using Base = JSNonFinalObject;
    3535
    3636    static JSPromise* create(VM&, Structure*);
    37     struct JSPromiseAndCallbacks {
    38         JSPromise* promise;
    39         JSFunction* resolve;
    40         JSFunction* reject;
    41     };
    42     static JSPromiseAndCallbacks createWithCallbacks(VM&, Structure*);
    43 
    4437    static Structure* createStructure(VM&, JSGlobalObject*, JSValue);
    4538
  • trunk/Source/JavaScriptCore/runtime/JSPromiseDeferred.cpp

    r236372 r239256  
    6767}
    6868
    69 JSPromiseDeferred* JSPromiseDeferred::create(ExecState* exec, JSGlobalObject* globalObject)
     69JSPromiseDeferred* JSPromiseDeferred::tryCreate(ExecState* exec, JSGlobalObject* globalObject)
    7070{
    7171    VM& vm = exec->vm();
  • trunk/Source/JavaScriptCore/runtime/JSPromiseDeferred.h

    r236372 r239256  
    5050    static DeferredData createDeferredData(ExecState*, JSGlobalObject*, JSPromiseConstructor*);
    5151
    52     JS_EXPORT_PRIVATE static JSPromiseDeferred* create(ExecState*, JSGlobalObject*);
     52    JS_EXPORT_PRIVATE static JSPromiseDeferred* tryCreate(ExecState*, JSGlobalObject*);
    5353    JS_EXPORT_PRIVATE static JSPromiseDeferred* create(VM&, JSPromise*, JSFunction* resolve, JSFunction* reject);
    5454
  • trunk/Source/JavaScriptCore/wasm/js/WebAssemblyPrototype.cpp

    r235420 r239256  
    116116    auto* globalObject = exec->lexicalGlobalObject();
    117117
    118     JSPromiseDeferred* promise = JSPromiseDeferred::create(exec, globalObject);
     118    JSPromiseDeferred* promise = JSPromiseDeferred::tryCreate(exec, globalObject);
    119119    RETURN_IF_EXCEPTION(throwScope, encodedJSValue());
    120120
     
    262262    auto* globalObject = exec->lexicalGlobalObject();
    263263
    264     JSPromiseDeferred* promise = JSPromiseDeferred::create(exec, globalObject);
     264    JSPromiseDeferred* promise = JSPromiseDeferred::tryCreate(exec, globalObject);
    265265    RETURN_IF_EXCEPTION(throwScope, encodedJSValue());
    266266
     
    307307    auto catchScope = DECLARE_CATCH_SCOPE(vm);
    308308
    309     JSPromiseDeferred* promise = JSPromiseDeferred::create(exec, globalObject);
     309    JSPromiseDeferred* promise = JSPromiseDeferred::tryCreate(exec, globalObject);
    310310
    311311    Vector<Strong<JSCell>> dependencies;
     
    331331    auto* globalObject = exec->lexicalGlobalObject();
    332332
    333     JSPromiseDeferred* promise = JSPromiseDeferred::create(exec, globalObject);
    334 
     333    JSPromiseDeferred* promise = JSPromiseDeferred::tryCreate(exec, globalObject);
    335334    RETURN_IF_EXCEPTION(throwScope, encodedJSValue());
    336335    {
  • trunk/Source/WebCore/ChangeLog

    r239255 r239256  
     12018-12-15  Yusuke Suzuki  <yusukesuzuki@slowstart.org>
     2
     3        Null pointer dereference in JSC::WriteBarrierBase()
     4        https://bugs.webkit.org/show_bug.cgi?id=191252
     5
     6        Reviewed by Keith Miller.
     7
     8        * bindings/js/JSCustomElementRegistryCustom.cpp:
     9        (WebCore::JSCustomElementRegistry::whenDefined):
     10        * bindings/js/JSDOMPromiseDeferred.cpp:
     11        (WebCore::createDeferredPromise):
     12        * bindings/js/JSDOMPromiseDeferred.h:
     13        (WebCore::DeferredPromise::create):
     14        (WebCore::callPromiseFunction):
     15        * bindings/js/JSDOMWindowBase.cpp:
     16        (WebCore::JSDOMWindowBase::moduleLoaderFetch):
     17        (WebCore::JSDOMWindowBase::moduleLoaderImportModule):
     18        * bindings/js/ScriptModuleLoader.cpp:
     19        (WebCore::ScriptModuleLoader::fetch):
     20        (WebCore::rejectPromise):
     21
    1222018-12-15  Darin Adler  <darin@apple.com>
    223
  • trunk/Source/WebCore/bindings/js/JSCustomElementRegistryCustom.cpp

    r233245 r239256  
    208208
    209209    ASSERT(globalObject());
    210     auto promiseDeferred = JSPromiseDeferred::create(&state, globalObject());
    211     ASSERT(promiseDeferred);
     210    auto promiseDeferred = JSPromiseDeferred::tryCreate(&state, globalObject());
     211    RELEASE_ASSERT(promiseDeferred);
    212212    JSValue promise = whenDefinedPromise(state, *globalObject(), wrapped(), *promiseDeferred);
    213213
  • trunk/Source/WebCore/bindings/js/JSDOMPromiseDeferred.cpp

    r232337 r239256  
    192192Ref<DeferredPromise> createDeferredPromise(JSC::ExecState& state, JSDOMWindow& domWindow)
    193193{
    194     JSC::JSPromiseDeferred* deferred = JSC::JSPromiseDeferred::create(&state, &domWindow);
     194    JSC::JSPromiseDeferred* deferred = JSC::JSPromiseDeferred::tryCreate(&state, &domWindow);
    195195    // deferred can only be null in workers.
    196     ASSERT(deferred);
     196    RELEASE_ASSERT(deferred);
    197197    return DeferredPromise::create(domWindow, *deferred);
    198198}
  • trunk/Source/WebCore/bindings/js/JSDOMPromiseDeferred.h

    r232156 r239256  
    4545    static RefPtr<DeferredPromise> create(JSC::ExecState& state, JSDOMGlobalObject& globalObject, Mode mode = Mode::ClearPromiseOnResolve)
    4646    {
    47         auto* promiseDeferred = JSC::JSPromiseDeferred::create(&state, &globalObject);
     47        auto* promiseDeferred = JSC::JSPromiseDeferred::tryCreate(&state, &globalObject);
    4848        if (!promiseDeferred)
    4949            return nullptr;
     
    271271
    272272    auto& globalObject = callerGlobalObject(state);
    273     JSC::JSPromiseDeferred* promiseDeferred = JSC::JSPromiseDeferred::create(&state, &globalObject);
     273    JSC::JSPromiseDeferred* promiseDeferred = JSC::JSPromiseDeferred::tryCreate(&state, &globalObject);
    274274
    275275    // promiseDeferred can be null when terminating a Worker abruptly.
     
    291291
    292292    auto& globalObject = callerGlobalObject(state);
    293     JSC::JSPromiseDeferred* promiseDeferred = JSC::JSPromiseDeferred::create(&state, &globalObject);
     293    JSC::JSPromiseDeferred* promiseDeferred = JSC::JSPromiseDeferred::tryCreate(&state, &globalObject);
    294294
    295295    // promiseDeferred can be null when terminating a Worker abruptly.
  • trunk/Source/WebCore/bindings/js/JSDOMWindowBase.cpp

    r237266 r239256  
    313313JSC::JSInternalPromise* JSDOMWindowBase::moduleLoaderFetch(JSC::JSGlobalObject* globalObject, JSC::ExecState* exec, JSC::JSModuleLoader* moduleLoader, JSC::JSValue moduleKey, JSC::JSValue parameters, JSC::JSValue scriptFetcher)
    314314{
     315    VM& vm = exec->vm();
     316    auto scope = DECLARE_THROW_SCOPE(vm);
    315317    JSDOMWindowBase* thisObject = JSC::jsCast<JSDOMWindowBase*>(globalObject);
    316318    if (RefPtr<Document> document = thisObject->wrapped().document())
    317         return document->moduleLoader()->fetch(globalObject, exec, moduleLoader, moduleKey, parameters, scriptFetcher);
    318     JSC::JSInternalPromiseDeferred* deferred = JSC::JSInternalPromiseDeferred::create(exec, globalObject);
    319     return deferred->reject(exec, jsUndefined());
     319        RELEASE_AND_RETURN(scope, document->moduleLoader()->fetch(globalObject, exec, moduleLoader, moduleKey, parameters, scriptFetcher));
     320    JSC::JSInternalPromiseDeferred* deferred = JSC::JSInternalPromiseDeferred::tryCreate(exec, globalObject);
     321    RETURN_IF_EXCEPTION(scope, nullptr);
     322    RELEASE_AND_RETURN(scope, deferred->reject(exec, jsUndefined()));
    320323}
    321324
     
    330333JSC::JSInternalPromise* JSDOMWindowBase::moduleLoaderImportModule(JSC::JSGlobalObject* globalObject, JSC::ExecState* exec, JSC::JSModuleLoader* moduleLoader, JSC::JSString* moduleName, JSC::JSValue parameters, const JSC::SourceOrigin& sourceOrigin)
    331334{
     335    VM& vm = exec->vm();
     336    auto scope = DECLARE_THROW_SCOPE(vm);
    332337    JSDOMWindowBase* thisObject = JSC::jsCast<JSDOMWindowBase*>(globalObject);
    333338    if (RefPtr<Document> document = thisObject->wrapped().document())
    334         return document->moduleLoader()->importModule(globalObject, exec, moduleLoader, moduleName, parameters, sourceOrigin);
    335     JSC::JSInternalPromiseDeferred* deferred = JSC::JSInternalPromiseDeferred::create(exec, globalObject);
    336     return deferred->reject(exec, jsUndefined());
     339        RELEASE_AND_RETURN(scope, document->moduleLoader()->importModule(globalObject, exec, moduleLoader, moduleName, parameters, sourceOrigin));
     340    JSC::JSInternalPromiseDeferred* deferred = JSC::JSInternalPromiseDeferred::tryCreate(exec, globalObject);
     341    RETURN_IF_EXCEPTION(scope, nullptr);
     342    RELEASE_AND_RETURN(scope, deferred->reject(exec, jsUndefined()));
    337343}
    338344
  • trunk/Source/WebCore/bindings/js/ScriptModuleLoader.cpp

    r233122 r239256  
    147147
    148148    auto& globalObject = *JSC::jsCast<JSDOMGlobalObject*>(jsGlobalObject);
    149     auto& jsPromise = *JSC::JSInternalPromiseDeferred::create(exec, &globalObject);
    150     auto deferred = DeferredPromise::create(globalObject, jsPromise);
     149    auto* jsPromise = JSC::JSInternalPromiseDeferred::tryCreate(exec, &globalObject);
     150    RELEASE_ASSERT(jsPromise);
     151    auto deferred = DeferredPromise::create(globalObject, *jsPromise);
    151152    if (moduleKeyValue.isSymbol()) {
    152153        deferred->reject(TypeError, "Symbol module key should be already fulfilled with the inlined resource."_s);
    153         return jsPromise.promise();
     154        return jsPromise->promise();
    154155    }
    155156
    156157    if (!moduleKeyValue.isString()) {
    157158        deferred->reject(TypeError, "Module key is not Symbol or String."_s);
    158         return jsPromise.promise();
     159        return jsPromise->promise();
    159160    }
    160161
     
    164165    if (!completedURL.isValid()) {
    165166        deferred->reject(TypeError, "Module key is a valid URL."_s);
    166         return jsPromise.promise();
     167        return jsPromise->promise();
    167168    }
    168169
     
    177178        m_loaders.remove(WTFMove(loader));
    178179        rejectToPropagateNetworkError(deferred.get(), ModuleFetchFailureKind::WasErrored, "Importing a module script failed."_s);
    179         return jsPromise.promise();
    180     }
    181 
    182     return jsPromise.promise();
     180        return jsPromise->promise();
     181    }
     182
     183    return jsPromise->promise();
    183184}
    184185
     
    215216static JSC::JSInternalPromise* rejectPromise(JSC::ExecState& state, JSDOMGlobalObject& globalObject, ExceptionCode ec, ASCIILiteral message)
    216217{
    217     auto& jsPromise = *JSC::JSInternalPromiseDeferred::create(&state, &globalObject);
    218     auto deferred = DeferredPromise::create(globalObject, jsPromise);
     218    auto* jsPromise = JSC::JSInternalPromiseDeferred::tryCreate(&state, &globalObject);
     219    RELEASE_ASSERT(jsPromise);
     220    auto deferred = DeferredPromise::create(globalObject, *jsPromise);
    219221    deferred->reject(ec, WTFMove(message));
    220     return jsPromise.promise();
     222    return jsPromise->promise();
    221223}
    222224
Note: See TracChangeset for help on using the changeset viewer.