Bug 1357911 - [WASM] Update to new name section format. r?luke
MozReview-Commit-ID: 8Jxb6MFGlg8
--- 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;