summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBen Smith <binjimin@gmail.com>2017-09-12 16:30:49 -0700
committerGitHub <noreply@github.com>2017-09-12 16:30:49 -0700
commita4aa20105bc8851b57b50b5c62684c0f36cdbb02 (patch)
tree735c09a2f4f49285ed1791f1baefc125907be540
parentcaf98190ca5267a0864ef019889b31ed16d95f77 (diff)
downloadwabt-a4aa20105bc8851b57b50b5c62684c0f36cdbb02.tar.gz
wabt-a4aa20105bc8851b57b50b5c62684c0f36cdbb02.tar.bz2
wabt-a4aa20105bc8851b57b50b5c62684c0f36cdbb02.zip
Only allow parsing one module with wat2wasm (#622)
`.wat` files can only contain one module, and no assertions. This fixes issue #621.
-rw-r--r--src/emscripten-helpers.cc2
-rw-r--r--src/tools/wasm-interp.cc2
-rw-r--r--src/tools/wast-desugar.cc4
-rw-r--r--src/tools/wast2json.cc4
-rw-r--r--src/tools/wat2wasm.cc17
-rw-r--r--src/wast-parser.cc90
-rw-r--r--src/wast-parser.h24
-rw-r--r--test/parse/bad-crlf.txt2
-rw-r--r--test/parse/bad-error-long-line.txt2
-rw-r--r--test/parse/bad-error-long-token.txt2
-rw-r--r--test/parse/bad-single-semicolon.txt2
-rw-r--r--test/parse/bad-toplevel.txt2
-rw-r--r--test/parse/empty-file.txt2
-rw-r--r--test/parse/module/bad-module-multi.txt10
-rw-r--r--test/parse/module/bad-module-with-assert.txt10
15 files changed, 119 insertions, 56 deletions
diff --git a/src/emscripten-helpers.cc b/src/emscripten-helpers.cc
index 48513fdd..9b0f1117 100644
--- a/src/emscripten-helpers.cc
+++ b/src/emscripten-helpers.cc
@@ -66,7 +66,7 @@ WabtParseWastResult* wabt_parse_wast(wabt::WastLexer* lexer,
wabt::ErrorHandlerBuffer* error_handler) {
WabtParseWastResult* result = new WabtParseWastResult();
std::unique_ptr<wabt::Script> script;
- result->result = wabt::ParseWast(lexer, &script, error_handler);
+ result->result = wabt::ParseWastScript(lexer, &script, error_handler);
result->script = std::move(script);
return result;
}
diff --git a/src/tools/wasm-interp.cc b/src/tools/wasm-interp.cc
index 5c108405..12fdae04 100644
--- a/src/tools/wasm-interp.cc
+++ b/src/tools/wasm-interp.cc
@@ -1014,7 +1014,7 @@ wabt::Result SpecJSONParser::ReadInvalidTextModule(
std::unique_ptr<WastLexer> lexer =
WastLexer::CreateFileLexer(module_filename);
std::unique_ptr<Script> script;
- wabt::Result result = ParseWast(lexer.get(), &script, error_handler);
+ wabt::Result result = ParseWastScript(lexer.get(), &script, error_handler);
if (Succeeded(result)) {
wabt::Module* module = script->GetFirstModule();
result = ResolveNamesModule(lexer.get(), module, error_handler);
diff --git a/src/tools/wast-desugar.cc b/src/tools/wast-desugar.cc
index 03bdc4b8..8aa76af8 100644
--- a/src/tools/wast-desugar.cc
+++ b/src/tools/wast-desugar.cc
@@ -88,8 +88,8 @@ int ProgramMain(int argc, char** argv) {
ErrorHandlerFile error_handler(Location::Type::Text);
std::unique_ptr<Script> script;
WastParseOptions parse_wast_options(s_features);
- Result result =
- ParseWast(lexer.get(), &script, &error_handler, &parse_wast_options);
+ Result result = ParseWastScript(lexer.get(), &script, &error_handler,
+ &parse_wast_options);
if (Succeeded(result)) {
Module* module = script->GetFirstModule();
diff --git a/src/tools/wast2json.cc b/src/tools/wast2json.cc
index 7fb75c72..c13221dd 100644
--- a/src/tools/wast2json.cc
+++ b/src/tools/wast2json.cc
@@ -101,8 +101,8 @@ int ProgramMain(int argc, char** argv) {
ErrorHandlerFile error_handler(Location::Type::Text);
std::unique_ptr<Script> script;
WastParseOptions parse_wast_options(s_features);
- Result result =
- ParseWast(lexer.get(), &script, &error_handler, &parse_wast_options);
+ Result result = ParseWastScript(lexer.get(), &script, &error_handler,
+ &parse_wast_options);
if (Succeeded(result)) {
result = ResolveNamesScript(lexer.get(), script.get(), &error_handler);
diff --git a/src/tools/wat2wasm.cc b/src/tools/wat2wasm.cc
index 20e27908..2eb63a42 100644
--- a/src/tools/wat2wasm.cc
+++ b/src/tools/wat2wasm.cc
@@ -123,26 +123,21 @@ int ProgramMain(int argc, char** argv) {
WABT_FATAL("unable to read file: %s\n", s_infile);
ErrorHandlerFile error_handler(Location::Type::Text);
- // TODO(binji): Parse Module instead of Script.
- std::unique_ptr<Script> script;
+ std::unique_ptr<Module> module;
WastParseOptions parse_wast_options(s_features);
Result result =
- ParseWast(lexer.get(), &script, &error_handler, &parse_wast_options);
+ ParseWatModule(lexer.get(), &module, &error_handler, &parse_wast_options);
if (Succeeded(result)) {
- result = ResolveNamesScript(lexer.get(), script.get(), &error_handler);
+ result = ResolveNamesModule(lexer.get(), module.get(), &error_handler);
if (Succeeded(result) && s_validate)
- result = ValidateScript(lexer.get(), script.get(), &error_handler);
+ result = ValidateModule(lexer.get(), module.get(), &error_handler);
if (Succeeded(result)) {
MemoryStream stream(s_log_stream.get());
- const Module* module = script->GetFirstModule();
- if (module) {
- result = WriteBinaryModule(&stream, module, &s_write_binary_options);
- } else {
- WABT_FATAL("no module found\n");
- }
+ result =
+ WriteBinaryModule(&stream, module.get(), &s_write_binary_options);
if (Succeeded(result))
WriteBufferToFile(s_outfile, stream.output_buffer());
diff --git a/src/wast-parser.cc b/src/wast-parser.cc
index 3048cee2..a9a53973 100644
--- a/src/wast-parser.cc
+++ b/src/wast-parser.cc
@@ -630,9 +630,37 @@ Result WastParser::ParseNat(uint64_t* out_nat) {
return Result::Ok;
}
-Result WastParser::ParseScript() {
+Result WastParser::ParseModule(std::unique_ptr<Module>* out_module) {
+ WABT_TRACE(ParseModule);
+ auto module = MakeUnique<Module>();
+
+ if (PeekMatchLpar(TokenType::Module)) {
+ // Starts with "(module". Allow text and binary modules, but no quoted
+ // modules.
+ CommandPtr command;
+ CHECK_RESULT(ParseModuleCommand(nullptr, &command));
+ auto module_command = cast<ModuleCommand>(std::move(command));
+ *module = std::move(module_command->module);
+ } else if (IsModuleField(PeekPair())) {
+ // Parse an inline module (i.e. one with no surrounding (module)).
+ CHECK_RESULT(ParseModuleFieldList(module.get()));
+ } else {
+ ConsumeIfLpar();
+ ErrorExpected({"a module field", "a module"});
+ }
+
+ EXPECT(Eof);
+ if (errors_ == 0) {
+ *out_module = std::move(module);
+ return Result::Ok;
+ } else {
+ return Result::Error;
+ }
+}
+
+Result WastParser::ParseScript(std::unique_ptr<Script>* out_script) {
WABT_TRACE(ParseScript);
- script_ = MakeUnique<Script>();
+ auto script = MakeUnique<Script>();
// Don't consume the Lpar yet, even though it is required. This way the
// sub-parser functions (e.g. ParseFuncModuleField) can consume it and keep
@@ -642,16 +670,21 @@ Result WastParser::ParseScript() {
auto command = MakeUnique<ModuleCommand>();
command->module.loc = GetLocation();
CHECK_RESULT(ParseModuleFieldList(&command->module));
- script_->commands.emplace_back(std::move(command));
+ script->commands.emplace_back(std::move(command));
} else if (IsCommand(PeekPair())) {
- CHECK_RESULT(ParseCommandList(&script_->commands));
+ CHECK_RESULT(ParseCommandList(script.get(), &script->commands));
} else {
ConsumeIfLpar();
ErrorExpected({"a module field", "a command"});
}
EXPECT(Eof);
- return errors_ == 0 ? Result::Ok : Result::Error;
+ if (errors_ == 0) {
+ *out_script = std::move(script);
+ return Result::Ok;
+ } else {
+ return Result::Error;
+ }
}
Result WastParser::ParseModuleFieldList(Module* module) {
@@ -1660,11 +1693,12 @@ Result WastParser::ParseGlobalType(Global* global) {
return Result::Ok;
}
-Result WastParser::ParseCommandList(CommandPtrVector* commands) {
+Result WastParser::ParseCommandList(Script* script,
+ CommandPtrVector* commands) {
WABT_TRACE(ParseCommandList);
while (IsCommand(PeekPair())) {
CommandPtr command;
- if (Succeeded(ParseCommand(&command))) {
+ if (Succeeded(ParseCommand(script, &command))) {
commands->push_back(std::move(command));
} else {
CHECK_RESULT(Synchronize(IsCommand));
@@ -1673,7 +1707,7 @@ Result WastParser::ParseCommandList(CommandPtrVector* commands) {
return Result::Ok;
}
-Result WastParser::ParseCommand(CommandPtr* out_command) {
+Result WastParser::ParseCommand(Script* script, CommandPtr* out_command) {
WABT_TRACE(ParseCommand);
switch (Peek(1)) {
case TokenType::AssertExhaustion:
@@ -1705,7 +1739,7 @@ Result WastParser::ParseCommand(CommandPtr* out_command) {
return ParseActionCommand(out_command);
case TokenType::Module:
- return ParseModuleCommand(out_command);
+ return ParseModuleCommand(script, out_command);
case TokenType::Register:
return ParseRegisterCommand(out_command);
@@ -1793,7 +1827,7 @@ Result WastParser::ParseActionCommand(CommandPtr* out_command) {
return Result::Ok;
}
-Result WastParser::ParseModuleCommand(CommandPtr* out_command) {
+Result WastParser::ParseModuleCommand(Script* script, CommandPtr* out_command) {
WABT_TRACE(ParseModuleCommand);
std::unique_ptr<ScriptModule> script_module;
CHECK_RESULT(ParseScriptModule(&script_module));
@@ -1822,14 +1856,18 @@ Result WastParser::ParseModuleCommand(CommandPtr* out_command) {
return ErrorExpected({"a binary module", "a text module"});
}
- Index command_index = script_->commands.size();
+ // script is nullptr when ParseModuleCommand is called from ParseModule.
+ if (script) {
+ Index command_index = script->commands.size();
- if (!module.name.empty()) {
- script_->module_bindings.emplace(module.name,
- Binding(module.loc, command_index));
+ if (!module.name.empty()) {
+ script->module_bindings.emplace(module.name,
+ Binding(module.loc, command_index));
+ }
+
+ last_module_index_ = command_index;
}
- last_module_index_ = command_index;
*out_command = std::move(command);
return Result::Ok;
}
@@ -1982,19 +2020,23 @@ void WastParser::CheckImportOrdering(Module* module) {
}
}
-std::unique_ptr<Script> WastParser::ReleaseScript() {
- return std::move(script_);
+Result ParseWatModule(WastLexer* lexer,
+ std::unique_ptr<Module>* out_module,
+ ErrorHandler* error_handler,
+ WastParseOptions* options) {
+ assert(out_module != nullptr);
+ WastParser parser(lexer, error_handler, options);
+ return parser.ParseModule(out_module);
}
-Result ParseWast(WastLexer* lexer,
- std::unique_ptr<Script>* out_script,
- ErrorHandler* error_handler,
- WastParseOptions* options) {
+
+Result ParseWastScript(WastLexer* lexer,
+ std::unique_ptr<Script>* out_script,
+ ErrorHandler* error_handler,
+ WastParseOptions* options) {
assert(out_script != nullptr);
WastParser parser(lexer, error_handler, options);
- Result result = parser.ParseScript();
- *out_script = parser.ReleaseScript();
- return result;
+ return parser.ParseScript(out_script);
}
} // namespace wabt
diff --git a/src/wast-parser.h b/src/wast-parser.h
index 95f5bc96..c537c7f1 100644
--- a/src/wast-parser.h
+++ b/src/wast-parser.h
@@ -43,7 +43,9 @@ class WastParser {
WastParser(WastLexer*, ErrorHandler*, WastParseOptions*);
void WABT_PRINTF_FORMAT(3, 4) Error(Location, const char* format, ...);
- Result ParseScript();
+ Result ParseModule(std::unique_ptr<Module>* out_module);
+ Result ParseScript(std::unique_ptr<Script>* out_script);
+
std::unique_ptr<Script> ReleaseScript();
private:
@@ -168,8 +170,8 @@ class WastParser {
template <typename T>
Result ParsePlainInstrVar(Location, std::unique_ptr<Expr>*);
- Result ParseCommandList(CommandPtrVector*);
- Result ParseCommand(CommandPtr*);
+ Result ParseCommandList(Script*, CommandPtrVector*);
+ Result ParseCommand(Script*, CommandPtr*);
Result ParseAssertExhaustionCommand(CommandPtr*);
Result ParseAssertInvalidCommand(CommandPtr*);
Result ParseAssertMalformedCommand(CommandPtr*);
@@ -179,7 +181,7 @@ class WastParser {
Result ParseAssertTrapCommand(CommandPtr*);
Result ParseAssertUnlinkableCommand(CommandPtr*);
Result ParseActionCommand(CommandPtr*);
- Result ParseModuleCommand(CommandPtr*);
+ Result ParseModuleCommand(Script*, CommandPtr*);
Result ParseRegisterCommand(CommandPtr*);
Result ParseAction(ActionPtr*);
@@ -197,7 +199,6 @@ class WastParser {
void CheckImportOrdering(Module*);
WastLexer* lexer_;
- std::unique_ptr<Script> script_;
Index last_module_index_ = kInvalidIndex;
ErrorHandler* error_handler_;
int errors_ = 0;
@@ -206,10 +207,15 @@ class WastParser {
CircularArray<Token, 2> tokens_;
};
-Result ParseWast(WastLexer* lexer,
- std::unique_ptr<Script>* out_script,
- ErrorHandler*,
- WastParseOptions* options = nullptr);
+Result ParseWatModule(WastLexer* lexer,
+ std::unique_ptr<Module>* out_module,
+ ErrorHandler*,
+ WastParseOptions* options = nullptr);
+
+Result ParseWastScript(WastLexer* lexer,
+ std::unique_ptr<Script>* out_script,
+ ErrorHandler*,
+ WastParseOptions* options = nullptr);
} // namespace wabt
diff --git a/test/parse/bad-crlf.txt b/test/parse/bad-crlf.txt
index 207bfdce..ddf2676e 100644
--- a/test/parse/bad-crlf.txt
+++ b/test/parse/bad-crlf.txt
@@ -2,7 +2,7 @@
modulez
funcz
(;; STDERR ;;;
-out/test/parse/bad-crlf.txt:2:1: error: unexpected token "modulez", expected a module field or a command.
+out/test/parse/bad-crlf.txt:2:1: error: unexpected token "modulez", expected a module field or a module.
modulez
^^^^^^^
out/test/parse/bad-crlf.txt:3:1: error: unexpected token funcz, expected EOF.
diff --git a/test/parse/bad-error-long-line.txt b/test/parse/bad-error-long-line.txt
index 451ac6fd..2f699c4e 100644
--- a/test/parse/bad-error-long-line.txt
+++ b/test/parse/bad-error-long-line.txt
@@ -1,7 +1,7 @@
;;; ERROR: 1
whoops (; some text at the end of the line ;)
(;; STDERR ;;;
-out/test/parse/bad-error-long-line.txt:2:170: error: unexpected token "whoops", expected a module field or a command.
+out/test/parse/bad-error-long-line.txt:2:170: error: unexpected token "whoops", expected a module field or a module.
... whoops (; some text...
^^^^^^
;;; STDERR ;;)
diff --git a/test/parse/bad-error-long-token.txt b/test/parse/bad-error-long-token.txt
index 5236637d..ca5fbf0a 100644
--- a/test/parse/bad-error-long-token.txt
+++ b/test/parse/bad-error-long-token.txt
@@ -1,7 +1,7 @@
;;; ERROR: 1
abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz
(;; STDERR ;;;
-out/test/parse/bad-error-long-token.txt:2:15: error: unexpected token "abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz", expected a module field or a command.
+out/test/parse/bad-error-long-token.txt:2:15: error: unexpected token "abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz", expected a module field or a module.
abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijk...
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
;;; STDERR ;;)
diff --git a/test/parse/bad-single-semicolon.txt b/test/parse/bad-single-semicolon.txt
index 18ab20d8..fe67eea0 100644
--- a/test/parse/bad-single-semicolon.txt
+++ b/test/parse/bad-single-semicolon.txt
@@ -5,7 +5,7 @@
out/test/parse/bad-single-semicolon.txt:2:1: error: unexpected char
; foo bar
^
-out/test/parse/bad-single-semicolon.txt:2:3: error: unexpected token "foo", expected a module field or a command.
+out/test/parse/bad-single-semicolon.txt:2:3: error: unexpected token "foo", expected a module field or a module.
; foo bar
^^^
out/test/parse/bad-single-semicolon.txt:2:7: error: unexpected token bar, expected EOF.
diff --git a/test/parse/bad-toplevel.txt b/test/parse/bad-toplevel.txt
index 9459b88e..ebf78714 100644
--- a/test/parse/bad-toplevel.txt
+++ b/test/parse/bad-toplevel.txt
@@ -1,7 +1,7 @@
;;; ERROR: 1
(foo bar)
(;; STDERR ;;;
-out/test/parse/bad-toplevel.txt:2:2: error: unexpected token "foo", expected a module field or a command.
+out/test/parse/bad-toplevel.txt:2:2: error: unexpected token "foo", expected a module field or a module.
(foo bar)
^^^
out/test/parse/bad-toplevel.txt:2:6: error: unexpected token bar, expected EOF.
diff --git a/test/parse/empty-file.txt b/test/parse/empty-file.txt
index 0d021226..bdd75938 100644
--- a/test/parse/empty-file.txt
+++ b/test/parse/empty-file.txt
@@ -1,5 +1,5 @@
;;; ERROR: 1
;; empty file
(;; STDERR ;;;
-out/test/parse/empty-file.txt:3:2: error: unexpected token "EOF", expected a module field or a command.
+out/test/parse/empty-file.txt:3:2: error: unexpected token "EOF", expected a module field or a module.
;;; STDERR ;;)
diff --git a/test/parse/module/bad-module-multi.txt b/test/parse/module/bad-module-multi.txt
new file mode 100644
index 00000000..10d8102a
--- /dev/null
+++ b/test/parse/module/bad-module-multi.txt
@@ -0,0 +1,10 @@
+;;; ERROR: 1
+(module (func))
+
+;; Can't have two modules in a .wat file.
+(module)
+(;; STDERR ;;;
+out/test/parse/module/bad-module-multi.txt:5:1: error: unexpected token (, expected EOF.
+(module)
+^
+;;; STDERR ;;)
diff --git a/test/parse/module/bad-module-with-assert.txt b/test/parse/module/bad-module-with-assert.txt
new file mode 100644
index 00000000..5145f611
--- /dev/null
+++ b/test/parse/module/bad-module-with-assert.txt
@@ -0,0 +1,10 @@
+;;; ERROR: 1
+(module (func (export "f")))
+
+;; Can't use assert_return when parsing a .wat file.
+(assert_return (invoke "f"))
+(;; STDERR ;;;
+out/test/parse/module/bad-module-with-assert.txt:5:1: error: unexpected token (, expected EOF.
+(assert_return (invoke "f"))
+^
+;;; STDERR ;;)