Bug 1357911 - [WASM] Update to new name section format. r?luke draft
authorMichelangelo De Simone <mdesimone@mozilla.com>
Fri, 28 Apr 2017 00:37:04 -0700
changeset 569973 84e57eaa8ccb7aad2254555955e2c08cc4eaa61f
parent 569701 2cca333f546f38860f84940d4c72d7470a3410f4
child 626365 00b7a84fcfe401e65b682f97a3532b8f6bcef168
push id56352
push userbmo:mdesimone@mozilla.com
push dateFri, 28 Apr 2017 07:40:13 +0000
reviewersluke
bugs1357911
milestone55.0a1
Bug 1357911 - [WASM] Update to new name section format. r?luke MozReview-Commit-ID: 8Jxb6MFGlg8
js/src/jit-test/lib/wasm-binary.js
js/src/jit-test/tests/wasm/binary.js
js/src/wasm/WasmBinaryConstants.h
js/src/wasm/WasmValidate.cpp
--- a/js/src/jit-test/lib/wasm-binary.js
+++ b/js/src/jit-test/lib/wasm-binary.js
@@ -23,16 +23,20 @@ const exportId         = 7;
 const startId          = 8;
 const elemId           = 9;
 const codeId           = 10;
 const dataId           = 11;
 
 // User-defined section names
 const nameName         = "name";
 
+// Name section name types
+const nameTypeFunction = 1;
+const nameTypeLocal    = 2;
+
 // Type codes
 const I32Code          = 0x7f;
 const I64Code          = 0x7e;
 const F32Code          = 0x7d;
 const F64Code          = 0x7c;
 const AnyFuncCode      = 0x70;
 const FuncCode         = 0x60;
 const VoidCode         = 0x40;
