From 93d627e791d5d5e4aba7d3cabf7e75403403168e Mon Sep 17 00:00:00 2001 From: Gorog Peter Date: Mon, 26 Jun 2023 09:09:54 +0200 Subject: [PATCH] Print error message - print lexer initialisation error - print syntax error - print semantic error - print assert fail - print unequal call parameter size in assert error - print not-defined function call in asser error Fixed 2 typo (replace uint16_t with Walrus::ByteCodeStackOffset). I also fixed another typo. Because of it 3 tests failed (binary.wast, binary-leb128.wast, elem.wast), although it didn't throw assert failed. --- src/parser/WASMParser.cpp | 4 ++-- src/runtime/Module.cpp | 2 +- src/runtime/Value.h | 22 ++++++++++++++++++++ src/shell/Shell.cpp | 42 ++++++++++++++++++++++++++++++--------- 4 files changed, 58 insertions(+), 12 deletions(-) diff --git a/src/parser/WASMParser.cpp b/src/parser/WASMParser.cpp index 1971d9591..27df585b9 100644 --- a/src/parser/WASMParser.cpp +++ b/src/parser/WASMParser.cpp @@ -1297,7 +1297,7 @@ class WASMBinaryReader : public wabt::WASMBinaryReaderDelegate { ASSERT(peekVMStackSize() == Walrus::valueSizeInStack(toValueKind(Type::I32))); auto stackPos = popVMStack(); size_t pos = m_currentFunction->currentByteCodeSize(); - pushByteCode(Walrus::JumpIfFalse(stackPos, sizeof(Walrus::JumpIfFalse) + sizeof(Walrus::End) + sizeof(uint16_t) * m_currentFunctionType->result().size()), WASMOpcode::BrIfOpcode); + pushByteCode(Walrus::JumpIfFalse(stackPos, sizeof(Walrus::JumpIfFalse) + sizeof(Walrus::End) + sizeof(Walrus::ByteCodeStackOffset) * m_currentFunctionType->result().size()), WASMOpcode::BrIfOpcode); for (size_t i = 0; i < m_currentFunctionType->result().size(); i++) { ASSERT((m_vmStack.rbegin() + i)->m_size == Walrus::valueSizeInStack(m_currentFunctionType->result()[m_currentFunctionType->result().size() - i - 1])); } @@ -1414,7 +1414,7 @@ class WASMBinaryReader : public wabt::WASMBinaryReaderDelegate { if (tagIndex != std::numeric_limits::max()) { auto functionType = m_result.m_functionTypes[m_result.m_tagTypes[tagIndex]->sigIndex()]; auto& param = functionType->param(); - m_currentFunction->expandByteCode(sizeof(uint16_t) * param.size()); + m_currentFunction->expandByteCode(sizeof(Walrus::ByteCodeStackOffset) * param.size()); Walrus::Throw* code = m_currentFunction->peekByteCode(pos); for (size_t i = 0; i < param.size(); i++) { code->dataOffsets()[param.size() - i - 1] = (m_vmStack.rbegin() + i)->m_position; diff --git a/src/runtime/Module.cpp b/src/runtime/Module.cpp index e33b0601f..361921469 100644 --- a/src/runtime/Module.cpp +++ b/src/runtime/Module.cpp @@ -282,7 +282,7 @@ Instance* Module::instantiate(ExecutionState& state, const ExternVector& imports &data); } - if (UNLIKELY(elem->tableIndex() >= numberOfTableTypes() || index >= instance->m_tables[elem->tableIndex()]->size() || index + elem->functionIndex().size() > instance->m_tables[elem->tableIndex()]->size())) { + if (UNLIKELY(elem->tableIndex() >= numberOfTableTypes() || index > instance->m_tables[elem->tableIndex()]->size() || index + elem->functionIndex().size() > instance->m_tables[elem->tableIndex()]->size())) { Trap::throwException(state, "out of bounds table access"); } diff --git a/src/runtime/Value.h b/src/runtime/Value.h index e7587b539..0f7e4d0a3 100644 --- a/src/runtime/Value.h +++ b/src/runtime/Value.h @@ -17,6 +17,8 @@ #ifndef __WalrusValue__ #define __WalrusValue__ +#include +#include #include "util/Vector.h" #include "runtime/ExecutionState.h" #include "runtime/Exception.h" @@ -308,6 +310,26 @@ class Value { return false; } + operator std::string() const + { + switch (m_type) { + case I32: + return std::to_string(asI32()); + case I64: + return std::to_string(asI64()); + case F32: + return std::to_string(asF32()); + case F64: + return std::to_string(asF64()); + case FuncRef: + case ExternRef: + return std::to_string((size_t)(asExternal())); + default: + ASSERT_NOT_REACHED(); + break; + } + } + private: union { int32_t m_i32; diff --git a/src/shell/Shell.cpp b/src/shell/Shell.cpp index 743412685..b04f48cf8 100644 --- a/src/shell/Shell.cpp +++ b/src/shell/Shell.cpp @@ -550,7 +550,10 @@ static void printConstVector(wabt::ConstVector& v) static void executeInvokeAction(wabt::InvokeAction* action, Walrus::Function* fn, wabt::ConstVector expectedResult, const char* expectedException, bool expectUserException = false) { - RELEASE_ASSERT(fn->functionType()->param().size() == action->args.size()); + if (fn->functionType()->param().size() != action->args.size()) { + fprintf(stderr, "Error: expected %zu parameter(s) but got %zu.\n", fn->functionType()->param().size(), action->args.size()); + abort(); + } Walrus::ValueVector args; for (auto& a : action->args) { args.push_back(toWalrusValue(a)); @@ -560,7 +563,8 @@ static void executeInvokeAction(wabt::InvokeAction* action, Walrus::Function* fn Walrus::Function* fn; wabt::ConstVector& expectedResult; Walrus::ValueVector& args; - } data = { fn, expectedResult, args }; + wabt::InvokeAction* action; + } data = { fn, expectedResult, args, action }; Walrus::Trap trap; auto trapResult = trap.run([](Walrus::ExecutionState& state, void* d) { RunData* data = reinterpret_cast(d); @@ -571,7 +575,15 @@ static void executeInvokeAction(wabt::InvokeAction* action, Walrus::Function* fn RELEASE_ASSERT(data->fn->functionType()->result().size() == data->expectedResult.size()); // compare result for (size_t i = 0; i < result.size(); i++) { - RELEASE_ASSERT(equals(result[i], data->expectedResult[i])); + if (!equals(result[i], data->expectedResult[i])) { + printf("Assert FAILED (line: %d) ", data->action->loc.line); + printf("%s(", data->action->name.data()); + printConstVector(data->action->args); + printf(") expected "); + printConstVector(data->expectedResult); + printf(", but got %s\n", ((std::string)result[i]).c_str()); + abort(); + } } } }, @@ -625,8 +637,8 @@ static void executeWAST(Store* store, const std::string& filename, const std::ve { auto lexer = wabt::WastLexer::CreateBufferLexer("test.wabt", src.data(), src.size()); if (!lexer) { - RELEASE_ASSERT_NOT_REACHED(); - return; + fprintf(stderr, "Error at lexer initialization!\n"); + abort(); } wabt::Errors errors; @@ -636,8 +648,11 @@ static void executeWAST(Store* store, const std::string& filename, const std::ve wabt::WastParseOptions parse_wast_options(features); auto result = wabt::ParseWastScript(lexer.get(), &script, &errors, &parse_wast_options); if (!wabt::Succeeded(result)) { - RELEASE_ASSERT_NOT_REACHED(); - return; + fprintf(stderr, "Syntax error(s):\n"); + for (auto e : errors) + fprintf(stderr, " %s\n", e.message.c_str()); + fprintf(stderr, "\n"); + abort(); } std::map instanceMap; @@ -649,7 +664,13 @@ static void executeWAST(Store* store, const std::string& filename, const std::ve case wabt::CommandType::ScriptModule: { auto* moduleCommand = static_cast(command.get()); auto buf = readModuleData(&moduleCommand->module); - executeWASM(store, filename, buf->data, functionTypes, ®isteredInstanceMap); + auto trapResult = executeWASM(store, filename, buf->data, functionTypes, ®isteredInstanceMap); + if (trapResult.exception) { + std::string& errorMessage = trapResult.exception->message(); + fprintf(stderr, "Error: %s\n", errorMessage.c_str()); + abort(); + } + instanceMap[commandCount] = store->getLastInstance(); if (moduleCommand->module.name.size()) { registeredInstanceMap[moduleCommand->module.name] = store->getLastInstance(); @@ -659,7 +680,10 @@ static void executeWAST(Store* store, const std::string& filename, const std::ve case wabt::CommandType::AssertReturn: { auto* assertReturn = static_cast(command.get()); auto value = fetchInstance(assertReturn->action->module_var, instanceMap, registeredInstanceMap)->resolveExportType(assertReturn->action->name); - RELEASE_ASSERT(value); + if (!value) { + fprintf(stderr, "Undefined function: %s\n", assertReturn->action->name.c_str()); + abort(); + } if (assertReturn->action->type() == wabt::ActionType::Invoke) { auto action = static_cast(assertReturn->action.get()); auto fn = fetchInstance(action->module_var, instanceMap, registeredInstanceMap)->resolveExportFunction(action->name);