| Differences between
and this patch
- a/JSTests/ChangeLog +16 lines
Lines 1-3 a/JSTests/ChangeLog_sec1
1
2017-11-17  JF Bastien  <jfbastien@apple.com>
2
3
        WebAssembly JS API: throw when a promise can't be created
4
        https://bugs.webkit.org/show_bug.cgi?id=179826
5
        <rdar://problem/35455813>
6
7
        Reviewed by NOBODY (OOPS!).
8
9
        Test WebAssembly.{compile,instantiate} where promise creation
10
        fails because of a stack overflow.
11
12
        * wasm/js-api/promise-stack-overflow.js: Added.
13
        (const.runNearStackLimit.f.const.t):
14
        (async.testCompile):
15
        (async.testInstantiate):
16
1
2017-11-16  Robin Morisset  <rmorisset@apple.com>
17
2017-11-16  Robin Morisset  <rmorisset@apple.com>
2
18
3
        REGRESSION (r224592): oss-fuzz: jsc: Null-dereference READ in JSC::JSCell::isObject (4216)
19
        REGRESSION (r224592): oss-fuzz: jsc: Null-dereference READ in JSC::JSCell::isObject (4216)
- a/JSTests/wasm/js-api/promise-stack-overflow.js +37 lines
Line 0 a/JSTests/wasm/js-api/promise-stack-overflow.js_sec1
1
import * as assert from '../assert.js';
2
3
const module = Uint8Array.of(0x0, 0x61, 0x73, 0x6d, 0x1, 0x00, 0x00, 0x00);
4
5
let promises = [];
6
7
const runNearStackLimit = f => {
8
    const t = () => {
9
        try {
10
            return t();
11
        } catch (e) {
12
            return f();
13
        }
14
    };
15
    return t();
16
};
17
18
const touchArgument = arg => promises.push(arg);
19
20
const compileMe = () => touchArgument(WebAssembly.compile(module));
21
22
async function testCompile() {
23
    await touchArgument(async function() {
24
        runNearStackLimit(compileMe);
25
    }());
26
}
27
28
const instantiateMe = () => touchArgument(WebAssembly.instantiate(module));
29
30
async function testInstantiate() {
31
    await touchArgument(async function() {
32
        runNearStackLimit(instantiateMe);
33
    }());
34
}
35
36
assert.asyncTest(testCompile());
37
assert.asyncTest(testInstantiate());
- a/Source/JavaScriptCore/ChangeLog +37 lines
Lines 1-3 a/Source/JavaScriptCore/ChangeLog_sec1
1
2017-11-17  JF Bastien  <jfbastien@apple.com>
2
3
        WebAssembly JS API: throw when a promise can't be created
4
        https://bugs.webkit.org/show_bug.cgi?id=179826
5
        <rdar://problem/35455813>
6
7
        Reviewed by NOBODY (OOPS!).
8
9
        Failure *in* a promise causes rejection, but failure to create a
10
        promise (because of stack overflow) isn't really spec'd (as all
11
        stack things JS). This applies to WebAssembly.compile and
12
        WebAssembly.instantiate.
13
14
        Dan's current proposal says:
15
16
            https://littledan.github.io/spec/document/js-api/index.html#stack-overflow
17
18
            Whenever a stack overflow occurs in WebAssembly code, the same
19
            class of exception is thrown as for a stack overflow in
20
            JavaScript. The particular exception here is
21
            implementation-defined in both cases.
22
23
            Note: ECMAScript doesn’t specify any sort of behavior on stack
24
            overflow; implementations have been observed to throw RangeError,
25
            InternalError or Error. Any is valid here.
26
27
        This is for general stack overflow within WebAssembly, not
28
        specifically for promise creation within JavaScript, but it seems
29
        like a stack overflow in promise creation should follow the same
30
        rule instead of, say, swallowing the overflow and returning
31
        undefined.
32
33
        * wasm/js/WebAssemblyPrototype.cpp:
34
        (JSC::createPromise): helper which throws instead of catches
35
        (JSC::webAssemblyCompileFunc):
36
        (JSC::webAssemblyInstantiateFunc):
37
1
2017-11-16  Robin Morisset  <rmorisset@apple.com>
38
2017-11-16  Robin Morisset  <rmorisset@apple.com>
2
39
3
        Provide a runtime option for disabling the optimization of recursive tail calls
40
        Provide a runtime option for disabling the optimization of recursive tail calls
