diff options
39 files changed, 255 insertions, 2 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index 02662b8d..ba94e526 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -317,6 +317,9 @@ if (NOT EMSCRIPTEN) # wat-desugar wabt_executable(wat-desugar src/tools/wat-desugar.cc) + # wasm-validate + wabt_executable(wasm-validate src/tools/wasm-validate.cc) + find_package(Threads) if (BUILD_TESTS) if (NOT EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/third_party/gtest/googletest) diff --git a/src/tools/wasm-validate.cc b/src/tools/wasm-validate.cc new file mode 100644 index 00000000..919d0bf4 --- /dev/null +++ b/src/tools/wasm-validate.cc @@ -0,0 +1,94 @@ +/* + * Copyright 2017 WebAssembly Community Group participants + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include <cassert> +#include <cinttypes> +#include <cstdio> +#include <cstdlib> + +#include "src/binary-reader.h" +#include "src/binary-reader-ir.h" +#include "src/error-handler.h" +#include "src/ir.h" +#include "src/option-parser.h" +#include "src/stream.h" +#include "src/validator.h" +#include "src/wast-lexer.h" + +using namespace wabt; + +static int s_verbose; +static std::string s_infile; +static Features s_features; +static bool s_read_debug_names = true; +static std::unique_ptr<FileStream> s_log_stream; + +static const char s_description[] = +R"( Read a file in the WebAssembly binary format, and validate it. + +examples: + # validate binary file test.wasm + $ wasm-validate test.wasm +)"; + +static void ParseOptions(int argc, char** argv) { + OptionParser parser("wasm-validate", s_description); + + parser.AddOption('v', "verbose", "Use multiple times for more info", []() { + s_verbose++; + s_log_stream = FileStream::CreateStdout(); + }); + parser.AddHelpOption(); + s_features.AddOptions(&parser); + parser.AddOption("no-debug-names", "Ignore debug names in the binary file", + []() { s_read_debug_names = false; }); + parser.AddArgument("filename", OptionParser::ArgumentCount::One, + [](const char* argument) { + s_infile = argument; + ConvertBackslashToSlash(&s_infile); + }); + parser.Parse(argc, argv); +} + +int ProgramMain(int argc, char** argv) { + Result result; + + InitStdio(); + ParseOptions(argc, argv); + + std::vector<uint8_t> file_data; + result = ReadFile(s_infile.c_str(), &file_data); + if (Succeeded(result)) { + ErrorHandlerFile error_handler(Location::Type::Binary); + Module module; + const bool kStopOnFirstError = true; + ReadBinaryOptions options(s_features, s_log_stream.get(), + s_read_debug_names, kStopOnFirstError); + result = ReadBinaryIr(s_infile.c_str(), DataOrNull(file_data), + file_data.size(), &options, &error_handler, &module); + if (Succeeded(result)) { + WastLexer* lexer = nullptr; + result = ValidateModule(lexer, &module, &error_handler); + } + } + return result != Result::Ok; +} + +int main(int argc, char** argv) { + WABT_TRY + return ProgramMain(argc, argv); + WABT_CATCH_BAD_ALLOC_AND_EXIT +} diff --git a/test/binary/bad-duplicate-section-around-custom.txt b/test/binary/bad-duplicate-section-around-custom.txt index fcbe72a8..de140958 100644 --- a/test/binary/bad-duplicate-section-around-custom.txt +++ b/test/binary/bad-duplicate-section-around-custom.txt @@ -6,6 +6,9 @@ section(TYPE) { count[0] } section("foo") { 1 2 3 4 } section(TYPE) { count[0] } (;; STDERR ;;; +Error running "wasm-validate": +0000017: error: section Type out of order + Error running "wasm2wat": 0000017: error: section Type out of order diff --git a/test/binary/bad-duplicate-section.txt b/test/binary/bad-duplicate-section.txt index 190ad39b..25cb178d 100644 --- a/test/binary/bad-duplicate-section.txt +++ b/test/binary/bad-duplicate-section.txt @@ -5,6 +5,9 @@ version section(TYPE) { count[0] } section(TYPE) { count[0] } (;; STDERR ;;; +Error running "wasm-validate": +000000d: error: section Type out of order + Error running "wasm2wat": 000000d: error: section Type out of order diff --git a/test/binary/bad-duplicate-subsection.txt b/test/binary/bad-duplicate-subsection.txt index ef9b04d8..b3d0f479 100644 --- a/test/binary/bad-duplicate-subsection.txt +++ b/test/binary/bad-duplicate-subsection.txt @@ -20,6 +20,9 @@ section("name") { count[0] } (;; STDERR ;;; +Error running "wasm-validate": +0000028: error: duplicate sub-section + Error running "wasm2wat": 0000028: error: duplicate sub-section diff --git a/test/binary/bad-export-func.txt b/test/binary/bad-export-func.txt index 1dd4f640..0b978948 100644 --- a/test/binary/bad-export-func.txt +++ b/test/binary/bad-export-func.txt @@ -6,6 +6,9 @@ section(TYPE) { count[1] function params[0] results[0] } section(FUNCTION) { count[1] sig[0] } section(EXPORT) { count[1] str("foo") func_kind func[1] } (;; STDERR ;;; +Error running "wasm-validate": +000001b: error: invalid export func index: 1 + Error running "wasm2wat": 000001b: error: invalid export func index: 1 diff --git a/test/binary/bad-extra-end.txt b/test/binary/bad-extra-end.txt index f7330335..eeab1e1e 100644 --- a/test/binary/bad-extra-end.txt +++ b/test/binary/bad-extra-end.txt @@ -13,6 +13,10 @@ section(CODE) { } } (;; STDERR ;;; +Error running "wasm-validate": +error: popping empty label stack +000001a: error: OnEndExpr callback failed + Error running "wasm2wat": error: popping empty label stack 000001a: error: OnEndExpr callback failed diff --git a/test/binary/bad-function-body-count.txt b/test/binary/bad-function-body-count.txt index d76302f6..bd6dbc75 100644 --- a/test/binary/bad-function-body-count.txt +++ b/test/binary/bad-function-body-count.txt @@ -9,6 +9,9 @@ section(CODE) { func { locals[0] } } (;; STDERR ;;; +Error running "wasm-validate": +0000016: error: function signature count != function body count + Error running "wasm2wat": 0000016: error: function signature count != function body count diff --git a/test/binary/bad-function-local-type.txt b/test/binary/bad-function-local-type.txt index 10654005..0886c825 100644 --- a/test/binary/bad-function-local-type.txt +++ b/test/binary/bad-function-local-type.txt @@ -12,6 +12,9 @@ section(CODE) { } } (;; STDERR ;;; +Error running "wasm-validate": +0000019: error: expected valid local type + Error running "wasm2wat": 0000019: error: expected valid local type diff --git a/test/binary/bad-function-names-too-many.txt b/test/binary/bad-function-names-too-many.txt index e1aaff30..0cddb3e0 100644 --- a/test/binary/bad-function-names-too-many.txt +++ b/test/binary/bad-function-names-too-many.txt @@ -15,6 +15,10 @@ section("name") { str("g") } (;; STDERR ;;; +Error running "wasm-validate": +error: expected function name count (2) <= function count (1) +0000023: error: OnFunctionNamesCount callback failed + Error running "wasm2wat": error: expected function name count (2) <= function count (1) 0000023: error: OnFunctionNamesCount callback failed diff --git a/test/binary/bad-function-param-type.txt b/test/binary/bad-function-param-type.txt index 756a69b2..37d1a0ee 100644 --- a/test/binary/bad-function-param-type.txt +++ b/test/binary/bad-function-param-type.txt @@ -7,6 +7,9 @@ section(TYPE) { function params[1] void results[0] } (;; STDERR ;;; +Error running "wasm-validate": +000000e: error: expected valid param type (got -64) + Error running "wasm2wat": 000000e: error: expected valid param type (got -64) diff --git a/test/binary/bad-function-result-type.txt b/test/binary/bad-function-result-type.txt index cfb0e62c..6809d9c3 100644 --- a/test/binary/bad-function-result-type.txt +++ b/test/binary/bad-function-result-type.txt @@ -7,6 +7,9 @@ section(TYPE) { function params[1] i32 results[1] void } (;; STDERR ;;; +Error running "wasm-validate": +0000010: error: expected valid result type: -64 + Error running "wasm2wat": 0000010: error: expected valid result type: -64 diff --git a/test/binary/bad-function-sig.txt b/test/binary/bad-function-sig.txt index e68cb889..0ba6a86d 100644 --- a/test/binary/bad-function-sig.txt +++ b/test/binary/bad-function-sig.txt @@ -5,6 +5,9 @@ version section(TYPE) { count[1] function params[1] i32 results[1] i32 } section(FUNCTION) { count[1] type[1] } (;; STDERR ;;; +Error running "wasm-validate": +0000014: error: invalid function signature index: 1 + Error running "wasm2wat": 0000014: error: invalid function signature index: 1 diff --git a/test/binary/bad-function-too-many-results.txt b/test/binary/bad-function-too-many-results.txt index cd05abde..ead52c1a 100644 --- a/test/binary/bad-function-too-many-results.txt +++ b/test/binary/bad-function-too-many-results.txt @@ -4,6 +4,9 @@ magic version section(TYPE) { count[1] function params[0] results[2] i32 i32 } (;; STDERR ;;; +Error running "wasm-validate": +000000e: error: result count must be 0 or 1 + Error running "wasm2wat": 000000e: error: result count must be 0 or 1 diff --git a/test/binary/bad-import-sig.txt b/test/binary/bad-import-sig.txt index 9e81a66a..ebec6efd 100644 --- a/test/binary/bad-import-sig.txt +++ b/test/binary/bad-import-sig.txt @@ -5,6 +5,9 @@ version section(TYPE) { count[1] function params[0] results[1] i32 } section(IMPORT) { count[1] str("module") str("func") func_kind type[1] } (;; STDERR ;;; +Error running "wasm-validate": +0000020: error: invalid import signature index + Error running "wasm2wat": 0000020: error: invalid import signature index diff --git a/test/binary/bad-magic.txt b/test/binary/bad-magic.txt index bb13f7b6..8cb6a2c5 100644 --- a/test/binary/bad-magic.txt +++ b/test/binary/bad-magic.txt @@ -3,6 +3,9 @@ 0 "ASM" version (;; STDERR ;;; +Error running "wasm-validate": +0000004: error: bad magic value + Error running "wasm2wat": 0000004: error: bad magic value diff --git a/test/binary/bad-memory-init-max-size.txt b/test/binary/bad-memory-init-max-size.txt index f5ef8a0f..3a8b2121 100644 --- a/test/binary/bad-memory-init-max-size.txt +++ b/test/binary/bad-memory-init-max-size.txt @@ -9,6 +9,9 @@ section(MEMORY) { max[1] } (;; STDERR ;;; +Error running "wasm-validate": +000000e: error: memory initial size must be <= max size + Error running "wasm2wat": 000000e: error: memory initial size must be <= max size diff --git a/test/binary/bad-memory-init-size.txt b/test/binary/bad-memory-init-size.txt index f6a5711c..864833e8 100644 --- a/test/binary/bad-memory-init-size.txt +++ b/test/binary/bad-memory-init-size.txt @@ -8,6 +8,9 @@ section(MEMORY) { initial[leb_u32(65537)] } (;; STDERR ;;; +Error running "wasm-validate": +000000f: error: invalid memory initial size + Error running "wasm2wat": 000000f: error: invalid memory initial size diff --git a/test/binary/bad-memory-max-size.txt b/test/binary/bad-memory-max-size.txt index 683a19e0..ada64820 100644 --- a/test/binary/bad-memory-max-size.txt +++ b/test/binary/bad-memory-max-size.txt @@ -9,6 +9,9 @@ section(MEMORY) { max[leb_u32(65537)] } (;; STDERR ;;; +Error running "wasm-validate": +0000010: error: invalid memory max size + Error running "wasm2wat": 0000010: error: invalid memory max size diff --git a/test/binary/bad-name-section-invalid-index.txt b/test/binary/bad-name-section-invalid-index.txt index 3301f1f0..9270cf8f 100644 --- a/test/binary/bad-name-section-invalid-index.txt +++ b/test/binary/bad-name-section-invalid-index.txt @@ -19,6 +19,9 @@ section("name") { str("$F0") } (;; STDERR ;;; +Error running "wasm-validate": +0000028: error: invalid function index: 8 + Error running "wasm2wat": 0000028: error: invalid function index: 8 diff --git a/test/binary/bad-names-duplicate-locals.txt b/test/binary/bad-names-duplicate-locals.txt index 1e96f65a..ad8d55e6 100644 --- a/test/binary/bad-names-duplicate-locals.txt +++ b/test/binary/bad-names-duplicate-locals.txt @@ -28,6 +28,9 @@ section("name") { str("L1") } (;; STDERR ;;; +Error running "wasm-validate": +0000035: error: duplicate local index: 0 + Error running "wasm2wat": 0000035: error: duplicate local index: 0 diff --git a/test/binary/bad-names-duplicates.txt b/test/binary/bad-names-duplicates.txt index 611c7c59..e6d64479 100644 --- a/test/binary/bad-names-duplicates.txt +++ b/test/binary/bad-names-duplicates.txt @@ -20,6 +20,9 @@ section("name") { str("F1") } (;; STDERR ;;; +Error running "wasm-validate": +000002c: error: duplicate function name: 0 + Error running "wasm2wat": 000002c: error: duplicate function name: 0 diff --git a/test/binary/bad-names-function-locals-out-of-order.txt b/test/binary/bad-names-function-locals-out-of-order.txt index 864fd7e9..1ea7c9b7 100644 --- a/test/binary/bad-names-function-locals-out-of-order.txt +++ b/test/binary/bad-names-function-locals-out-of-order.txt @@ -31,6 +31,9 @@ section("name") { str("L0") } (;; STDERR ;;; +Error running "wasm-validate": +000003d: error: locals function index out of order: 0 + Error running "wasm2wat": 000003d: error: locals function index out of order: 0 diff --git a/test/binary/bad-names-locals-out-of-order.txt b/test/binary/bad-names-locals-out-of-order.txt index f5234588..3a6e01c0 100644 --- a/test/binary/bad-names-locals-out-of-order.txt +++ b/test/binary/bad-names-locals-out-of-order.txt @@ -28,6 +28,9 @@ section("name") { str("L0") } (;; STDERR ;;; +Error running "wasm-validate": +0000035: error: local index out of order: 0 + Error running "wasm2wat": 0000035: error: local index out of order: 0 diff --git a/test/binary/bad-names-out-of-order.txt b/test/binary/bad-names-out-of-order.txt index 02a8122c..98c71f22 100644 --- a/test/binary/bad-names-out-of-order.txt +++ b/test/binary/bad-names-out-of-order.txt @@ -21,6 +21,9 @@ section("name") { str("F0") } (;; STDERR ;;; +Error running "wasm-validate": +000002c: error: function index out of order: 0 + Error running "wasm2wat": 000002c: error: function index out of order: 0 diff --git a/test/binary/bad-op-after-end.txt b/test/binary/bad-op-after-end.txt index da64af13..5cf38c9f 100644 --- a/test/binary/bad-op-after-end.txt +++ b/test/binary/bad-op-after-end.txt @@ -13,6 +13,10 @@ section(CODE) { } } (;; STDERR ;;; +Error running "wasm-validate": +error: accessing stack depth: 0 >= max: 0 +000001a: error: OnNopExpr callback failed + Error running "wasm2wat": error: accessing stack depth: 0 >= max: 0 000001a: error: OnNopExpr callback failed diff --git a/test/binary/bad-section-ends-early.txt b/test/binary/bad-section-ends-early.txt index d983e6d4..824cc0ae 100644 --- a/test/binary/bad-section-ends-early.txt +++ b/test/binary/bad-section-ends-early.txt @@ -14,6 +14,9 @@ dummy[0] dummy[0] dummy[0] (;; STDERR ;;; +Error running "wasm-validate": +000000b: error: unfinished section (expected end: 0xf) + Error running "wasm2wat": 000000b: error: unfinished section (expected end: 0xf) diff --git a/test/binary/bad-section-size-zero.txt b/test/binary/bad-section-size-zero.txt index 2eb7350b..18861a83 100644 --- a/test/binary/bad-section-size-zero.txt +++ b/test/binary/bad-section-size-zero.txt @@ -6,6 +6,9 @@ section_code[1] section_size[0] ;; garbage after the section; shouldn't be read 1 2 3 4 5 (;; STDERR ;;; +Error running "wasm-validate": +000000a: error: unable to read u32 leb128: type count + Error running "wasm2wat": 000000a: error: unable to read u32 leb128: type count diff --git a/test/binary/bad-segment-no-memory.txt b/test/binary/bad-segment-no-memory.txt index 5e426ee8..2a7aa6e2 100644 --- a/test/binary/bad-segment-no-memory.txt +++ b/test/binary/bad-segment-no-memory.txt @@ -8,6 +8,9 @@ section(DATA) { data[str("hi")] } (;; STDERR ;;; +Error running "wasm-validate": +000000b: error: data section without memory section + Error running "wasm2wat": 000000b: error: data section without memory section diff --git a/test/binary/bad-start-func.txt b/test/binary/bad-start-func.txt index 112653d2..0d683d39 100644 --- a/test/binary/bad-start-func.txt +++ b/test/binary/bad-start-func.txt @@ -6,6 +6,9 @@ section(TYPE) { count[1] function params[0] results[0] } section(FUNCTION) { count[1] sig[0] } section(START) { func[1] } (;; STDERR ;;; +Error running "wasm-validate": +0000015: error: invalid start function index: 1 + Error running "wasm2wat": 0000015: error: invalid start function index: 1 diff --git a/test/binary/bad-subsection-out-of-order.txt b/test/binary/bad-subsection-out-of-order.txt index b0eeb489..947036fd 100644 --- a/test/binary/bad-subsection-out-of-order.txt +++ b/test/binary/bad-subsection-out-of-order.txt @@ -20,6 +20,9 @@ section("name") { count[0] } (;; STDERR ;;; +Error running "wasm-validate": +0000028: error: out-of-order sub-section + Error running "wasm2wat": 0000028: error: out-of-order sub-section diff --git a/test/binary/bad-subsection-size.txt b/test/binary/bad-subsection-size.txt index 4f9bba22..f96290e4 100644 --- a/test/binary/bad-subsection-size.txt +++ b/test/binary/bad-subsection-size.txt @@ -19,6 +19,9 @@ section("name") { str("$F0") } (;; STDERR ;;; +Error running "wasm-validate": +0000027: error: unable to read u32 leb128: function index + Error running "wasm2wat": 0000027: error: unable to read u32 leb128: function index diff --git a/test/binary/bad-subsection-unfinished.txt b/test/binary/bad-subsection-unfinished.txt index 6a281b47..6d3bef12 100644 --- a/test/binary/bad-subsection-unfinished.txt +++ b/test/binary/bad-subsection-unfinished.txt @@ -23,6 +23,9 @@ section("name") { data[1] } (;; STDERR ;;; +Error running "wasm-validate": +000002c: error: unfinished sub-section (expected end: 0x30) + Error running "wasm2wat": 000002c: error: unfinished sub-section (expected end: 0x30) diff --git a/test/binary/bad-type-form.txt b/test/binary/bad-type-form.txt index d26ee974..dd53c929 100644 --- a/test/binary/bad-type-form.txt +++ b/test/binary/bad-type-form.txt @@ -7,6 +7,9 @@ section(TYPE) { 0x20 } (;; STDERR ;;; +Error running "wasm-validate": +000000c: error: unexpected type form: 32 + Error running "wasm2wat": 000000c: error: unexpected type form: 32 diff --git a/test/binary/bad-typecheck-missing-drop.txt b/test/binary/bad-typecheck-missing-drop.txt index 16046ded..f49277f5 100644 --- a/test/binary/bad-typecheck-missing-drop.txt +++ b/test/binary/bad-typecheck-missing-drop.txt @@ -14,6 +14,9 @@ section(CODE) { } } (;; STDERR ;;; +Error running "wasm-validate": +out/test/binary/bad-typecheck-missing-drop/bad-typecheck-missing-drop.wasm:000001c: error: type mismatch in function, expected [] but got [i32] + Error running "wasm2wat": out/test/binary/bad-typecheck-missing-drop/bad-typecheck-missing-drop.wasm:000001c: error: type mismatch in function, expected [] but got [i32] diff --git a/test/binary/bad-version.txt b/test/binary/bad-version.txt index f815fd2d..2a5aa3ca 100644 --- a/test/binary/bad-version.txt +++ b/test/binary/bad-version.txt @@ -3,6 +3,9 @@ magic 0xe 0 0 0 (;; STDERR ;;; +Error running "wasm-validate": +0000008: error: bad wasm file version: 0xe (expected 0x1) + Error running "wasm2wat": 0000008: error: bad wasm file version: 0xe (expected 0x1) diff --git a/test/find_exe.py b/test/find_exe.py index e75379a9..5bc919a6 100644 --- a/test/find_exe.py +++ b/test/find_exe.py @@ -26,6 +26,7 @@ REPO_ROOT_DIR = os.path.dirname(SCRIPT_DIR) EXECUTABLES = [ 'wat2wasm', 'wast2json', 'wasm2wat', 'wasm-objdump', 'wasm-interp', 'wasm-opcodecnt', 'wat-desugar', 'wasm-link', 'spectest-interp', + 'wasm-validate', ] @@ -98,3 +99,7 @@ def GetWasmOpcodeCntExecutable(override=None): def GetWatDesugarExecutable(override=None): return FindExecutable('wat-desugar', override) + + +def GetWasmValidateExecutable(override=None): + return FindExecutable('wasm-validate', override) diff --git a/test/help/wasm-validate.txt b/test/help/wasm-validate.txt new file mode 100644 index 00000000..f0cab51b --- /dev/null +++ b/test/help/wasm-validate.txt @@ -0,0 +1,19 @@ +;;; EXE: %(wasm-validate)s +;;; FLAGS: --help +(;; STDOUT ;;; +usage: wasm-validate [options] filename + + Read a file in the WebAssembly binary format, and validate it. + +examples: + # validate binary file test.wasm + $ wasm-validate test.wasm + +options: + -v, --verbose Use multiple times for more info + -h, --help Print this help message + --enable-exceptions Experimental exception handling + --enable-saturating-float-to-int Saturating float-to-int operators + --enable-threads Threading support + --no-debug-names Ignore debug names in the binary file +;;; STDOUT ;;) diff --git a/test/run-gen-wasm.py b/test/run-gen-wasm.py index 4b1aa8aa..0d8344f0 100755 --- a/test/run-gen-wasm.py +++ b/test/run-gen-wasm.py @@ -64,11 +64,19 @@ def main(args): error_cmdline=options.error_cmdline) wasm2wat.AppendOptionalArgs({ '--no-debug-names': options.no_debug_names, + '--verbose': options.verbose, + }) + + wasmvalidate = utils.Executable( + find_exe.GetWasmValidateExecutable(options.bindir), + error_cmdline=options.error_cmdline) + wasmvalidate.AppendOptionalArgs({ + '--no-debug-names': options.no_debug_names, }) - wasm2wat.AppendOptionalArgs({'--verbose': options.verbose,}) gen_wasm.verbose = options.print_cmd wasm2wat.verbose = options.print_cmd + wasmvalidate.verbose = options.print_cmd objdump.verbose = options.print_cmd with utils.TempDirectory(options.out_dir, 'run-gen-wasm-') as out_dir: @@ -77,7 +85,26 @@ def main(args): if options.objdump: objdump.RunWithArgs(out_file, '-x') else: - wasm2wat.RunWithArgs(out_file) + # Test running wasm-validate on all files. wasm2wat should produce the + # same errors, so let's make sure that's true. + validate_ok = False + wasm2wat_ok = False + + try: + try: + wasmvalidate.RunWithArgs(out_file) + validate_ok = True + except Error as e: + sys.stderr.write(str(e) + '\n') + + try: + wasm2wat.RunWithArgs(out_file) + wasm2wat_ok = True + except Error as e: + raise + finally: + if validate_ok != wasm2wat_ok: + sys.stderr.write('wasm-validate and wasm2wat have different results!') if __name__ == '__main__': |