Wasm::FunctionParser is failing to enforce maxFunctionLocals.
authormark.lam@apple.com <mark.lam@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 22 Aug 2019 01:42:22 +0000 (01:42 +0000)
committermark.lam@apple.com <mark.lam@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 22 Aug 2019 01:42:22 +0000 (01:42 +0000)
https://bugs.webkit.org/show_bug.cgi?id=201016
<rdar://problem/54579911>

Reviewed by Yusuke Suzuki.

JSTests:

* wasm/stress/too-many-locals.js: Added.
(import.Builder.from.string_appeared_here.import.as.assert.from.string_appeared_here.catch):

Source/JavaScriptCore:

Currently, Wasm::FunctionParser is allowing

    maxFunctionParams + maxFunctionLocals * maxFunctionLocals

... locals, which is 0x9502FCE8.  It should be enforcing max locals of
maxFunctionLocals instead.

* wasm/WasmFunctionParser.h:
(JSC::Wasm::FunctionParser<Context>::parse):

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@248989 268f45cc-cd09-0410-ab3c-d52691b4dbfc

JSTests/ChangeLog
JSTests/wasm/stress/too-many-locals.js [new file with mode: 0644]
Source/JavaScriptCore/ChangeLog
Source/JavaScriptCore/wasm/WasmFunctionParser.h

index 1a7d95b..e308c10 100644 (file)
@@ -1,3 +1,14 @@
+2019-08-21  Mark Lam  <mark.lam@apple.com>
+
+        Wasm::FunctionParser is failing to enforce maxFunctionLocals.
+        https://bugs.webkit.org/show_bug.cgi?id=201016
+        <rdar://problem/54579911>
+
+        Reviewed by Yusuke Suzuki.
+
+        * wasm/stress/too-many-locals.js: Added.
+        (import.Builder.from.string_appeared_here.import.as.assert.from.string_appeared_here.catch):
+
 2019-08-21  Ross Kirsling  <ross.kirsling@sony.com>
 
         JSTests/stress/optional-chaining should not call shouldThrowTypeError in a loop
diff --git a/JSTests/wasm/stress/too-many-locals.js b/JSTests/wasm/stress/too-many-locals.js
new file mode 100644 (file)
index 0000000..c046d32
--- /dev/null
@@ -0,0 +1,33 @@
+import Builder from '../Builder.js'
+import * as assert from '../assert.js'
+
+{
+    const b = new Builder();
+    const locals = [];
+    const maxFunctionLocals = 50000;
+    const numLocals = maxFunctionLocals;
+    for (let i = 0; i < numLocals; ++i)
+        locals[i] = "i32";
+    let cont = b
+        .Type().End()
+        .Function().End()
+        .Export()
+            .Function("loop")
+        .End()
+        .Code()
+            .Function("loop", { params: ["i32"], ret: "i32" }, locals)
+                .I32Const(1)
+                .Return()
+            .End()
+        .End()
+
+    const bin = b.WebAssembly().get();
+    var exception;
+    try {
+        const module = new WebAssembly.Module(bin);
+    } catch (e) {
+        exception = "" + e;
+    }
+
+    assert.eq(exception, "Error: WebAssembly.Module doesn't parse at byte 100002: Function's number of locals is too big 50001 maximum 50000, in function at index 0 (evaluating 'new WebAssembly.Module(bin)')");
+}
index 97d266a..8a7bfe3 100644 (file)
@@ -1,3 +1,21 @@
+2019-08-21  Mark Lam  <mark.lam@apple.com>
+
+        Wasm::FunctionParser is failing to enforce maxFunctionLocals.
+        https://bugs.webkit.org/show_bug.cgi?id=201016
+        <rdar://problem/54579911>
+
+        Reviewed by Yusuke Suzuki.
+
+        Currently, Wasm::FunctionParser is allowing
+
+            maxFunctionParams + maxFunctionLocals * maxFunctionLocals
+
+        ... locals, which is 0x9502FCE8.  It should be enforcing max locals of
+        maxFunctionLocals instead.
+
+        * wasm/WasmFunctionParser.h:
+        (JSC::Wasm::FunctionParser<Context>::parse):
+
 2019-08-21  Michael Saboff  <msaboff@apple.com>
 
         [JSC] incorrent JIT lead to StackOverflow
index dd7353b..a138410 100644 (file)
@@ -115,18 +115,19 @@ FunctionParser<Context>::FunctionParser(Context& context, const uint8_t* functio
 template<typename Context>
 auto FunctionParser<Context>::parse() -> Result
 {
-    uint32_t localCount;
+    uint32_t localGroupsCount;
 
     WASM_PARSER_FAIL_IF(!m_context.addArguments(m_signature), "can't add ", m_signature.argumentCount(), " arguments to Function");
-    WASM_PARSER_FAIL_IF(!parseVarUInt32(localCount), "can't get local count");
-    WASM_PARSER_FAIL_IF(localCount > maxFunctionLocals, "Function section's local count is too big ", localCount, " maximum ", maxFunctionLocals);
+    WASM_PARSER_FAIL_IF(!parseVarUInt32(localGroupsCount), "can't get local groups count");
 
-    for (uint32_t i = 0; i < localCount; ++i) {
+    uint64_t totalNumberOfLocals = m_signature.argumentCount();
+    for (uint32_t i = 0; i < localGroupsCount; ++i) {
         uint32_t numberOfLocals;
         Type typeOfLocal;
 
         WASM_PARSER_FAIL_IF(!parseVarUInt32(numberOfLocals), "can't get Function's number of locals in group ", i);
-        WASM_PARSER_FAIL_IF(numberOfLocals > maxFunctionLocals, "Function section's ", i, "th local group count is too big ", numberOfLocals, " maximum ", maxFunctionLocals);
+        totalNumberOfLocals += numberOfLocals;
+        WASM_PARSER_FAIL_IF(totalNumberOfLocals > maxFunctionLocals, "Function's number of locals is too big ", totalNumberOfLocals, " maximum ", maxFunctionLocals);
         WASM_PARSER_FAIL_IF(!parseValueType(typeOfLocal), "can't get Function local's type in group ", i);
         WASM_TRY_ADD_TO_CONTEXT(addLocal(typeOfLocal, numberOfLocals));
     }