- a/Source/JavaScriptCore/wasm/js/WebAssemblyPrototype.cpp -7 / +16 lines
Lines 40-45 a/Source/JavaScriptCore/wasm/js/WebAssemblyPrototype.cpp_sec1
40
#include "ObjectConstructor.h"
40
#include "ObjectConstructor.h"
41
#include "PromiseDeferredTimer.h"
41
#include "PromiseDeferredTimer.h"
42
#include "StrongInlines.h"
42
#include "StrongInlines.h"
43
#include "ThrowScope.h"
43
#include "WasmBBQPlan.h"
44
#include "WasmBBQPlan.h"
44
#include "WasmToJS.h"
45
#include "WasmToJS.h"
45
#include "WasmWorklist.h"
46
#include "WasmWorklist.h"
Lines 77-82 static void reject(ExecState* exec, CatchScope& catchScope, JSPromiseDeferred* p a/Source/JavaScriptCore/wasm/js/WebAssemblyPrototype.cpp_sec2
77
    promise->reject(exec, exception->value());
78
    promise->reject(exec, exception->value());
78
    CLEAR_AND_RETURN_IF_EXCEPTION(catchScope, void());
79
    CLEAR_AND_RETURN_IF_EXCEPTION(catchScope, void());
79
}
80
}
81
    
82
static JSPromiseDeferred* createPromise(VM& vm, ExecState* exec, JSGlobalObject* globalObject)
83
{
84
    auto scope = DECLARE_THROW_SCOPE(vm);
85
    JSPromiseDeferred* promise = JSPromiseDeferred::create(exec, globalObject);
86
    RETURN_IF_EXCEPTION(scope, nullptr);
87
    return promise;
88
}
80
89
81
static EncodedJSValue JSC_HOST_CALL webAssemblyCompileFunc(ExecState* exec)
90
static EncodedJSValue JSC_HOST_CALL webAssemblyCompileFunc(ExecState* exec)
82
{
91
{
Lines 84-91 static EncodedJSValue JSC_HOST_CALL webAssemblyCompileFunc(ExecState* exec) a/Source/JavaScriptCore/wasm/js/WebAssemblyPrototype.cpp_sec3
84
    auto scope = DECLARE_CATCH_SCOPE(vm);
93
    auto scope = DECLARE_CATCH_SCOPE(vm);
85
    auto* globalObject = exec->lexicalGlobalObject();
94
    auto* globalObject = exec->lexicalGlobalObject();
86
95
87
    JSPromiseDeferred* promise = JSPromiseDeferred::create(exec, globalObject);
96
    JSPromiseDeferred* promise = createPromise(vm, exec, globalObject);
88
    CLEAR_AND_RETURN_IF_EXCEPTION(scope, encodedJSValue());
97
    RETURN_IF_EXCEPTION(scope, encodedJSValue());
89
98
90
    Vector<Strong<JSCell>> dependencies;
99
    Vector<Strong<JSCell>> dependencies;
91
    dependencies.append(Strong<JSCell>(vm, globalObject));
100
    dependencies.append(Strong<JSCell>(vm, globalObject));
Lines 184-199 static EncodedJSValue JSC_HOST_CALL webAssemblyInstantiateFunc(ExecState* exec) a/Source/JavaScriptCore/wasm/js/WebAssemblyPrototype.cpp_sec4
184
{
193
{
185
    VM& vm = exec->vm();
194
    VM& vm = exec->vm();
186
    auto scope = DECLARE_CATCH_SCOPE(vm);
195
    auto scope = DECLARE_CATCH_SCOPE(vm);
187
196
    auto* globalObject = exec->lexicalGlobalObject();
188
    JSPromiseDeferred* promise = JSPromiseDeferred::create(exec, exec->lexicalGlobalObject());
197
    
189
    CLEAR_AND_RETURN_IF_EXCEPTION(scope, encodedJSValue());
198
    JSPromiseDeferred* promise = createPromise(vm, exec, globalObject);
199
    RETURN_IF_EXCEPTION(scope, encodedJSValue());
190
200
191
    JSValue importArgument = exec->argument(1);
201
    JSValue importArgument = exec->argument(1);
192
    JSObject* importObject = importArgument.getObject();
202
    JSObject* importObject = importArgument.getObject();
193
    if (!importArgument.isUndefined() && !importObject) {
203
    if (!importArgument.isUndefined() && !importObject) {
194
        promise->reject(exec, createTypeError(exec,
204
        promise->reject(exec, createTypeError(exec,
195
            ASCIILiteral("second argument to WebAssembly.instantiate must be undefined or an Object"), defaultSourceAppender, runtimeTypeForValue(importArgument)));
205
            ASCIILiteral("second argument to WebAssembly.instantiate must be undefined or an Object"), defaultSourceAppender, runtimeTypeForValue(importArgument)));
196
        CLEAR_AND_RETURN_IF_EXCEPTION(scope, encodedJSValue());
206
        RETURN_IF_EXCEPTION(scope, encodedJSValue());
197
        return JSValue::encode(promise->promise());
207
        return JSValue::encode(promise->promise());
198
    }
208
    }
199
209
200
- 

Return to Bug 179826