From aa8c0287025a112dbb0a73328dbee8aa09d75a15 Mon Sep 17 00:00:00 2001 From: SoniEx2 Date: Mon, 17 Feb 2025 10:33:14 -0300 Subject: [PATCH] Make ReadBinaryOptions more strict across readers --- include/wabt/binary-reader-ir.h | 23 +++++- include/wabt/binary-reader-objdump.h | 2 +- include/wabt/binary-reader-options.h | 39 ++++++++++ include/wabt/binary-reader-stats.h | 17 ++++- include/wabt/binary-reader.h | 24 +----- include/wabt/interp/binary-reader-interp.h | 17 ++++- src/binary-reader-ir.cc | 2 +- src/binary-reader-objdump.cc | 27 +++++-- src/binary-reader-stats.cc | 2 +- src/binary-reader.cc | 86 +++++++++++----------- src/emscripten-helpers.cc | 2 +- src/interp/binary-reader-interp.cc | 2 +- src/interp/interp-wasm-c-api.cc | 8 +- src/test-binary-reader.cc | 9 ++- src/test-interp.cc | 2 +- src/tools/spectest-interp.cc | 20 ++--- src/tools/wasm-decompile.cc | 6 +- src/tools/wasm-interp.cc | 6 +- src/tools/wasm-stats.cc | 2 +- src/tools/wasm-strip.cc | 19 +++-- src/tools/wasm-validate.cc | 7 +- src/tools/wasm2c.cc | 7 +- src/tools/wasm2wat-fuzz.cc | 2 +- src/tools/wasm2wat.cc | 7 +- src/wast-parser.cc | 2 +- 25 files changed, 202 insertions(+), 138 deletions(-) create mode 100644 include/wabt/binary-reader-options.h diff --git a/include/wabt/binary-reader-ir.h b/include/wabt/binary-reader-ir.h index 4de0ee7099..d59c76e556 100644 --- a/include/wabt/binary-reader-ir.h +++ b/include/wabt/binary-reader-ir.h @@ -17,18 +17,37 @@ #ifndef WABT_BINARY_READER_IR_H_ #define WABT_BINARY_READER_IR_H_ +#include "wabt/binary-reader-options.h" #include "wabt/common.h" #include "wabt/error.h" +#include "wabt/feature.h" namespace wabt { struct Module; -struct ReadBinaryOptions; + +class ReadBinaryIrOptions : public ReadBinaryOptions { + public: + ReadBinaryIrOptions() = default; + ReadBinaryIrOptions(const Features& features, Stream* log_stream) + : features(features), log_stream(log_stream) {} + Features features; + Stream* log_stream = nullptr; + bool read_debug_names = false; + bool fail_on_custom_section_error = true; + + const Features& GetFeatures() const override { return features; } + Stream* GetLogStream() const override { return log_stream; } + bool ReadDebugNames() const override { return read_debug_names; } + bool FailOnCustomSectionError() const override { + return fail_on_custom_section_error; + } +}; Result ReadBinaryIr(const char* filename, const void* data, size_t size, - const ReadBinaryOptions& options, + const ReadBinaryIrOptions& options, Errors*, Module* out_module); diff --git a/include/wabt/binary-reader-objdump.h b/include/wabt/binary-reader-objdump.h index a23a08d9f1..5a48e8a5db 100644 --- a/include/wabt/binary-reader-objdump.h +++ b/include/wabt/binary-reader-objdump.h @@ -20,6 +20,7 @@ #include #include +#include "wabt/binary-reader-options.h" #include "wabt/common.h" #include "wabt/feature.h" #include "wabt/stream.h" @@ -27,7 +28,6 @@ namespace wabt { struct Module; -struct ReadBinaryOptions; enum class ObjdumpMode { Prepass, diff --git a/include/wabt/binary-reader-options.h b/include/wabt/binary-reader-options.h new file mode 100644 index 0000000000..18d51501b2 --- /dev/null +++ b/include/wabt/binary-reader-options.h @@ -0,0 +1,39 @@ +/* + * Copyright 2025 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. + */ + +#ifndef WABT_BINARY_READER_OPTIONS_H_ +#define WABT_BINARY_READER_OPTIONS_H_ + +namespace wabt { + +class Features; +class Stream; + +class ReadBinaryOptions { + public: + virtual ~ReadBinaryOptions() {} + + virtual const Features& GetFeatures() const = 0; + virtual Stream* GetLogStream() const = 0; + virtual bool ReadDebugNames() const { return false; } + virtual bool StopOnFirstError() const { return true; } + virtual bool FailOnCustomSectionError() const { return true; } + virtual bool SkipFunctionBodies() const { return false; } +}; + +} // namespace wabt + +#endif /* WABT_BINARY_READER_OPTIONS_H_ */ diff --git a/include/wabt/binary-reader-stats.h b/include/wabt/binary-reader-stats.h index 8c3a9aba8d..489aadb36b 100644 --- a/include/wabt/binary-reader-stats.h +++ b/include/wabt/binary-reader-stats.h @@ -20,15 +20,28 @@ #include #include +#include "wabt/binary-reader-options.h" #include "wabt/common.h" +#include "wabt/feature.h" #include "wabt/opcode.h" namespace wabt { struct Module; -struct ReadBinaryOptions; class Stream; +class ReadBinaryStatsOptions : public ReadBinaryOptions { + public: + ReadBinaryStatsOptions() = default; + ReadBinaryStatsOptions(const Features& features, Stream* log_stream) + : features(features), log_stream(log_stream) {} + Features features; + Stream* log_stream = nullptr; + + const Features& GetFeatures() const override { return features; } + Stream* GetLogStream() const override { return log_stream; } +}; + class OpcodeInfo { public: enum class Kind { @@ -88,7 +101,7 @@ using OpcodeInfoCounts = std::map; Result ReadBinaryOpcnt(const void* data, size_t size, - const ReadBinaryOptions& options, + const ReadBinaryStatsOptions& options, OpcodeInfoCounts* opcode_counts); } // namespace wabt diff --git a/include/wabt/binary-reader.h b/include/wabt/binary-reader.h index 94b19c1100..71708298ac 100644 --- a/include/wabt/binary-reader.h +++ b/include/wabt/binary-reader.h @@ -21,6 +21,7 @@ #include #include +#include "wabt/binary-reader-options.h" #include "wabt/binary.h" #include "wabt/common.h" #include "wabt/error.h" @@ -29,29 +30,6 @@ namespace wabt { -class Stream; - -struct ReadBinaryOptions { - ReadBinaryOptions() = default; - ReadBinaryOptions(const Features& features, - Stream* log_stream, - bool read_debug_names, - bool stop_on_first_error, - bool fail_on_custom_section_error) - : features(features), - log_stream(log_stream), - read_debug_names(read_debug_names), - stop_on_first_error(stop_on_first_error), - fail_on_custom_section_error(fail_on_custom_section_error) {} - - Features features; - Stream* log_stream = nullptr; - bool read_debug_names = false; - bool stop_on_first_error = true; - bool fail_on_custom_section_error = true; - bool skip_function_bodies = false; -}; - // TODO: Move somewhere else? struct TypeMut { Type type; diff --git a/include/wabt/interp/binary-reader-interp.h b/include/wabt/interp/binary-reader-interp.h index 74d8e15f22..da9ade907a 100644 --- a/include/wabt/interp/binary-reader-interp.h +++ b/include/wabt/interp/binary-reader-interp.h @@ -17,20 +17,33 @@ #ifndef WABT_BINARY_READER_INTERP_H_ #define WABT_BINARY_READER_INTERP_H_ +#include "wabt/binary-reader-options.h" #include "wabt/common.h" #include "wabt/error.h" +#include "wabt/feature.h" #include "wabt/interp/interp.h" namespace wabt { -struct ReadBinaryOptions; +class ReadBinaryInterpOptions : public ReadBinaryOptions { + public: + ReadBinaryInterpOptions() = default; + ReadBinaryInterpOptions(const Features& features, Stream* log_stream) + : features(features), log_stream(log_stream) {} + Features features; + Stream* log_stream = nullptr; + + const Features& GetFeatures() const override { return features; } + Stream* GetLogStream() const override { return log_stream; } + bool ReadDebugNames() const override { return true; } +}; namespace interp { Result ReadBinaryInterp(std::string_view filename, const void* data, size_t size, - const ReadBinaryOptions& options, + const ReadBinaryInterpOptions& options, Errors*, ModuleDesc* out_module); diff --git a/src/binary-reader-ir.cc b/src/binary-reader-ir.cc index 2029b0f7c4..7f1372d0bc 100644 --- a/src/binary-reader-ir.cc +++ b/src/binary-reader-ir.cc @@ -1850,7 +1850,7 @@ Result BinaryReaderIR::OnGenericCustomSection(std::string_view name, Result ReadBinaryIr(const char* filename, const void* data, size_t size, - const ReadBinaryOptions& options, + const ReadBinaryIrOptions& options, Errors* errors, Module* out_module) { BinaryReaderIR reader(out_module, filename, errors); diff --git a/src/binary-reader-objdump.cc b/src/binary-reader-objdump.cc index 80850541b2..7fd9f708ca 100644 --- a/src/binary-reader-objdump.cc +++ b/src/binary-reader-objdump.cc @@ -2493,13 +2493,26 @@ Result ReadBinaryObjdump(const uint8_t* data, size_t size, ObjdumpOptions* options, ObjdumpState* state) { - Features features; - features.EnableAll(); - const bool kReadDebugNames = true; - const bool kStopOnFirstError = false; - const bool kFailOnCustomSectionError = false; - ReadBinaryOptions read_options(features, options->log_stream, kReadDebugNames, - kStopOnFirstError, kFailOnCustomSectionError); + class ReadBinaryObjdumpOptions : public ReadBinaryOptions { + Features features; + Stream* log_stream; + + public: + explicit ReadBinaryObjdumpOptions(Stream* log_stream) + : log_stream(log_stream) { + features.EnableAll(); + } + bool skip_function_bodies = false; + + const Features& GetFeatures() const override { return features; } + Stream* GetLogStream() const override { return log_stream; } + bool ReadDebugNames() const override { return true; } + bool StopOnFirstError() const override { return false; } + bool FailOnCustomSectionError() const override { return false; } + bool SkipFunctionBodies() const override { return skip_function_bodies; } + }; + + ReadBinaryObjdumpOptions read_options(options->log_stream); switch (options->mode) { case ObjdumpMode::Prepass: { diff --git a/src/binary-reader-stats.cc b/src/binary-reader-stats.cc index df0c438fda..c60808be9b 100644 --- a/src/binary-reader-stats.cc +++ b/src/binary-reader-stats.cc @@ -305,7 +305,7 @@ Result BinaryReaderOpcnt::OnEndExpr() { Result ReadBinaryOpcnt(const void* data, size_t size, - const ReadBinaryOptions& options, + const ReadBinaryStatsOptions& options, OpcodeInfoCounts* counts) { BinaryReaderOpcnt reader(counts); return ReadBinary(data, size, &reader, options); diff --git a/src/binary-reader.cc b/src/binary-reader.cc index e1859a1c31..645f47318e 100644 --- a/src/binary-reader.cc +++ b/src/binary-reader.cc @@ -52,11 +52,11 @@ #define ERROR_UNLESS(expr, ...) ERROR_IF(!(expr), __VA_ARGS__) -#define ERROR_UNLESS_OPCODE_ENABLED(opcode) \ - do { \ - if (!opcode.IsEnabled(options_.features)) { \ - return ReportUnexpectedOpcode(opcode); \ - } \ +#define ERROR_UNLESS_OPCODE_ENABLED(opcode) \ + do { \ + if (!opcode.IsEnabled(options_.GetFeatures())) { \ + return ReportUnexpectedOpcode(opcode); \ + } \ } while (0) #define CALLBACK0(member) \ @@ -223,8 +223,8 @@ BinaryReader::BinaryReader(const void* data, const ReadBinaryOptions& options) : read_end_(size), state_(static_cast(data), size), - logging_delegate_(options.log_stream, delegate), - delegate_(options.log_stream ? &logging_delegate_ : delegate), + logging_delegate_(options.GetLogStream(), delegate), + delegate_(options.GetLogStream() ? &logging_delegate_ : delegate), options_(options), last_known_section_(BinarySection::Invalid) { delegate->OnSetState(&state_); @@ -233,7 +233,7 @@ BinaryReader::BinaryReader(const void* data, void WABT_PRINTF_FORMAT(2, 3) BinaryReader::PrintError(const char* format, ...) { ErrorLevel error_level = - reading_custom_section_ && !options_.fail_on_custom_section_error + reading_custom_section_ && !options_.FailOnCustomSectionError() ? ErrorLevel::Warning : ErrorLevel::Error; @@ -486,7 +486,7 @@ Result BinaryReader::ReadMemLocation(Address* alignment_log2, CHECK_RESULT(CheckAlignment(alignment_log2, desc_align)); *memidx = 0; if (has_memidx) { - ERROR_IF(!options_.features.multi_memory_enabled(), + ERROR_IF(!options_.GetFeatures().multi_memory_enabled(), "multi_memory not allowed"); CHECK_RESULT(ReadMemidx(memidx, desc_memidx)); } @@ -563,17 +563,17 @@ bool BinaryReader::IsConcreteType(Type type) { return true; case Type::V128: - return options_.features.simd_enabled(); + return options_.GetFeatures().simd_enabled(); case Type::FuncRef: case Type::ExternRef: - return options_.features.reference_types_enabled(); + return options_.GetFeatures().reference_types_enabled(); case Type::ExnRef: - return options_.features.exceptions_enabled(); + return options_.GetFeatures().exceptions_enabled(); case Type::Reference: - return options_.features.function_references_enabled(); + return options_.GetFeatures().function_references_enabled(); default: return false; @@ -585,7 +585,7 @@ bool BinaryReader::IsBlockType(Type type) { return true; } - if (!(options_.features.multi_value_enabled() && type.IsIndex())) { + if (!(options_.GetFeatures().multi_value_enabled() && type.IsIndex())) { return false; } @@ -614,7 +614,7 @@ Result BinaryReader::ReadTable(Type* out_elem_type, Limits* out_elem_limits) { bool is_64 = flags & WABT_BINARY_LIMITS_IS_64_FLAG; const uint8_t unknown_flags = flags & ~WABT_BINARY_LIMITS_ALL_TABLE_FLAGS; ERROR_IF(is_shared, "tables may not be shared"); - ERROR_IF(is_64 && !options_.features.memory64_enabled(), + ERROR_IF(is_64 && !options_.GetFeatures().memory64_enabled(), "memory64 not allowed"); ERROR_UNLESS(unknown_flags == 0, "malformed table limits flag: %d", flags); CHECK_RESULT(ReadU32Leb128(&initial, "table initial elem count")); @@ -642,14 +642,14 @@ Result BinaryReader::ReadMemory(Limits* out_page_limits, flags & WABT_BINARY_LIMITS_HAS_CUSTOM_PAGE_SIZE_FLAG; const uint8_t unknown_flags = flags & ~WABT_BINARY_LIMITS_ALL_MEMORY_FLAGS; ERROR_UNLESS(unknown_flags == 0, "malformed memory limits flag: %d", flags); - ERROR_IF(is_shared && !options_.features.threads_enabled(), + ERROR_IF(is_shared && !options_.GetFeatures().threads_enabled(), "memory may not be shared: threads not allowed"); - ERROR_IF(is_64 && !options_.features.memory64_enabled(), + ERROR_IF(is_64 && !options_.GetFeatures().memory64_enabled(), "memory64 not allowed"); - ERROR_IF( - has_custom_page_size && !options_.features.custom_page_sizes_enabled(), - "custom page sizes not allowed"); - if (options_.features.memory64_enabled()) { + ERROR_IF(has_custom_page_size && + !options_.GetFeatures().custom_page_sizes_enabled(), + "custom page sizes not allowed"); + if (options_.GetFeatures().memory64_enabled()) { CHECK_RESULT(ReadU64Leb128(&initial, "memory initial page count")); if (has_max) { CHECK_RESULT(ReadU64Leb128(&max, "memory max page count")); @@ -700,7 +700,7 @@ Result BinaryReader::ReadGlobalHeader(Type* out_type, bool* out_mutable) { Result BinaryReader::ReadAddress(Address* out_value, Index memory, const char* desc) { - if (options_.features.memory64_enabled()) { + if (options_.GetFeatures().memory64_enabled()) { return ReadU64Leb128(out_value, desc); } else { uint32_t val; @@ -947,7 +947,7 @@ Result BinaryReader::ReadInstructions(Offset end_offset, const char* context) { Index sig_index; CHECK_RESULT(ReadIndex(&sig_index, "call_indirect signature index")); Index table_index = 0; - if (options_.features.reference_types_enabled()) { + if (options_.GetFeatures().reference_types_enabled()) { CHECK_RESULT(ReadIndex(&table_index, "call_indirect table index")); } else { uint8_t reserved; @@ -971,7 +971,7 @@ Result BinaryReader::ReadInstructions(Offset end_offset, const char* context) { Index sig_index; CHECK_RESULT(ReadIndex(&sig_index, "return_call_indirect")); Index table_index = 0; - if (options_.features.reference_types_enabled()) { + if (options_.GetFeatures().reference_types_enabled()) { CHECK_RESULT( ReadIndex(&table_index, "return_call_indirect table index")); } else { @@ -1048,7 +1048,7 @@ Result BinaryReader::ReadInstructions(Offset end_offset, const char* context) { case Opcode::MemorySize: { Index memidx = 0; - if (!options_.features.multi_memory_enabled()) { + if (!options_.GetFeatures().multi_memory_enabled()) { uint8_t reserved; CHECK_RESULT(ReadU8(&reserved, "memory.size reserved")); ERROR_UNLESS(reserved == 0, "memory.size reserved value must be 0"); @@ -1062,7 +1062,7 @@ Result BinaryReader::ReadInstructions(Offset end_offset, const char* context) { case Opcode::MemoryGrow: { Index memidx = 0; - if (!options_.features.multi_memory_enabled()) { + if (!options_.GetFeatures().multi_memory_enabled()) { uint8_t reserved; CHECK_RESULT(ReadU8(&reserved, "memory.grow reserved")); ERROR_UNLESS(reserved == 0, "memory.grow reserved value must be 0"); @@ -1794,7 +1794,7 @@ Result BinaryReader::ReadInstructions(Offset end_offset, const char* context) { "memory.init requires data count section"); CHECK_RESULT(ReadIndex(&segment, "elem segment index")); Index memidx = 0; - if (!options_.features.multi_memory_enabled()) { + if (!options_.GetFeatures().multi_memory_enabled()) { uint8_t reserved; CHECK_RESULT(ReadU8(&reserved, "reserved memory index")); ERROR_UNLESS(reserved == 0, "reserved value must be 0"); @@ -1824,7 +1824,7 @@ Result BinaryReader::ReadInstructions(Offset end_offset, const char* context) { case Opcode::MemoryFill: { Index memidx = 0; - if (!options_.features.multi_memory_enabled()) { + if (!options_.GetFeatures().multi_memory_enabled()) { uint8_t reserved; CHECK_RESULT(ReadU8(&reserved, "memory.fill reserved")); ERROR_UNLESS(reserved == 0, "memory.fill reserved value must be 0"); @@ -1839,7 +1839,7 @@ Result BinaryReader::ReadInstructions(Offset end_offset, const char* context) { case Opcode::MemoryCopy: { Index destmemidx = 0; Index srcmemidx = 0; - if (!options_.features.multi_memory_enabled()) { + if (!options_.GetFeatures().multi_memory_enabled()) { uint8_t reserved; CHECK_RESULT(ReadU8(&reserved, "reserved memory index")); ERROR_UNLESS(reserved == 0, "reserved value must be 0"); @@ -2496,7 +2496,7 @@ Result BinaryReader::ReadCustomSection(Index section_index, CHECK_RESULT(ReadGenericCustomSection(section_name, section_size)); } - if (options_.read_debug_names && section_name == WABT_BINARY_SECTION_NAME) { + if (options_.ReadDebugNames() && section_name == WABT_BINARY_SECTION_NAME) { CHECK_RESULT(ReadNameSection(section_size)); did_read_names_section_ = true; } else if (section_name == WABT_BINARY_SECTION_DYLINK0) { @@ -2510,7 +2510,7 @@ Result BinaryReader::ReadCustomSection(Index section_index, CHECK_RESULT(ReadTargetFeaturesSections(section_size)); } else if (section_name == WABT_BINARY_SECTION_LINKING) { CHECK_RESULT(ReadLinkingSection(section_size)); - } else if (options_.features.code_metadata_enabled() && + } else if (options_.GetFeatures().code_metadata_enabled() && section_name.find(WABT_BINARY_SECTION_CODE_METADATA) == 0) { std::string_view metadata_name = section_name; metadata_name.remove_prefix(sizeof(WABT_BINARY_SECTION_CODE_METADATA) - 1); @@ -2531,7 +2531,7 @@ Result BinaryReader::ReadTypeSection(Offset section_size) { for (Index i = 0; i < num_signatures; ++i) { Type form; - if (options_.features.gc_enabled()) { + if (options_.GetFeatures().gc_enabled()) { CHECK_RESULT(ReadType(&form, "type form")); } else { uint8_t type; @@ -2579,7 +2579,7 @@ Result BinaryReader::ReadTypeSection(Offset section_size) { } case Type::Struct: { - ERROR_UNLESS(options_.features.gc_enabled(), + ERROR_UNLESS(options_.GetFeatures().gc_enabled(), "invalid type form: struct not allowed"); Index num_fields; CHECK_RESULT(ReadCount(&num_fields, "field count")); @@ -2594,7 +2594,7 @@ Result BinaryReader::ReadTypeSection(Offset section_size) { } case Type::Array: { - ERROR_UNLESS(options_.features.gc_enabled(), + ERROR_UNLESS(options_.GetFeatures().gc_enabled(), "invalid type form: array not allowed"); TypeMut field; @@ -2669,7 +2669,7 @@ Result BinaryReader::ReadImportSection(Offset section_size) { } case ExternalKind::Tag: { - ERROR_UNLESS(options_.features.exceptions_enabled(), + ERROR_UNLESS(options_.GetFeatures().exceptions_enabled(), "invalid import tag kind: exceptions not allowed"); Index sig_index; CHECK_RESULT(ReadTagType(&sig_index)); @@ -2771,7 +2771,7 @@ Result BinaryReader::ReadExportSection(Offset section_size) { Index item_index; CHECK_RESULT(ReadIndex(&item_index, "export item index")); if (kind == ExternalKind::Tag) { - ERROR_UNLESS(options_.features.exceptions_enabled(), + ERROR_UNLESS(options_.GetFeatures().exceptions_enabled(), "invalid export tag kind: exceptions not allowed"); } @@ -2886,7 +2886,7 @@ Result BinaryReader::ReadCodeSection(Offset section_size) { } CALLBACK(EndLocalDecls); - if (options_.skip_function_bodies) { + if (options_.SkipFunctionBodies()) { state_.offset = end_offset; } else { CHECK_RESULT(ReadFunctionBody(end_offset)); @@ -2909,7 +2909,7 @@ Result BinaryReader::ReadDataSection(Offset section_size) { for (Index i = 0; i < num_data_segments_; ++i) { uint32_t flags; CHECK_RESULT(ReadU32Leb128(&flags, "data segment flags")); - ERROR_IF(flags != 0 && !options_.features.bulk_memory_enabled(), + ERROR_IF(flags != 0 && !options_.GetFeatures().bulk_memory_enabled(), "invalid memory index %d: bulk memory not allowed", flags); ERROR_IF(flags > SegFlagMax, "invalid data segment flags: %#x", flags); Index memory_index(0); @@ -2994,12 +2994,12 @@ Result BinaryReader::ReadSections(const ReadSectionsOptions& options) { CALLBACK(BeginSection, section_index, section, section_size); - bool stop_on_first_error = options_.stop_on_first_error; + bool stop_on_first_error = options_.StopOnFirstError(); Result section_result = Result::Error; switch (section) { case BinarySection::Custom: section_result = ReadCustomSection(section_index, section_size); - if (options_.fail_on_custom_section_error) { + if (options_.FailOnCustomSectionError()) { result |= section_result; } else { stop_on_first_error = false; @@ -3050,14 +3050,14 @@ Result BinaryReader::ReadSections(const ReadSectionsOptions& options) { result |= section_result; break; case BinarySection::Tag: - ERROR_UNLESS(options_.features.exceptions_enabled(), + ERROR_UNLESS(options_.GetFeatures().exceptions_enabled(), "invalid section code: %u", static_cast(section)); section_result = ReadTagSection(section_size); result |= section_result; break; case BinarySection::DataCount: - ERROR_UNLESS(options_.features.bulk_memory_enabled(), + ERROR_UNLESS(options_.GetFeatures().bulk_memory_enabled(), "invalid section code: %u", static_cast(section)); section_result = ReadDataCountSection(section_size); @@ -3139,7 +3139,7 @@ Result ReadBinary(const void* data, const ReadBinaryOptions& options) { BinaryReader reader(data, size, delegate, options); return reader.ReadModule( - BinaryReader::ReadModuleOptions{options.stop_on_first_error}); + BinaryReader::ReadModuleOptions{options.StopOnFirstError()}); } } // namespace wabt diff --git a/src/emscripten-helpers.cc b/src/emscripten-helpers.cc index 127a8c458d..10ef6bcf82 100644 --- a/src/emscripten-helpers.cc +++ b/src/emscripten-helpers.cc @@ -130,7 +130,7 @@ WabtReadBinaryResult* wabt_read_binary(const void* data, int read_debug_names, wabt::Features* features, wabt::Errors* errors) { - wabt::ReadBinaryOptions options; + wabt::ReadBinaryIrOptions options; options.features = *features; options.read_debug_names = read_debug_names; diff --git a/src/interp/binary-reader-interp.cc b/src/interp/binary-reader-interp.cc index 7e9b8d5e14..79f1840348 100644 --- a/src/interp/binary-reader-interp.cc +++ b/src/interp/binary-reader-interp.cc @@ -1713,7 +1713,7 @@ Result BinaryReaderInterp::OnDelegateExpr(Index depth) { Result ReadBinaryInterp(std::string_view filename, const void* data, size_t size, - const ReadBinaryOptions& options, + const ReadBinaryInterpOptions& options, Errors* errors, ModuleDesc* out_module) { BinaryReaderInterp reader(out_module, filename, errors, options.features); diff --git a/src/interp/interp-wasm-c-api.cc b/src/interp/interp-wasm-c-api.cc index bb4598a472..2d38729b59 100644 --- a/src/interp/interp-wasm-c-api.cc +++ b/src/interp/interp-wasm-c-api.cc @@ -513,16 +513,12 @@ static wasm_message_t FromString(const std::string& s) { return result; } -static ReadBinaryOptions GetOptions() { - const bool kReadDebugNames = true; - const bool kStopOnFirstError = true; - const bool kFailOnCustomSectionError = true; +static ReadBinaryInterpOptions GetOptions() { s_features.EnableAll(); if (getenv("WASM_API_DEBUG") != nullptr) { s_log_stream = FileStream::CreateStderr(); } - return ReadBinaryOptions(s_features, s_log_stream.get(), kReadDebugNames, - kStopOnFirstError, kFailOnCustomSectionError); + return ReadBinaryInterpOptions(s_features, s_log_stream.get()); } extern "C" { diff --git a/src/test-binary-reader.cc b/src/test-binary-reader.cc index b3e3540d4f..5578281c09 100644 --- a/src/test-binary-reader.cc +++ b/src/test-binary-reader.cc @@ -34,11 +34,18 @@ struct BinaryReaderError : BinaryReaderNop { Error first_error; }; +class ReadBinaryTestOptions : public ReadBinaryOptions { + public: + Features features; + const Features& GetFeatures() const override { return features; } + Stream* GetLogStream() const override { return nullptr; } +}; + } // End of anonymous namespace TEST(BinaryReader, DisabledOpcodes) { // Use the default features. - ReadBinaryOptions options; + ReadBinaryTestOptions options; // Loop through all opcodes. for (uint32_t i = 0; i < static_cast(Opcode::Invalid); ++i) { diff --git a/src/test-interp.cc b/src/test-interp.cc index 9346b7b166..40756e7dc4 100644 --- a/src/test-interp.cc +++ b/src/test-interp.cc @@ -29,7 +29,7 @@ class InterpTest : public ::testing::Test { public: void ReadModule(const std::vector& data) { Errors errors; - ReadBinaryOptions options; + ReadBinaryInterpOptions options; Result result = ReadBinaryInterp("", data.data(), data.size(), options, &errors, &module_desc_); ASSERT_EQ(Result::Ok, result) diff --git a/src/tools/spectest-interp.cc b/src/tools/spectest-interp.cc index d859f14823..4ea3aaf0c4 100644 --- a/src/tools/spectest-interp.cc +++ b/src/tools/spectest-interp.cc @@ -283,11 +283,8 @@ bool CheckIR(const std::string& filename, bool validate) { return false; } - const bool kReadDebugNames = true; - const bool kStopOnFirstError = true; - const bool kFailOnCustomSectionError = true; - ReadBinaryOptions options(s_features, s_log_stream.get(), kReadDebugNames, - kStopOnFirstError, kFailOnCustomSectionError); + ReadBinaryIrOptions options(s_features, s_log_stream.get()); + options.read_debug_names = true; Errors errors; wabt::Module module; @@ -1477,11 +1474,7 @@ interp::Module::Ptr CommandRunner::ReadModule(std::string_view module_filename, return {}; } - const bool kReadDebugNames = true; - const bool kStopOnFirstError = true; - const bool kFailOnCustomSectionError = true; - ReadBinaryOptions options(s_features, s_log_stream.get(), kReadDebugNames, - kStopOnFirstError, kFailOnCustomSectionError); + ReadBinaryInterpOptions options(s_features, s_log_stream.get()); ModuleDesc module_desc; if (Failed(ReadBinaryInterp(module_filename, file_data.data(), file_data.size(), options, errors, @@ -1531,11 +1524,8 @@ wabt::Result CommandRunner::ReadMalformedBinaryModule( CHECK_RESULT(ReadFile(module_filename, &file_data)); - const bool kReadDebugNames = true; - const bool kStopOnFirstError = true; - const bool kFailOnCustomSectionError = true; - ReadBinaryOptions options(s_features, s_log_stream.get(), kReadDebugNames, - kStopOnFirstError, kFailOnCustomSectionError); + // while we are using a custom delegate, use the same rules as interp. + ReadBinaryInterpOptions options(s_features, s_log_stream.get()); class BinaryReaderErrorLogging : public BinaryReaderNop { Errors* errors_; diff --git a/src/tools/wasm-decompile.cc b/src/tools/wasm-decompile.cc index 5c8c125237..2882eb6b73 100644 --- a/src/tools/wasm-decompile.cc +++ b/src/tools/wasm-decompile.cc @@ -76,9 +76,9 @@ int ProgramMain(int argc, char** argv) { if (Succeeded(result)) { Errors errors; Module module; - const bool kStopOnFirstError = true; - ReadBinaryOptions options(features, nullptr, true, kStopOnFirstError, - fail_on_custom_section_error); + ReadBinaryIrOptions options(features, nullptr); + options.read_debug_names = true; + options.fail_on_custom_section_error = fail_on_custom_section_error; result = ReadBinaryIr(infile.c_str(), file_data.data(), file_data.size(), options, &errors, &module); if (Succeeded(result)) { diff --git a/src/tools/wasm-interp.cc b/src/tools/wasm-interp.cc index 97c14d3a2b..913b899e16 100644 --- a/src/tools/wasm-interp.cc +++ b/src/tools/wasm-interp.cc @@ -316,11 +316,7 @@ static Result ReadModule(const char* module_filename, CHECK_RESULT(ReadFile(module_filename, &file_data)); ModuleDesc module_desc; - const bool kReadDebugNames = true; - const bool kStopOnFirstError = true; - const bool kFailOnCustomSectionError = true; - ReadBinaryOptions options(s_features, s_log_stream.get(), kReadDebugNames, - kStopOnFirstError, kFailOnCustomSectionError); + ReadBinaryInterpOptions options(s_features, s_log_stream.get()); CHECK_RESULT(ReadBinaryInterp(module_filename, file_data.data(), file_data.size(), options, errors, &module_desc)); diff --git a/src/tools/wasm-stats.cc b/src/tools/wasm-stats.cc index d8fb1fb433..5292b3a974 100644 --- a/src/tools/wasm-stats.cc +++ b/src/tools/wasm-stats.cc @@ -40,7 +40,7 @@ static const char* s_outfile; static size_t s_cutoff = 0; static const char* s_separator = ": "; -static ReadBinaryOptions s_read_binary_options; +static ReadBinaryStatsOptions s_read_binary_options; static std::unique_ptr s_log_stream; static Features s_features; diff --git a/src/tools/wasm-strip.cc b/src/tools/wasm-strip.cc index 9b5479cfd5..002abbee7f 100644 --- a/src/tools/wasm-strip.cc +++ b/src/tools/wasm-strip.cc @@ -133,13 +133,18 @@ int ProgramMain(int argc, char** argv) { } Errors errors; - Features features; - features.EnableAll(); - const bool kReadDebugNames = false; - const bool kStopOnFirstError = true; - const bool kFailOnCustomSectionError = false; - ReadBinaryOptions options(features, nullptr, kReadDebugNames, - kStopOnFirstError, kFailOnCustomSectionError); + class ReadBinaryStripOptions : public ReadBinaryOptions { + Features features; + + public: + ReadBinaryStripOptions() { features.EnableAll(); } + + const Features& GetFeatures() const override { return features; } + Stream* GetLogStream() const override { return nullptr; } + bool ReadDebugNames() const override { return false; } + bool FailOnCustomSectionError() const override { return false; } + }; + ReadBinaryStripOptions options; BinaryReaderStrip reader(v_sections_to_keep, v_sections_to_remove, &errors); result = ReadBinary(file_data.data(), file_data.size(), &reader, options); diff --git a/src/tools/wasm-validate.cc b/src/tools/wasm-validate.cc index d093f1bee7..74c7df6a79 100644 --- a/src/tools/wasm-validate.cc +++ b/src/tools/wasm-validate.cc @@ -77,10 +77,9 @@ int ProgramMain(int argc, char** argv) { if (Succeeded(result)) { Errors errors; Module module; - const bool kStopOnFirstError = true; - ReadBinaryOptions options(s_features, s_log_stream.get(), - s_read_debug_names, kStopOnFirstError, - s_fail_on_custom_section_error); + ReadBinaryIrOptions options(s_features, s_log_stream.get()); + options.read_debug_names = s_read_debug_names; + options.fail_on_custom_section_error = s_fail_on_custom_section_error; result = ReadBinaryIr(s_infile.c_str(), file_data.data(), file_data.size(), options, &errors, &module); if (Succeeded(result)) { diff --git a/src/tools/wasm2c.cc b/src/tools/wasm2c.cc index 68bc7a6ba0..c563bf0312 100644 --- a/src/tools/wasm2c.cc +++ b/src/tools/wasm2c.cc @@ -127,11 +127,8 @@ Result Wasm2cMain(Errors& errors) { CHECK_RESULT(ReadFile(s_infile.c_str(), &file_data)); Module module; - const bool kStopOnFirstError = true; - const bool kFailOnCustomSectionError = true; - ReadBinaryOptions options(s_write_c_options.features, s_log_stream.get(), - s_read_debug_names, kStopOnFirstError, - kFailOnCustomSectionError); + ReadBinaryIrOptions options(s_write_c_options.features, s_log_stream.get()); + options.read_debug_names = s_read_debug_names; CHECK_RESULT(ReadBinaryIr(s_infile.c_str(), file_data.data(), file_data.size(), options, &errors, &module)); CHECK_RESULT(ValidateModule(&module, &errors, s_write_c_options.features)); diff --git a/src/tools/wasm2wat-fuzz.cc b/src/tools/wasm2wat-fuzz.cc index 5247424835..a810e4121c 100644 --- a/src/tools/wasm2wat-fuzz.cc +++ b/src/tools/wasm2wat-fuzz.cc @@ -22,7 +22,7 @@ #include "wabt/ir.h" extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { - wabt::ReadBinaryOptions options; + wabt::ReadBinaryIrOptions options; wabt::Errors errors; wabt::Module module; wabt::ReadBinaryIr("dummy filename", data, size, options, &errors, &module); diff --git a/src/tools/wasm2wat.cc b/src/tools/wasm2wat.cc index 25e1c743c6..c3afe94062 100644 --- a/src/tools/wasm2wat.cc +++ b/src/tools/wasm2wat.cc @@ -110,10 +110,9 @@ int ProgramMain(int argc, char** argv) { if (Succeeded(result)) { Errors errors; Module module; - const bool kStopOnFirstError = true; - ReadBinaryOptions options(s_features, s_log_stream.get(), - s_read_debug_names, kStopOnFirstError, - s_fail_on_custom_section_error); + ReadBinaryIrOptions options(s_features, s_log_stream.get()); + options.read_debug_names = s_read_debug_names; + options.fail_on_custom_section_error = s_fail_on_custom_section_error; result = ReadBinaryIr(s_infile.c_str(), file_data.data(), file_data.size(), options, &errors, &module); if (Succeeded(result)) { diff --git a/src/wast-parser.cc b/src/wast-parser.cc index a1dc32f3bb..fdb2ba7490 100644 --- a/src/wast-parser.cc +++ b/src/wast-parser.cc @@ -3519,7 +3519,7 @@ Result WastParser::ParseModuleCommand(Script* script, CommandPtr* out_command) { auto command = std::make_unique(); module = &command->module; auto* bsm = cast(script_module.get()); - ReadBinaryOptions options; + ReadBinaryIrOptions options; #if WABT_TRACING auto log_stream = FileStream::CreateStdout(); options.log_stream = log_stream.get();