// Copyright 2017 the V8 project authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. // Flags: --wasm-test-streaming --wasm-async-compilation --expose-wasm --allow-natives-syntax 'use strict'; load('test/mjsunit/wasm/wasm-constants.js'); load('test/mjsunit/wasm/wasm-module-builder.js'); function module(bytes) { let buffer = bytes; if (typeof buffer === 'string') { buffer = new ArrayBuffer(bytes.length); let view = new Uint8Array(buffer); for (let i = 0; i < bytes.length; ++i) { view[i] = bytes.charCodeAt(i); } } return new WebAssembly.Module(buffer); } function toBuffer(binary) { let buffer = new ArrayBuffer(binary.length); let view = new Uint8Array(buffer); for (let i = 0; i < binary.length; i++) { let val = binary[i]; if ((typeof val) == 'string') val = val.charCodeAt(0); view[i] = val | 0; } return buffer; } function testErrorPosition(bytes, pos, test_name) { assertPromiseResult( WebAssembly.compile(toBuffer(bytes)), assertUnreachable, e => { print(test_name); assertInstanceof(e, WebAssembly.CompileError); let regex = new RegExp('@\\+' + pos); print(e.message); assertMatches(regex, e.message, 'Error Position'); }); } (function testInvalidMagic() { let bytes = new Binary; bytes.push( kWasmH0, kWasmH1 + 1, kWasmH2, kWasmH3, kWasmV0, kWasmV1, kWasmV2, kWasmV3); // Error at pos==0 because that's where the magic word is. testErrorPosition(bytes, 0, 'testInvalidMagic'); })(); (function testInvalidVersion() { let bytes = new Binary; bytes.push( kWasmH0, kWasmH1, kWasmH2, kWasmH3, kWasmV0, kWasmV1 + 1, kWasmV2, kWasmV3); // Error at pos==4 because that's where the version word is. testErrorPosition(bytes, 4, 'testInvalidVersion'); })(); (function testSectionLengthInvalidVarint() { let bytes = new Binary; bytes.emit_header(); bytes.emit_u8(kTypeSectionCode); bytes.push(0x80, 0x80, 0x80, 0x80, 0x80, 0x00); let pos = bytes.length - 1 - 1; testErrorPosition(bytes, pos, 'testSectionLengthInvalidVarint'); })(); (function testSectionLengthTooBig() { let bytes = new Binary; bytes.emit_header(); bytes.emit_u8(kTypeSectionCode); bytes.emit_u32v(0xffffff23); let pos = bytes.length - 1; testErrorPosition(bytes, pos, 'testSectionLengthTooBig'); })(); (function testFunctionsCountInvalidVarint() { let bytes = new Binary; bytes.emit_header(); bytes.push( kTypeSectionCode, // section id 1, // section length 0 // number of types ); bytes.push( kFunctionSectionCode, // section id 1, // section length 0 // number of functions ); bytes.push( kCodeSectionCode, // section id 20, // section length (arbitrary value > 6) ); // Functions count bytes.push(0x80, 0x80, 0x80, 0x80, 0x80, 0x00); let pos = bytes.length - 1 - 1; testErrorPosition(bytes, pos, 'testFunctionsCountInvalidVarint'); })(); (function testFunctionsCountTooBig() { let bytes = new Binary; bytes.emit_header(); bytes.push( kTypeSectionCode, // section id 1, // section length 0 // number of types ); bytes.push( kFunctionSectionCode, // section id 1, // section length 0 // number of functions ); bytes.push( kCodeSectionCode, // section id 20, // section length (arbitrary value > 6) ); // Functions count bytes.emit_u32v(0xffffff23); let pos = bytes.length - 1; testErrorPosition(bytes, pos, 'testFunctionsCountTooBig'); })(); (function testFunctionsCountDoesNotMatch() { let bytes = new Binary; bytes.emit_header(); bytes.push( kTypeSectionCode, // section id 1, // section length 0 // number of types ); bytes.push( kFunctionSectionCode, // section id 1, // section length 0 // number of functions ); bytes.push( kCodeSectionCode, // section id 20, // section length (arbitrary value > 6) ); // Functions count (different than the count in the functions section. bytes.emit_u32v(5); let pos = bytes.length - 1; testErrorPosition(bytes, pos, 'testFunctionsCountDoesNotMatch'); })(); (function testBodySizeInvalidVarint() { let bytes = new Binary; bytes.emit_header(); bytes.push( kTypeSectionCode, // section id 4, // section length 1, // number of types kWasmFunctionTypeForm, // type 0, // number of parameter 0 // number of returns ); bytes.push( kFunctionSectionCode, // section id 2, // section length 1, // number of functions 0 // signature index ); bytes.push( kCodeSectionCode, // section id 20, // section length (arbitrary value > 6) 1 // functions count ); // Invalid function body size. bytes.push(0x80, 0x80, 0x80, 0x80, 0x80, 0x00); let pos = bytes.length - 1 - 1; testErrorPosition(bytes, pos, 'testBodySizeInvalidVarint'); })(); (function testBodySizeTooBig() { let bytes = new Binary; bytes.emit_header(); bytes.push( kTypeSectionCode, // section id 4, // section length 1, // number of types kWasmFunctionTypeForm, // type 0, // number of parameter 0 // number of returns ); bytes.push( kFunctionSectionCode, // section id 2, // section length 1, // number of functions 0 // signature index ); bytes.push( kCodeSectionCode, // section id 20, // section length (arbitrary value > 6) 1 // functions count ); // Invalid function body size. bytes.emit_u32v(0xffffff23); let pos = bytes.length - 1; testErrorPosition(bytes, pos, 'testBodySizeTooBig'); })(); (function testBodySizeDoesNotFit() { let bytes = new Binary; bytes.emit_header(); bytes.push( kTypeSectionCode, // section id 4, // section length 1, // number of types kWasmFunctionTypeForm, // type 0, // number of parameter 0 // number of returns ); bytes.push( kFunctionSectionCode, // section id 2, // section length 1, // number of functions 0 // signature index ); bytes.push( kCodeSectionCode, // section id 20, // section length (arbitrary value > 6) 1 // functions count ); // Invalid function body size (does not fit into the code section). bytes.emit_u32v(20); let pos = bytes.length - 1; testErrorPosition(bytes, pos, 'testBodySizeDoesNotFit'); })(); (function testBodySizeIsZero() { let bytes = new Binary; bytes.emit_header(); bytes.push( kTypeSectionCode, // section id 4, // section length 1, // number of types kWasmFunctionTypeForm, // type 0, // number of parameter 0 // number of returns ); bytes.push( kFunctionSectionCode, // section id 2, // section length 1, // number of functions 0 // signature index ); bytes.push( kCodeSectionCode, // section id 20, // section length (arbitrary value > 6) 1 // functions count ); // Invalid function body size (body size of 0 is invalid). bytes.emit_u32v(0); let pos = bytes.length - 1; testErrorPosition(bytes, pos, 'testBodySizeIsZero'); })(); (function testStaleCodeSectionBytes() { let bytes = new Binary; bytes.emit_header(); bytes.push( kTypeSectionCode, // section id 4, // section length 1, // number of types kWasmFunctionTypeForm, // type 0, // number of parameter 0 // number of returns ); bytes.push( kFunctionSectionCode, // section id 2, // section length 1, // number of functions 0 // signature index ); bytes.push( kCodeSectionCode, // section id 20, // section length (too big) 1, // functions count 2, // body size 0, // locals count kExprEnd // body ); let pos = bytes.length - 1; testErrorPosition(bytes, pos, 'testStaleCodeSectionBytes'); })(); (function testInvalidCode() { let bytes = new Binary; bytes.emit_header(); bytes.push( kTypeSectionCode, // section id 4, // section length 1, // number of types kWasmFunctionTypeForm, // type 0, // number of parameter 0 // number of returns ); bytes.push( kFunctionSectionCode, // section id 2, // section length 1, // number of functions 0 // signature index ); bytes.push( kCodeSectionCode, // section id 6, // section length (too big) 1, // functions count 4, // body size 0, // locals count kExprGetLocal, 0, // Access a non-existing local kExprEnd // -- ); // Find error at the index of kExprGetLocal. let pos = bytes.length - 1 - 1; testErrorPosition(bytes, pos, 'testInvalidCode'); })(); (function testCodeSectionSizeZero() { let bytes = new Binary; bytes.emit_header(); bytes.push( kTypeSectionCode, // section id 4, // section length 1, // number of types kWasmFunctionTypeForm, // type 0, // number of parameter 0 // number of returns ); bytes.push( kFunctionSectionCode, // section id 2, // section length 1, // number of functions 0 // signature index ); bytes.push( kCodeSectionCode, // section id 0, // section length (too big) ); // Find error at the index of kExprGetLocal. let pos = bytes.length - 1; testErrorPosition(bytes, pos, 'testCodeSectionSizeZero'); })(); (function testInvalidSection() { let bytes = new Binary; bytes.emit_header(); bytes.push( kTypeSectionCode, // section id 5, // section length 1, // number of types kWasmFunctionTypeForm, // type 1, // number of parameter 0x7b, // invalid type 0 // number of returns ); let pos = bytes.length - 1 - 1; testErrorPosition(bytes, pos, 'testInvalidSection'); })();