--- a/js/src/jit-test/tests/wasm/binary.js
+++ b/js/src/jit-test/tests/wasm/binary.js
@@ -229,28 +229,34 @@ function elemSection(elemArrays) {
         for (let elem of array.elems)
             body.push(...varU32(elem));
     }
     return { name: elemId, body };
 }
 
 function nameSection(elems) {
     var body = [];
+    var funcs = [];
+
     body.push(...string(nameName));
-    body.push(...varU32(elems.length));
-    for (let fn of elems) {
-        body.push(...encodedString(fn.name, fn.nameLen));
-        if (!fn.locals) {
-           body.push(...varU32(0));
-           continue;
-        }
-        body.push(...varU32(fn.locals.length));
-        for (let local of fn.locals)
-            body.push(...encodedString(local.name, local.nameLen));
+
+    var indexRecover = 0;
+    funcs.push(...varU32(elems.length));
+    for (let f of elems) {
+        funcs.push(...varU32(f.index ? f.index : indexRecover));
+        funcs.push(...toU8(encodedString(f.name, f.nameLen)));
+        indexRecover++;
     }
+
+    // *** Function Subsection ***
+    let funcBytes = toU8(funcs);
+    body.push(...varU32(nameTypeFunction)); // name_type (1 for functions).
+    body.push(...varU32(funcBytes.length)); // name_payload_len
+    body.push(...funcBytes); // name_payload_data
+
     return { name: userDefinedId, body };
 }
 
 function customSection(name, ...body) {
     return { name: userDefinedId, body: [...string(name), ...body] };
 }
 
 const v2vSig = {args:[], ret:VoidCode};
@@ -458,10 +464,9 @@ runStackTraceTest([{name:'blah'}, {name:
 runStackTraceTest([{name:'blah'}, {name: 'test', locals: [{name: 'var1'}, {name: 'var2'}]}], 'test');
 runStackTraceTest([{name:'blah'}, {name: 'test1'}, {name: 'test2'}], 'test1');
 runStackTraceTest([{name:'blah'}, {name: 'test☃'}], 'test☃');
 runStackTraceTest([{name:'blah'}, {name: 'te\xE0\xFF'}], 'te\xE0\xFF');
 runStackTraceTest([{name:'blah'}], 'wasm-function[1]');
 runStackTraceTest([], 'wasm-function[1]');
 // Notice that invalid names section content shall not fail the parsing
 runStackTraceTest([{name:'blah'}, {nameLen: 100, name: 'test'}], 'wasm-function[1]'); // invalid name size
-runStackTraceTest([{name:'blah'}, {name: 'test', locals: [{nameLen: 40, name: 'var1'}]}], 'wasm-function[1]'); // invalid variable name size
 runStackTraceTest([{name:'blah'}, {name: ''}], 'wasm-function[1]'); // empty name
--- a/js/src/wasm/WasmBinaryConstants.h
+++ b/js/src/wasm/WasmBinaryConstants.h
@@ -40,16 +40,22 @@ enum class SectionId
     Global                               = 6,
     Export                               = 7,
     Start                                = 8,
     Elem                                 = 9,
     Code                                 = 10,
     Data                                 = 11
 };
 
+enum class NameSectionSubsection
+{
+    TypeFunction                        = 1,
+    TypeLocal                           = 2
+};
+
 enum class TypeCode
 {
     I32                                  = 0x7f,  // SLEB128(-0x01)
     I64                                  = 0x7e,  // SLEB128(-0x02)
     F32                                  = 0x7d,  // SLEB128(-0x03)
     F64                                  = 0x7c,  // SLEB128(-0x04)
 
     // Only emitted internally for asm.js, likely to get collapsed into I128
--- a/js/src/wasm/WasmValidate.cpp
+++ b/js/src/wasm/WasmValidate.cpp
@@ -1558,65 +1558,64 @@ DecodeDataSection(Decoder& d, ModuleEnvi
         return false;
 
     return true;
 }
 
 static void
 MaybeDecodeNameSectionBody(Decoder& d, ModuleEnvironment* env)
 {
-    // For simplicity, ignore all failures, even OOM. Failure will simply result
-    // in the names section not being included for this module.
-
-    uint32_t numFuncNames;
-    if (!d.readVarU32(&numFuncNames))
+    uint8_t subsectionType = UINT8_MAX;
+    if (!d.readFixedU8(&subsectionType))
         return;
 
-    if (numFuncNames > MaxFuncs)
+    if (subsectionType != uint8_t(NameSectionSubsection::TypeFunction))
+        return;
+
+    uint32_t payloadLen = 0;
+    if (!d.readVarU32(&payloadLen) || !payloadLen)
         return;
 
-    // Use a local vector (and not env->funcNames) since it could result in a
-    // partially initialized result in case of failure in the middle.
-    NameInBytecodeVector funcNames;
-    if (!funcNames.resize(numFuncNames))
+    uint32_t payloadLenOffset = d.currentOffset();
+
+    uint32_t nameCount = 0;
+    if (!d.readVarU32(&nameCount) || !nameCount)
         return;
 
-    for (uint32_t i = 0; i < numFuncNames; i++) {
-        uint32_t numBytes;
-        if (!d.readVarU32(&numBytes))
-            return;
-        if (numBytes > MaxStringLength)
+    if (nameCount > MaxFuncs)
+        return;
+
+    NameInBytecodeVector funcNames;
+    if (!funcNames.resize(nameCount))
+        return;
+
+    for (uint32_t i = 0; i < nameCount; ++i) {
+        uint32_t funcIndex = 0;
+        if (!d.readVarU32(&funcIndex))
             return;
 
-        NameInBytecode name;
-        name.offset = d.currentOffset();
-        name.length = numBytes;
-        funcNames[i] = name;
+        uint32_t nameLen = 0;
+        if (!d.readVarU32(&nameLen))
+            return;
 
-        if (!d.readBytes(numBytes))
+        if (nameLen > MaxStringLength)
             return;
 
-        // Skip local names for a function.
-        uint32_t numLocals;
-        if (!d.readVarU32(&numLocals))
-            return;
-        if (numLocals > MaxLocals)
+        NameInBytecode func;
+        func.offset = d.currentOffset();
+        func.length = nameLen;
+
+        if (!d.readBytes(nameLen))
             return;
 
-        for (uint32_t j = 0; j < numLocals; j++) {
-            uint32_t numBytes;
-            if (!d.readVarU32(&numBytes))
-                return;
-            if (numBytes > MaxStringLength)
-                return;
+        funcNames[funcIndex] = func;
+    }
 
-            if (!d.readBytes(numBytes))
-                return;
-        }
-    }
+    if (d.currentOffset() != payloadLenOffset + payloadLen)
+        return;
 
     env->funcNames = Move(funcNames);
 }
 
 static bool
 DecodeNameSection(Decoder& d, ModuleEnvironment* env)
 {
     uint32_t sectionStart, sectionSize;