From c57642cbd5edc1ca653b8fb88991766343766094 Mon Sep 17 00:00:00 2001 From: Ryan Harrison Date: Thu, 30 Sep 2021 18:58:32 +0000 Subject: [PATCH] Refactor fuzzer transform generation Also splits out various utility classes from tint_common_fuzzer and uses consistent naming for utility classes. BUG=tint:1106 Change-Id: Ic343741eea799366850c46834865d50885554a84 Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/65301 Auto-Submit: Ryan Harrison Kokoro: Kokoro Commit-Queue: Ryan Harrison Reviewed-by: Antonio Maiorano --- fuzzers/BUILD.gn | 6 +- fuzzers/CMakeLists.txt | 6 +- fuzzers/data_builder.h | 142 ++++++++++++ .../{tint_init_fuzzer.cc => fuzzer_init.cc} | 2 +- fuzzers/{tint_init_fuzzer.h => fuzzer_init.h} | 6 +- fuzzers/random_generator.cc | 3 + fuzzers/random_generator.h | 6 + fuzzers/tint_all_transforms_fuzzer.cc | 48 ++-- fuzzers/tint_ast_fuzzer/fuzzer.cc | 2 +- fuzzers/tint_binding_remapper_fuzzer.cc | 14 +- fuzzers/tint_common_fuzzer.cc | 97 +-------- fuzzers/tint_common_fuzzer.h | 68 +----- fuzzers/tint_first_index_offset_fuzzer.cc | 15 +- fuzzers/tint_inspector_fuzzer.cc | 12 +- fuzzers/tint_regex_fuzzer/fuzzer.cc | 2 +- fuzzers/tint_renamer_fuzzer.cc | 2 +- fuzzers/tint_robustness_fuzzer.cc | 2 +- fuzzers/tint_single_entry_point_fuzzer.cc | 15 +- fuzzers/tint_spv_reader_fuzzer.cc | 2 +- fuzzers/tint_spv_reader_hlsl_writer_fuzzer.cc | 2 +- fuzzers/tint_spv_reader_msl_writer_fuzzer.cc | 2 +- fuzzers/tint_spv_reader_spv_writer_fuzzer.cc | 2 +- fuzzers/tint_spv_reader_wgsl_writer_fuzzer.cc | 2 +- fuzzers/tint_vertex_pulling_fuzzer.cc | 13 +- fuzzers/tint_wgsl_reader_fuzzer.cc | 2 +- .../tint_wgsl_reader_hlsl_writer_fuzzer.cc | 2 +- fuzzers/tint_wgsl_reader_msl_writer_fuzzer.cc | 2 +- fuzzers/tint_wgsl_reader_spv_writer_fuzzer.cc | 2 +- .../tint_wgsl_reader_wgsl_writer_fuzzer.cc | 2 +- fuzzers/transform_builder.h | 206 ++++++++++++++++++ 30 files changed, 436 insertions(+), 251 deletions(-) create mode 100644 fuzzers/data_builder.h rename fuzzers/{tint_init_fuzzer.cc => fuzzer_init.cc} (96%) rename fuzzers/{tint_init_fuzzer.h => fuzzer_init.h} (88%) create mode 100644 fuzzers/transform_builder.h diff --git a/fuzzers/BUILD.gn b/fuzzers/BUILD.gn index 00844079f1..acb510b967 100644 --- a/fuzzers/BUILD.gn +++ b/fuzzers/BUILD.gn @@ -66,10 +66,12 @@ if (build_with_chromium) { ] sources = [ + "data_builder.h", "random_generator.cc", "random_generator.h", "tint_common_fuzzer.cc", "tint_common_fuzzer.h", + "transform_builder.h", ] } @@ -79,8 +81,8 @@ if (build_with_chromium) { sources = [ "cli.cc", "cli.h", - "tint_init_fuzzer.cc", - "tint_init_fuzzer.h", + "fuzzer_init.cc", + "fuzzer_init.h", ] } if (tint_build_wgsl_reader) { diff --git a/fuzzers/CMakeLists.txt b/fuzzers/CMakeLists.txt index f50ec5646c..0c8b1cac57 100644 --- a/fuzzers/CMakeLists.txt +++ b/fuzzers/CMakeLists.txt @@ -17,12 +17,14 @@ function(add_tint_fuzzer NAME) ${NAME}.cc cli.cc cli.h + data_builder.h + fuzzer_init.cc + fuzzer_init.h random_generator.cc random_generator.h tint_common_fuzzer.cc tint_common_fuzzer.h - tint_init_fuzzer.cc - tint_init_fuzzer.h + transform_builder.h ) target_link_libraries(${NAME} libtint-fuzz) tint_default_compile_options(${NAME}) diff --git a/fuzzers/data_builder.h b/fuzzers/data_builder.h new file mode 100644 index 0000000000..b6ec22fd45 --- /dev/null +++ b/fuzzers/data_builder.h @@ -0,0 +1,142 @@ +// Copyright 2021 The Tint Authors. +// +// 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 FUZZERS_DATA_BUILDER_H_ +#define FUZZERS_DATA_BUILDER_H_ + +#include +#include +#include +#include + +#include "fuzzers/random_generator.h" + +namespace tint { +namespace fuzzers { + +/// Builder for generic pseudo-random data using a data buffer as seed +class DataBuilder { + public: + /// @brief Initialize random number generations + /// @param data - pointer to a data buffer to use as a seed + /// @param size - size of data buffer + explicit DataBuilder(const uint8_t* data, size_t size) + : generator_(data, size) {} + + ~DataBuilder() {} + + /// Generate pseudo-random data of a specific type + /// @tparam T - type of data to produce + /// @returns pseudo-random data of type T + template + T build() { + return BuildImpl::impl(this); + } + + /// Generate pseudo-random data of a specific type in a vector + /// @tparam T - data type held vector + /// @returns pseudo-random data of type std::vector + template + std::vector vector() { + auto count = build(); + std::vector out(count); + for (uint8_t i = 0; i < count; i++) { + out[i] = build(); + } + return out; + } + + /// Generate complex pseudo-random data of a specific type in a vector + /// @tparam T - data type held vector + /// @tparam Callback - callback that takes in a DataBuilder* and returns a T + /// @param generate - callback for generating each instance of T + /// @returns pseudo-random data of type std::vector + template + std::vector vector(Callback generate) { + auto count = build(); + std::vector out(count); + for (size_t i = 0; i < count; i++) { + out[i] = generate(this); + } + return out; + } + + /// Generate an pseudo-random entry to a enum class. + /// Assumes enum is tightly packed starting at 0. + /// @tparam T - type of enum class + /// @param count - number of entries in enum class + /// @returns a random enum class entry + template + T enum_class(uint32_t count) { + return static_cast(generator_.Get4Bytes() % count); + } + + private: + RandomGenerator generator_; + + /// Get N bytes of pseudo-random data + /// @param out - pointer to location to save data + /// @param n - number of bytes to get + void build(void* out, size_t n) { + assert(out != nullptr && "|out| cannot be nullptr"); + assert(n > 0 && "|n| must be > 0"); + + generator_.GetNBytes(reinterpret_cast(out), n); + } + + /// Implementation of ::build() + /// @tparam T - type of data to produce + template + struct BuildImpl { + /// Generate a pseudo-random variable of type T + /// @param b - data builder to use + /// @returns a variable of type T filled with pseudo-random data + static T impl(DataBuilder* b) { + T out{}; + b->build(&out, sizeof(T)); + return out; + } + }; + + /// Specialization for std::string + template <> + struct BuildImpl { + /// Generate a pseudo-random string + /// @param b - data builder to use + /// @returns a string filled with pseudo-random data + static std::string impl(DataBuilder* b) { + auto count = b->build(); + if (count == 0) { + return ""; + } + std::vector source(count); + b->build(source.data(), count); + return std::string(source.begin(), source.end()); + } + }; + + /// Specialization for bool + template <> + struct BuildImpl { + /// Generate a pseudo-random bool + /// @param b - data builder to use + /// @returns a boolean with even odds of being true or false + static bool impl(DataBuilder* b) { return b->generator_.GetBool(); } + }; +}; + +} // namespace fuzzers +} // namespace tint + +#endif // FUZZERS_DATA_BUILDER_H_ diff --git a/fuzzers/tint_init_fuzzer.cc b/fuzzers/fuzzer_init.cc similarity index 96% rename from fuzzers/tint_init_fuzzer.cc rename to fuzzers/fuzzer_init.cc index b8e38cdc4e..f651713a74 100644 --- a/fuzzers/tint_init_fuzzer.cc +++ b/fuzzers/fuzzer_init.cc @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -#include "fuzzers/tint_init_fuzzer.h" +#include "fuzzers/fuzzer_init.h" #include "fuzzers/cli.h" namespace tint { diff --git a/fuzzers/tint_init_fuzzer.h b/fuzzers/fuzzer_init.h similarity index 88% rename from fuzzers/tint_init_fuzzer.h rename to fuzzers/fuzzer_init.h index 278ab5bde6..fa96ce5d2a 100644 --- a/fuzzers/tint_init_fuzzer.h +++ b/fuzzers/fuzzer_init.h @@ -12,8 +12,8 @@ // See the License for the specific language governing permissions and // limitations under the License. -#ifndef FUZZERS_TINT_INIT_FUZZER_H_ -#define FUZZERS_TINT_INIT_FUZZER_H_ +#ifndef FUZZERS_FUZZER_INIT_H_ +#define FUZZERS_FUZZER_INIT_H_ #include "fuzzers/cli.h" @@ -26,4 +26,4 @@ const CliParams& GetCliParams(); } // namespace fuzzers } // namespace tint -#endif // FUZZERS_TINT_INIT_FUZZER_H_ +#endif // FUZZERS_FUZZER_INIT_H_ diff --git a/fuzzers/random_generator.cc b/fuzzers/random_generator.cc index 20b04db1a5..a485b0e221 100644 --- a/fuzzers/random_generator.cc +++ b/fuzzers/random_generator.cc @@ -58,6 +58,9 @@ size_t HashBuffer(const uint8_t* data, const size_t size) { RandomGenerator::RandomGenerator(uint64_t seed) : engine_(seed) {} +RandomGenerator::RandomGenerator(const uint8_t* data, size_t size) + : engine_(RandomGenerator::CalculateSeed(data, size)) {} + uint32_t RandomGenerator::GetUInt32(uint32_t lower, uint32_t upper) { return RandomUInt(&engine_, lower, upper); } diff --git a/fuzzers/random_generator.h b/fuzzers/random_generator.h index 1879045b21..4fe6acc64b 100644 --- a/fuzzers/random_generator.h +++ b/fuzzers/random_generator.h @@ -27,6 +27,12 @@ class RandomGenerator { /// @brief Initializes the internal engine /// @param seed - seed value passed to engine explicit RandomGenerator(uint64_t seed); + + /// @brief Wrapper that invokes CalculateSeed for caller + /// @param data - data fuzzer to calculate seed from + /// @param size - size of data buffer + explicit RandomGenerator(const uint8_t* data, size_t size); + ~RandomGenerator() {} /// Get uint32_t value from uniform distribution. diff --git a/fuzzers/tint_all_transforms_fuzzer.cc b/fuzzers/tint_all_transforms_fuzzer.cc index 083ee289a2..88b6c82ee1 100644 --- a/fuzzers/tint_all_transforms_fuzzer.cc +++ b/fuzzers/tint_all_transforms_fuzzer.cc @@ -12,41 +12,21 @@ // See the License for the specific language governing permissions and // limitations under the License. +#include "fuzzers/fuzzer_init.h" #include "fuzzers/random_generator.h" #include "fuzzers/tint_common_fuzzer.h" -#include "fuzzers/tint_init_fuzzer.h" +#include "fuzzers/transform_builder.h" namespace tint { namespace fuzzers { -struct Config { - Config(const uint8_t* data, size_t size) : builder(data, size) {} - DataBuilder builder; - transform::Manager manager; - transform::DataMap inputs; -}; - -void AddPlatformIndependentPasses(Config* config) { - GenerateFirstIndexOffsetInputs(&config->builder, &config->inputs); - GenerateBindingRemapperInputs(&config->builder, &config->inputs); - GenerateSingleEntryPointInputs(&config->builder, &config->inputs); - GenerateVertexPullingInputs(&config->builder, &config->inputs); - - config->manager.Add(); - config->manager.Add(); - config->manager.Add(); - config->manager.Add(); - config->manager.Add(); - config->manager.Add(); -} - extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { { - Config config(data, size); - AddPlatformIndependentPasses(&config); + TransformBuilder tb(data, size); + tb.AddPlatformIndependentPasses(); fuzzers::CommonFuzzer fuzzer(InputFormat::kWGSL, OutputFormat::kSpv); - fuzzer.SetTransformManager(&(config.manager), std::move(config.inputs)); + fuzzer.SetTransformManager(tb.manager(), tb.data_map()); fuzzer.SetDumpInput(GetCliParams().dump_input); fuzzer.Run(data, size); @@ -54,11 +34,11 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { #if TINT_BUILD_HLSL_WRITER { - Config config(data, size); - AddPlatformIndependentPasses(&config); + TransformBuilder tb(data, size); + tb.AddPlatformIndependentPasses(); fuzzers::CommonFuzzer fuzzer(InputFormat::kWGSL, OutputFormat::kHLSL); - fuzzer.SetTransformManager(&config.manager, std::move(config.inputs)); + fuzzer.SetTransformManager(tb.manager(), tb.data_map()); fuzzer.SetDumpInput(GetCliParams().dump_input); fuzzer.Run(data, size); @@ -67,11 +47,11 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { #if TINT_BUILD_MSL_WRITER { - Config config(data, size); - AddPlatformIndependentPasses(&config); + TransformBuilder tb(data, size); + tb.AddPlatformIndependentPasses(); fuzzers::CommonFuzzer fuzzer(InputFormat::kWGSL, OutputFormat::kMSL); - fuzzer.SetTransformManager(&config.manager, std::move(config.inputs)); + fuzzer.SetTransformManager(tb.manager(), tb.data_map()); fuzzer.SetDumpInput(GetCliParams().dump_input); fuzzer.Run(data, size); @@ -79,11 +59,11 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { #endif // TINT_BUILD_MSL_WRITER #if TINT_BUILD_SPV_WRITER { - Config config(data, size); - AddPlatformIndependentPasses(&config); + TransformBuilder tb(data, size); + tb.AddPlatformIndependentPasses(); fuzzers::CommonFuzzer fuzzer(InputFormat::kWGSL, OutputFormat::kSpv); - fuzzer.SetTransformManager(&config.manager, std::move(config.inputs)); + fuzzer.SetTransformManager(tb.manager(), tb.data_map()); fuzzer.SetDumpInput(GetCliParams().dump_input); fuzzer.Run(data, size); diff --git a/fuzzers/tint_ast_fuzzer/fuzzer.cc b/fuzzers/tint_ast_fuzzer/fuzzer.cc index cdb1693197..ca60cf8a04 100644 --- a/fuzzers/tint_ast_fuzzer/fuzzer.cc +++ b/fuzzers/tint_ast_fuzzer/fuzzer.cc @@ -115,7 +115,7 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { CommonFuzzer fuzzer(InputFormat::kWGSL, target.output_format); fuzzer.EnableInspector(); - fuzzer.SetTransformManager(&transform_manager, std::move(transform_inputs)); + fuzzer.SetTransformManager(&transform_manager, &transform_inputs); fuzzer.Run(data, size); if (fuzzer.HasErrors()) { diff --git a/fuzzers/tint_binding_remapper_fuzzer.cc b/fuzzers/tint_binding_remapper_fuzzer.cc index c701078ea3..4deb2d8f75 100644 --- a/fuzzers/tint_binding_remapper_fuzzer.cc +++ b/fuzzers/tint_binding_remapper_fuzzer.cc @@ -12,23 +12,19 @@ // See the License for the specific language governing permissions and // limitations under the License. +#include "fuzzers/fuzzer_init.h" #include "fuzzers/tint_common_fuzzer.h" -#include "fuzzers/tint_init_fuzzer.h" +#include "fuzzers/transform_builder.h" namespace tint { namespace fuzzers { extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { - transform::Manager transform_manager; - transform::DataMap transform_inputs; - DataBuilder b(data, size); - - GenerateBindingRemapperInputs(&b, &transform_inputs); - - transform_manager.Add(); + TransformBuilder tb(data, size); + tb.AddTransform(); fuzzers::CommonFuzzer fuzzer(InputFormat::kWGSL, OutputFormat::kWGSL); - fuzzer.SetTransformManager(&transform_manager, std::move(transform_inputs)); + fuzzer.SetTransformManager(tb.manager(), tb.data_map()); fuzzer.SetDumpInput(GetCliParams().dump_input); return fuzzer.Run(data, size); diff --git a/fuzzers/tint_common_fuzzer.cc b/fuzzers/tint_common_fuzzer.cc index f15c7336fc..ac4de239c0 100644 --- a/fuzzers/tint_common_fuzzer.cc +++ b/fuzzers/tint_common_fuzzer.cc @@ -52,26 +52,6 @@ namespace { FatalError(diagnostics); } -transform::VertexAttributeDescriptor GenerateVertexAttributeDescriptor( - DataBuilder* b) { - transform::VertexAttributeDescriptor desc{}; - desc.format = b->enum_class( - static_cast(transform::VertexFormat::kLastEntry) + 1); - desc.offset = b->build(); - desc.shader_location = b->build(); - return desc; -} - -transform::VertexBufferLayoutDescriptor GenerateVertexBufferLayoutDescriptor( - DataBuilder* b) { - transform::VertexBufferLayoutDescriptor desc; - desc.array_stride = b->build(); - desc.step_mode = b->enum_class( - static_cast(transform::VertexStepMode::kLastEntry) + 1); - desc.attributes = b->vector(GenerateVertexAttributeDescriptor); - return desc; -} - bool SPIRVToolsValidationCheck(const tint::Program& program, const std::vector& spirv) { spvtools::SpirvTools tools(SPV_ENV_VULKAN_1_1); @@ -94,76 +74,6 @@ bool SPIRVToolsValidationCheck(const tint::Program& program, } // namespace -DataBuilder::DataBuilder(const uint8_t* data, size_t size) - : generator_(RandomGenerator::CalculateSeed(data, size)) {} - -std::string DataBuilder::string() { - auto count = build(); - if (count == 0) { - return ""; - } - std::vector source(count); - build(source.data(), count); - return std::string(source.begin(), source.end()); -} - -void DataBuilder::build(void* out, size_t n) { - assert(out != nullptr && "|out| cannot be nullptr"); - assert(n > 0 && "|n| must be > 0"); - - generator_.GetNBytes(reinterpret_cast(out), n); -} - -void GenerateBindingRemapperInputs(DataBuilder* b, - tint::transform::DataMap* inputs) { - struct Config { - uint8_t old_group; - uint8_t old_binding; - uint8_t new_group; - uint8_t new_binding; - ast::Access new_access; - }; - - std::vector configs = b->vector(); - transform::BindingRemapper::BindingPoints binding_points; - transform::BindingRemapper::AccessControls accesses; - for (const auto& config : configs) { - binding_points[{config.old_binding, config.old_group}] = { - config.new_binding, config.new_group}; - accesses[{config.old_binding, config.old_group}] = config.new_access; - } - - inputs->Add(binding_points, accesses); -} - -void GenerateFirstIndexOffsetInputs(DataBuilder* b, - tint::transform::DataMap* inputs) { - struct Config { - uint32_t group; - uint32_t binding; - }; - - Config config = b->build(); - inputs->Add(config.binding, - config.group); -} - -void GenerateSingleEntryPointInputs(DataBuilder* b, - tint::transform::DataMap* inputs) { - std::string input = b->string(); - transform::SingleEntryPoint::Config cfg(input); - inputs->Add(cfg); -} - -void GenerateVertexPullingInputs(DataBuilder* b, - tint::transform::DataMap* inputs) { - transform::VertexPulling::Config cfg; - cfg.entry_point_name = b->string(); - cfg.vertex_state = b->vector(GenerateVertexBufferLayoutDescriptor); - cfg.pulling_group = b->build(); - inputs->Add(cfg); -} - void GenerateSpirvOptions(DataBuilder* b, writer::spirv::Options* options) { *options = b->build(); } @@ -181,10 +91,7 @@ void GenerateMslOptions(DataBuilder* b, writer::msl::Options* options) { } CommonFuzzer::CommonFuzzer(InputFormat input, OutputFormat output) - : input_(input), - output_(output), - transform_manager_(nullptr), - inspector_enabled_(false) {} + : input_(input), output_(output) {} CommonFuzzer::~CommonFuzzer() = default; @@ -345,7 +252,7 @@ int CommonFuzzer::Run(const uint8_t* data, size_t size) { } if (transform_manager_) { - auto out = transform_manager_->Run(&program, transform_inputs_); + auto out = transform_manager_->Run(&program, *transform_inputs_); if (!out.program.IsValid()) { // Transforms can produce error messages for bad input. // Catch ICEs and errors from non transform systems. diff --git a/fuzzers/tint_common_fuzzer.h b/fuzzers/tint_common_fuzzer.h index 96aac01ee3..975e563515 100644 --- a/fuzzers/tint_common_fuzzer.h +++ b/fuzzers/tint_common_fuzzer.h @@ -15,71 +15,20 @@ #ifndef FUZZERS_TINT_COMMON_FUZZER_H_ #define FUZZERS_TINT_COMMON_FUZZER_H_ +#include #include #include #include #include #include -#include "fuzzers/random_generator.h" #include "include/tint/tint.h" +#include "fuzzers/data_builder.h" + namespace tint { namespace fuzzers { -class DataBuilder { - public: - DataBuilder(const uint8_t* data, size_t size); - - template - T build() { - T out{}; - build(&out, sizeof(T)); - return out; - } - - std::string string(); - - template - std::vector vector() { - auto count = build(); - std::vector out(count); - for (uint8_t i = 0; i < count; i++) { - out[i] = build(); - } - return out; - } - - template - std::vector vector(T (*generate)(DataBuilder*)) { - auto count = build(); - std::vector out(count); - for (uint8_t i = 0; i < count; i++) { - out[i] = generate(this); - } - return out; - } - - template - T enum_class(uint8_t count) { - auto val = build(); - return static_cast(val % count); - } - - private: - void build(void* out, size_t n); - - RandomGenerator generator_; -}; - -void GenerateBindingRemapperInputs(DataBuilder* b, - tint::transform::DataMap* inputs); -void GenerateFirstIndexOffsetInputs(DataBuilder* b, - tint::transform::DataMap* inputs); -void GenerateSingleEntryPointInputs(DataBuilder* b, - tint::transform::DataMap* inputs); -void GenerateVertexPullingInputs(DataBuilder* b, - tint::transform::DataMap* inputs); void GenerateSpirvOptions(DataBuilder* b, writer::spirv::Options* options); void GenerateWgslOptions(DataBuilder* b, writer::wgsl::Options* options); void GenerateHlslOptions(DataBuilder* b, writer::hlsl::Options* options); @@ -94,9 +43,10 @@ class CommonFuzzer { explicit CommonFuzzer(InputFormat input, OutputFormat output); ~CommonFuzzer(); - void SetTransformManager(transform::Manager* tm, transform::DataMap inputs) { + void SetTransformManager(transform::Manager* tm, transform::DataMap* inputs) { + assert((!tm || inputs) && "DataMap must be !nullptr if Manager !nullptr"); transform_manager_ = tm; - transform_inputs_ = std::move(inputs); + transform_inputs_ = inputs; } void EnableInspector() { inspector_enabled_ = true; } @@ -137,9 +87,9 @@ class CommonFuzzer { private: InputFormat input_; OutputFormat output_; - transform::Manager* transform_manager_; - transform::DataMap transform_inputs_; - bool inspector_enabled_; + transform::Manager* transform_manager_ = nullptr; + transform::DataMap* transform_inputs_ = nullptr; + bool inspector_enabled_ = false; bool dump_input_ = false; tint::diag::List diagnostics_; diff --git a/fuzzers/tint_first_index_offset_fuzzer.cc b/fuzzers/tint_first_index_offset_fuzzer.cc index cf96e4af9d..f33529f075 100644 --- a/fuzzers/tint_first_index_offset_fuzzer.cc +++ b/fuzzers/tint_first_index_offset_fuzzer.cc @@ -12,22 +12,19 @@ // See the License for the specific language governing permissions and // limitations under the License. +#include "fuzzers/fuzzer_init.h" #include "fuzzers/tint_common_fuzzer.h" -#include "fuzzers/tint_init_fuzzer.h" +#include "fuzzers/transform_builder.h" namespace tint { namespace fuzzers { extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { - tint::transform::Manager transform_manager; - tint::transform::DataMap transform_inputs; - DataBuilder b(data, size); + TransformBuilder tb(data, size); + tb.AddTransform(); - GenerateFirstIndexOffsetInputs(&b, &transform_inputs); - transform_manager.Add(); - - tint::fuzzers::CommonFuzzer fuzzer(InputFormat::kWGSL, OutputFormat::kWGSL); - fuzzer.SetTransformManager(&transform_manager, std::move(transform_inputs)); + fuzzers::CommonFuzzer fuzzer(InputFormat::kWGSL, OutputFormat::kWGSL); + fuzzer.SetTransformManager(tb.manager(), tb.data_map()); fuzzer.SetDumpInput(GetCliParams().dump_input); return fuzzer.Run(data, size); diff --git a/fuzzers/tint_inspector_fuzzer.cc b/fuzzers/tint_inspector_fuzzer.cc index 9175ea2bd8..0fa71982ab 100644 --- a/fuzzers/tint_inspector_fuzzer.cc +++ b/fuzzers/tint_inspector_fuzzer.cc @@ -12,21 +12,21 @@ // See the License for the specific language governing permissions and // limitations under the License. +#include "fuzzers/fuzzer_init.h" #include "fuzzers/tint_common_fuzzer.h" -#include "fuzzers/tint_init_fuzzer.h" +#include "fuzzers/transform_builder.h" namespace tint { namespace fuzzers { extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { - transform::Manager transform_manager; - transform::DataMap transform_inputs; - transform_manager.Add(); + TransformBuilder tb(data, size); + tb.AddTransform(); - tint::fuzzers::CommonFuzzer fuzzer(InputFormat::kWGSL, OutputFormat::kWGSL); + fuzzers::CommonFuzzer fuzzer(InputFormat::kWGSL, OutputFormat::kWGSL); fuzzer.EnableInspector(); + fuzzer.SetTransformManager(tb.manager(), tb.data_map()); fuzzer.SetDumpInput(GetCliParams().dump_input); - fuzzer.SetTransformManager(&transform_manager, std::move(transform_inputs)); return fuzzer.Run(data, size); } diff --git a/fuzzers/tint_regex_fuzzer/fuzzer.cc b/fuzzers/tint_regex_fuzzer/fuzzer.cc index 9eef8e3341..1de67c7524 100644 --- a/fuzzers/tint_regex_fuzzer/fuzzer.cc +++ b/fuzzers/tint_regex_fuzzer/fuzzer.cc @@ -143,7 +143,7 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { CommonFuzzer fuzzer(InputFormat::kWGSL, target.output_format); fuzzer.EnableInspector(); - fuzzer.SetTransformManager(&transform_manager, std::move(transform_inputs)); + fuzzer.SetTransformManager(&transform_manager, &transform_inputs); fuzzer.Run(data, size); } diff --git a/fuzzers/tint_renamer_fuzzer.cc b/fuzzers/tint_renamer_fuzzer.cc index 7528915909..db703524fd 100644 --- a/fuzzers/tint_renamer_fuzzer.cc +++ b/fuzzers/tint_renamer_fuzzer.cc @@ -12,8 +12,8 @@ // See the License for the specific language governing permissions and // limitations under the License. +#include "fuzzers/fuzzer_init.h" #include "fuzzers/tint_common_fuzzer.h" -#include "fuzzers/tint_init_fuzzer.h" namespace tint { namespace fuzzers { diff --git a/fuzzers/tint_robustness_fuzzer.cc b/fuzzers/tint_robustness_fuzzer.cc index 3ae61211b8..e0296bb5d5 100644 --- a/fuzzers/tint_robustness_fuzzer.cc +++ b/fuzzers/tint_robustness_fuzzer.cc @@ -12,8 +12,8 @@ // See the License for the specific language governing permissions and // limitations under the License. +#include "fuzzers/fuzzer_init.h" #include "fuzzers/tint_common_fuzzer.h" -#include "fuzzers/tint_init_fuzzer.h" namespace tint { namespace fuzzers { diff --git a/fuzzers/tint_single_entry_point_fuzzer.cc b/fuzzers/tint_single_entry_point_fuzzer.cc index 988e4d217f..a226b1f41b 100644 --- a/fuzzers/tint_single_entry_point_fuzzer.cc +++ b/fuzzers/tint_single_entry_point_fuzzer.cc @@ -12,22 +12,19 @@ // See the License for the specific language governing permissions and // limitations under the License. +#include "fuzzers/fuzzer_init.h" #include "fuzzers/tint_common_fuzzer.h" -#include "fuzzers/tint_init_fuzzer.h" +#include "fuzzers/transform_builder.h" namespace tint { namespace fuzzers { extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { - tint::transform::Manager transform_manager; - tint::transform::DataMap transform_inputs; - DataBuilder b(data, size); + TransformBuilder tb(data, size); + tb.AddTransform(); - GenerateSingleEntryPointInputs(&b, &transform_inputs); - transform_manager.Add(); - - tint::fuzzers::CommonFuzzer fuzzer(InputFormat::kWGSL, OutputFormat::kWGSL); - fuzzer.SetTransformManager(&transform_manager, std::move(transform_inputs)); + fuzzers::CommonFuzzer fuzzer(InputFormat::kWGSL, OutputFormat::kWGSL); + fuzzer.SetTransformManager(tb.manager(), tb.data_map()); fuzzer.SetDumpInput(GetCliParams().dump_input); return fuzzer.Run(data, size); diff --git a/fuzzers/tint_spv_reader_fuzzer.cc b/fuzzers/tint_spv_reader_fuzzer.cc index 1eb54ea981..945b0f6f01 100644 --- a/fuzzers/tint_spv_reader_fuzzer.cc +++ b/fuzzers/tint_spv_reader_fuzzer.cc @@ -14,8 +14,8 @@ #include +#include "fuzzers/fuzzer_init.h" #include "fuzzers/tint_common_fuzzer.h" -#include "fuzzers/tint_init_fuzzer.h" namespace tint { namespace fuzzers { diff --git a/fuzzers/tint_spv_reader_hlsl_writer_fuzzer.cc b/fuzzers/tint_spv_reader_hlsl_writer_fuzzer.cc index 505e8e1a62..5af7f9d085 100644 --- a/fuzzers/tint_spv_reader_hlsl_writer_fuzzer.cc +++ b/fuzzers/tint_spv_reader_hlsl_writer_fuzzer.cc @@ -14,8 +14,8 @@ #include +#include "fuzzers/fuzzer_init.h" #include "fuzzers/tint_common_fuzzer.h" -#include "fuzzers/tint_init_fuzzer.h" namespace tint { namespace fuzzers { diff --git a/fuzzers/tint_spv_reader_msl_writer_fuzzer.cc b/fuzzers/tint_spv_reader_msl_writer_fuzzer.cc index 6117d01fc7..ed2ca584f4 100644 --- a/fuzzers/tint_spv_reader_msl_writer_fuzzer.cc +++ b/fuzzers/tint_spv_reader_msl_writer_fuzzer.cc @@ -14,8 +14,8 @@ #include +#include "fuzzers/fuzzer_init.h" #include "fuzzers/tint_common_fuzzer.h" -#include "fuzzers/tint_init_fuzzer.h" namespace tint { namespace fuzzers { diff --git a/fuzzers/tint_spv_reader_spv_writer_fuzzer.cc b/fuzzers/tint_spv_reader_spv_writer_fuzzer.cc index 3d1a5c56ba..c3a03a4fbc 100644 --- a/fuzzers/tint_spv_reader_spv_writer_fuzzer.cc +++ b/fuzzers/tint_spv_reader_spv_writer_fuzzer.cc @@ -14,8 +14,8 @@ #include +#include "fuzzers/fuzzer_init.h" #include "fuzzers/tint_common_fuzzer.h" -#include "fuzzers/tint_init_fuzzer.h" namespace tint { namespace fuzzers { diff --git a/fuzzers/tint_spv_reader_wgsl_writer_fuzzer.cc b/fuzzers/tint_spv_reader_wgsl_writer_fuzzer.cc index d3883f8028..3de88f5b64 100644 --- a/fuzzers/tint_spv_reader_wgsl_writer_fuzzer.cc +++ b/fuzzers/tint_spv_reader_wgsl_writer_fuzzer.cc @@ -14,8 +14,8 @@ #include +#include "fuzzers/fuzzer_init.h" #include "fuzzers/tint_common_fuzzer.h" -#include "fuzzers/tint_init_fuzzer.h" namespace tint { namespace fuzzers { diff --git a/fuzzers/tint_vertex_pulling_fuzzer.cc b/fuzzers/tint_vertex_pulling_fuzzer.cc index a4f33a4a9e..ff6182baea 100644 --- a/fuzzers/tint_vertex_pulling_fuzzer.cc +++ b/fuzzers/tint_vertex_pulling_fuzzer.cc @@ -12,22 +12,19 @@ // See the License for the specific language governing permissions and // limitations under the License. +#include "fuzzers/fuzzer_init.h" #include "fuzzers/tint_common_fuzzer.h" -#include "fuzzers/tint_init_fuzzer.h" +#include "fuzzers/transform_builder.h" namespace tint { namespace fuzzers { extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { - tint::transform::Manager transform_manager; - tint::transform::DataMap transform_inputs; - DataBuilder b(data, size); - - GenerateVertexPullingInputs(&b, &transform_inputs); - transform_manager.Add(); + TransformBuilder tb(data, size); + tb.AddTransform(); tint::fuzzers::CommonFuzzer fuzzer(InputFormat::kWGSL, OutputFormat::kWGSL); - fuzzer.SetTransformManager(&transform_manager, std::move(transform_inputs)); + fuzzer.SetTransformManager(tb.manager(), tb.data_map()); fuzzer.SetDumpInput(GetCliParams().dump_input); return fuzzer.Run(data, size); diff --git a/fuzzers/tint_wgsl_reader_fuzzer.cc b/fuzzers/tint_wgsl_reader_fuzzer.cc index f66e54bd26..71e902680b 100644 --- a/fuzzers/tint_wgsl_reader_fuzzer.cc +++ b/fuzzers/tint_wgsl_reader_fuzzer.cc @@ -14,8 +14,8 @@ #include +#include "fuzzers/fuzzer_init.h" #include "fuzzers/tint_common_fuzzer.h" -#include "fuzzers/tint_init_fuzzer.h" namespace tint { namespace fuzzers { diff --git a/fuzzers/tint_wgsl_reader_hlsl_writer_fuzzer.cc b/fuzzers/tint_wgsl_reader_hlsl_writer_fuzzer.cc index 0465b7a972..b9974c77cd 100644 --- a/fuzzers/tint_wgsl_reader_hlsl_writer_fuzzer.cc +++ b/fuzzers/tint_wgsl_reader_hlsl_writer_fuzzer.cc @@ -14,8 +14,8 @@ #include +#include "fuzzers/fuzzer_init.h" #include "fuzzers/tint_common_fuzzer.h" -#include "fuzzers/tint_init_fuzzer.h" namespace tint { namespace fuzzers { diff --git a/fuzzers/tint_wgsl_reader_msl_writer_fuzzer.cc b/fuzzers/tint_wgsl_reader_msl_writer_fuzzer.cc index e075a30a81..dd75513155 100644 --- a/fuzzers/tint_wgsl_reader_msl_writer_fuzzer.cc +++ b/fuzzers/tint_wgsl_reader_msl_writer_fuzzer.cc @@ -14,8 +14,8 @@ #include +#include "fuzzers/fuzzer_init.h" #include "fuzzers/tint_common_fuzzer.h" -#include "fuzzers/tint_init_fuzzer.h" namespace tint { namespace fuzzers { diff --git a/fuzzers/tint_wgsl_reader_spv_writer_fuzzer.cc b/fuzzers/tint_wgsl_reader_spv_writer_fuzzer.cc index 74985c6cb3..14275ee1e5 100644 --- a/fuzzers/tint_wgsl_reader_spv_writer_fuzzer.cc +++ b/fuzzers/tint_wgsl_reader_spv_writer_fuzzer.cc @@ -14,8 +14,8 @@ #include +#include "fuzzers/fuzzer_init.h" #include "fuzzers/tint_common_fuzzer.h" -#include "fuzzers/tint_init_fuzzer.h" namespace tint { namespace fuzzers { diff --git a/fuzzers/tint_wgsl_reader_wgsl_writer_fuzzer.cc b/fuzzers/tint_wgsl_reader_wgsl_writer_fuzzer.cc index bbdb5ba040..daf60e69be 100644 --- a/fuzzers/tint_wgsl_reader_wgsl_writer_fuzzer.cc +++ b/fuzzers/tint_wgsl_reader_wgsl_writer_fuzzer.cc @@ -14,8 +14,8 @@ #include +#include "fuzzers/fuzzer_init.h" #include "fuzzers/tint_common_fuzzer.h" -#include "fuzzers/tint_init_fuzzer.h" namespace tint { namespace fuzzers { diff --git a/fuzzers/transform_builder.h b/fuzzers/transform_builder.h new file mode 100644 index 0000000000..280c762c02 --- /dev/null +++ b/fuzzers/transform_builder.h @@ -0,0 +1,206 @@ +// Copyright 2021 The Tint Authors. +// +// 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 FUZZERS_TRANSFORM_BUILDER_H_ +#define FUZZERS_TRANSFORM_BUILDER_H_ + +#include +#include + +#include "include/tint/tint.h" + +#include "fuzzers/data_builder.h" + +namespace tint { +namespace fuzzers { + +/// Fuzzer utility class to build inputs for transforms and setup the transform +/// manager. +class TransformBuilder { + public: + /// @brief Initialize the data source using a data buffer as a seed + /// @param data - pointer to a data buffer to use as a seed + /// @param size - size of data buffer + explicit TransformBuilder(const uint8_t* data, size_t size) + : builder_(data, size) {} + ~TransformBuilder() {} + + transform::Manager* manager() { return &manager_; } + transform::DataMap* data_map() { return &data_map_; } + DataBuilder* builder() { return &builder_; } + + /// Adds a transform and needed data to |manager_| and |data_map_|. + /// @tparam T - A class that inherits from transform::Transform and has an + /// explicit specialization in AddTransformImpl. + template + void AddTransform() { + static_assert(std::is_base_of::value, + "T is not a transform::Transform"); + AddTransformImpl::impl(this); + } + + /// Helper that invokes Add*Transform for all of the platform independent + /// passes. + void AddPlatformIndependentPasses() { + AddTransform(); + AddTransform(); + AddTransform(); + AddTransform(); + AddTransform(); + AddTransform(); + } + + private: + DataBuilder builder_; + transform::Manager manager_; + transform::DataMap data_map_; + + /// Implementation of AddTransform, specialized for each transform that is + /// implemented. Default implementation intentionally deleted to cause compile + /// error if unimplemented type passed in. + /// @tparam T - A fuzzer transform + template + struct AddTransformImpl; + + /// Implementation of AddTransform for transform::Robustness + template <> + struct AddTransformImpl { + /// Add instance of transform::Robustness to TransformBuilder + /// @param tb - TransformBuilder to add transform to + static void impl(TransformBuilder* tb) { + tb->manager()->Add(); + } + }; + + /// Implementation of AddTransform for transform::FirstIndexOffset + template <> + struct AddTransformImpl { + /// Add instance of transform::FirstIndexOffset to TransformBuilder + /// @param tb - TransformBuilder to add transform to + static void impl(TransformBuilder* tb) { + struct Config { + uint32_t group; + uint32_t binding; + }; + + Config config = tb->builder()->build(); + + tb->data_map()->Add( + config.binding, config.group); + tb->manager()->Add(); + } + }; + + /// Implementation of AddTransform for transform::BindingRemapper + template <> + struct AddTransformImpl { + /// Add instance of transform::BindingRemapper to TransformBuilder + /// @param tb - TransformBuilder to add transform to + static void impl(TransformBuilder* tb) { + struct Config { + uint8_t old_group; + uint8_t old_binding; + uint8_t new_group; + uint8_t new_binding; + ast::Access new_access; + }; + + std::vector configs = tb->builder()->vector(); + transform::BindingRemapper::BindingPoints binding_points; + transform::BindingRemapper::AccessControls accesses; + for (const auto& config : configs) { + binding_points[{config.old_binding, config.old_group}] = { + config.new_binding, config.new_group}; + accesses[{config.old_binding, config.old_group}] = config.new_access; + } + + tb->data_map()->Add( + binding_points, accesses, tb->builder()->build()); + tb->manager()->Add(); + } + }; + + /// Implementation of AddTransform for transform::Renamer + template <> + struct AddTransformImpl { + /// Add instance of transform::Renamer to TransformBuilder + /// @param tb - TransformBuilder to add transform to + static void impl(TransformBuilder* tb) { + tb->manager()->Add(); + } + }; + + /// Implementation of AddTransform for transform::SingleEntryPoint + template <> + struct AddTransformImpl { + /// Add instance of transform::SingleEntryPoint to TransformBuilder + /// @param tb - TransformBuilder to add transform to + static void impl(TransformBuilder* tb) { + auto input = tb->builder()->build(); + transform::SingleEntryPoint::Config cfg(input); + + tb->data_map()->Add(cfg); + tb->manager()->Add(); + } + }; // struct AddTransformImpl + + /// Implementation of AddTransform for transform::VertexPulling + template <> + struct AddTransformImpl { + /// Add instance of transform::VertexPulling to TransformBuilder + /// @param tb - TransformBuilder to add transform to + static void impl(TransformBuilder* tb) { + transform::VertexPulling::Config cfg; + cfg.entry_point_name = tb->builder()->build(); + cfg.vertex_state = + tb->builder()->vector( + GenerateVertexBufferLayoutDescriptor); + cfg.pulling_group = tb->builder()->build(); + + tb->data_map()->Add(cfg); + tb->manager()->Add(); + } + + private: + /// Generate an instance of transform::VertexAttributeDescriptor + /// @param b - DataBuilder to use + static transform::VertexAttributeDescriptor + GenerateVertexAttributeDescriptor(DataBuilder* b) { + transform::VertexAttributeDescriptor desc{}; + desc.format = b->enum_class( + static_cast(transform::VertexFormat::kLastEntry) + 1); + desc.offset = b->build(); + desc.shader_location = b->build(); + return desc; + } + + /// Generate an instance of VertexBufferLayoutDescriptor + /// @param b - DataBuilder to use + static transform::VertexBufferLayoutDescriptor + GenerateVertexBufferLayoutDescriptor(DataBuilder* b) { + transform::VertexBufferLayoutDescriptor desc; + desc.array_stride = b->build(); + desc.step_mode = b->enum_class( + static_cast(transform::VertexStepMode::kLastEntry) + 1); + desc.attributes = b->vector( + GenerateVertexAttributeDescriptor); + return desc; + } + }; +}; // class TransformBuilder + +} // namespace fuzzers +} // namespace tint + +#endif // FUZZERS_TRANSFORM_BUILDER_H_