diff options
Diffstat (limited to 'src/binary-reader.cc')
-rw-r--r-- | src/binary-reader.cc | 126 |
1 files changed, 118 insertions, 8 deletions
diff --git a/src/binary-reader.cc b/src/binary-reader.cc index beb807ff..1c162210 100644 --- a/src/binary-reader.cc +++ b/src/binary-reader.cc @@ -48,6 +48,12 @@ } \ } while (0) +#define ERROR_UNLESS_FUTURE_EXCEPTIONS_OPCODE(opcode) \ + do { \ + if (!options_->allow_future_exceptions) \ + return ReportUnexpectedOpcode(opcode); \ + } while (0) + #define CALLBACK0(member) \ ERROR_UNLESS(Succeeded(delegate_->member()), #member \ " callback failed") @@ -180,6 +186,7 @@ class BinaryReader { Limits* out_elem_limits) WABT_WARN_UNUSED; Result ReadMemory(Limits* out_page_limits) WABT_WARN_UNUSED; Result ReadGlobalHeader(Type* out_type, bool* out_mutable) WABT_WARN_UNUSED; + Result ReadExceptionType(TypeVector& sig) WABT_WARN_UNUSED; Result ReadFunctionBody(Offset end_offset) WABT_WARN_UNUSED; Result ReadNamesSection(Offset section_size) WABT_WARN_UNUSED; Result ReadRelocSection(Offset section_size) WABT_WARN_UNUSED; @@ -196,7 +203,9 @@ class BinaryReader { Result ReadElemSection(Offset section_size) WABT_WARN_UNUSED; Result ReadCodeSection(Offset section_size) WABT_WARN_UNUSED; Result ReadDataSection(Offset section_size) WABT_WARN_UNUSED; + Result ReadExceptionSection(Offset section_size) WABT_WARN_UNUSED; Result ReadSections() WABT_WARN_UNUSED; + Result ReportUnexpectedOpcode(Opcode opcode, const char* message = nullptr); size_t read_end_ = 0; /* Either the section end or data_size. */ BinaryReaderDelegate::State state_; @@ -212,12 +221,14 @@ class BinaryReader { Index num_table_imports_ = 0; Index num_memory_imports_ = 0; Index num_global_imports_ = 0; + Index num_exception_imports_ = 0; Index num_function_signatures_ = 0; Index num_tables_ = 0; Index num_memories_ = 0; Index num_globals_ = 0; Index num_exports_ = 0; Index num_function_bodies_ = 0; + Index num_exceptions_ = 0; }; BinaryReader::BinaryReader(const void* data, @@ -253,6 +264,16 @@ void WABT_PRINTF_FORMAT(2, 3) BinaryReader::PrintError(const char* format, state_.offset += sizeof(type); \ return Result::Ok +Result BinaryReader::ReportUnexpectedOpcode(Opcode opcode, + const char* message) { + const char* maybe_space = " "; + if (!message) + message = maybe_space = ""; + PrintError("unexpected opcode%s%s: %d (0x%x)", + maybe_space, message, opcode.GetCode(), opcode.GetCode()); + return Result::Error; +} + Result BinaryReader::ReadOpcode(Opcode* out_value, const char* desc) { uint8_t value = 0; if (Failed(ReadU8(&value, desc))) { @@ -508,9 +529,7 @@ Result BinaryReader::ReadInitExpr(Index index) { return Result::Ok; default: - PrintError("unexpected opcode in initializer expression: %d (0x%x)", - opcode.GetCode(), opcode.GetCode()); - return Result::Error; + return ReportUnexpectedOpcode(opcode, "in initializer expression"); } CHECK_RESULT(ReadOpcode(&opcode, "opcode")); @@ -989,10 +1008,54 @@ Result BinaryReader::ReadFunctionBody(Offset end_offset) { CALLBACK0(OnOpcodeBare); break; + case Opcode::Try: { + ERROR_UNLESS_FUTURE_EXCEPTIONS_OPCODE(opcode); + Type sig_type; + CHECK_RESULT(ReadType(&sig_type, "try signature type")); + ERROR_UNLESS(is_inline_sig_type(sig_type), + "expected valid block signature type"); + Index num_types = sig_type == Type::Void ? 0 : 1; + CALLBACK(OnTryExpr, num_types, &sig_type); + CALLBACK(OnOpcodeBlockSig, num_types, &sig_type); + break; + } + + case Opcode::Catch: { + ERROR_UNLESS_FUTURE_EXCEPTIONS_OPCODE(opcode); + Index index; + CHECK_RESULT(ReadIndex(&index, "exception index")); + CALLBACK(OnCatchExpr, index); + CALLBACK(OnOpcodeIndex, index); + break; + } + + case Opcode::CatchAll: { + ERROR_UNLESS_FUTURE_EXCEPTIONS_OPCODE(opcode); + CALLBACK(OnCatchAllExpr); + CALLBACK0(OnOpcodeBare); + break; + } + + case Opcode::Rethrow: { + ERROR_UNLESS_FUTURE_EXCEPTIONS_OPCODE(opcode); + Index depth; + CHECK_RESULT(ReadIndex(&depth, "catch depth")); + CALLBACK(OnRethrowExpr, depth); + CALLBACK(OnOpcodeIndex, depth); + break; + } + + case Opcode::Throw: { + ERROR_UNLESS_FUTURE_EXCEPTIONS_OPCODE(opcode); + Index index; + CHECK_RESULT(ReadIndex(&index, "exception index")); + CALLBACK(OnThrowExpr, index); + CALLBACK(OnOpcodeIndex, index); + break; + } + default: - PrintError("unexpected opcode: %d (0x%x)", static_cast<int>(opcode), - static_cast<unsigned>(opcode)); - return Result::Error; + return ReportUnexpectedOpcode(opcode); } } ERROR_UNLESS(state_.offset == end_offset, @@ -1185,6 +1248,36 @@ Result BinaryReader::ReadLinkingSection(Offset section_size) { return Result::Ok; } +Result BinaryReader::ReadExceptionType(TypeVector& sig) { + Index num_values; + CHECK_RESULT(ReadIndex(&num_values, "exception type count")); + sig.resize(num_values); + for (Index j = 0; j < num_values; ++j) { + Type value_type; + CHECK_RESULT(ReadType(&value_type, "exception value type")); + ERROR_UNLESS(is_concrete_type(value_type), + "excepted valid exception value type (got %d)", + static_cast<int>(value_type)); + sig[j] = value_type; + } + return Result::Ok; +} + +Result BinaryReader::ReadExceptionSection(Offset section_size) { + CALLBACK(BeginExceptionSection, section_size); + CHECK_RESULT(ReadIndex(&num_exceptions_, "exception count")); + CALLBACK(OnExceptionCount, num_exceptions_); + + for (Index i = 0; i < num_exceptions_; ++i) { + TypeVector sig; + CHECK_RESULT(ReadExceptionType(sig)); + CALLBACK(OnExceptionType, i, sig); + } + + CALLBACK(EndExceptionSection); + return Result::Ok; +} + Result BinaryReader::ReadCustomSection(Offset section_size) { StringSlice section_name; CHECK_RESULT(ReadStr(§ion_name, "section name")); @@ -1201,6 +1294,10 @@ Result BinaryReader::ReadCustomSection(Offset section_size) { } else if (strncmp(section_name.start, WABT_BINARY_SECTION_LINKING, strlen(WABT_BINARY_SECTION_LINKING)) == 0) { CHECK_RESULT(ReadLinkingSection(section_size)); + } else if (options_->allow_future_exceptions && + strncmp(section_name.start, WABT_BINARY_SECTION_EXCEPTION, + strlen(WABT_BINARY_SECTION_EXCEPTION)) == 0) { + CHECK_RESULT(ReadExceptionSection(section_size)); } else { /* This is an unknown custom section, skip it. */ state_.offset = read_end_; @@ -1311,6 +1408,18 @@ Result BinaryReader::ReadImportSection(Offset section_size) { break; } + case ExternalKind::Except: { + if (!options_->allow_future_exceptions) + PrintError("invalid import exception kind: exceptions not allowed"); + TypeVector sig; + CHECK_RESULT(ReadExceptionType(sig)); + CALLBACK(OnImport, i, module_name, field_name); + CALLBACK(OnImportException, i, module_name, field_name, + num_exception_imports_, sig); + num_exception_imports_++; + break; + } + default: PrintError("invalid import kind: %d", kind); return Result::Error; @@ -1421,8 +1530,9 @@ Result BinaryReader::ReadExportSection(Offset section_size) { "invalid export global index: %" PRIindex, item_index); break; case ExternalKind::Except: - // TODO(karlschimpf) Define. - WABT_FATAL("read export except not implemented"); + // Note: Can't check if index valid, exceptions section comes later. + if (!options_->allow_future_exceptions) + PrintError("invalid export exception kind: exceptions not allowed"); break; } |