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 <rharrison@chromium.org>
Kokoro: Kokoro <noreply+kokoro@google.com>
Commit-Queue: Ryan Harrison <rharrison@chromium.org>
Reviewed-by: Antonio Maiorano <amaiorano@google.com>
diff --git a/fuzzers/BUILD.gn b/fuzzers/BUILD.gn
index 0084407..acb510b 100644
--- a/fuzzers/BUILD.gn
+++ b/fuzzers/BUILD.gn
@@ -66,10 +66,12 @@
]
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 @@
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 f50ec56..0c8b1ca 100644
--- a/fuzzers/CMakeLists.txt
+++ b/fuzzers/CMakeLists.txt
@@ -17,12 +17,14 @@
${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 0000000..b6ec22f
--- /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 <cassert>
+#include <functional>
+#include <string>
+#include <vector>
+
+#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 <typename T>
+ T build() {
+ return BuildImpl<T>::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<T>
+ template <typename T>
+ std::vector<T> vector() {
+ auto count = build<uint8_t>();
+ std::vector<T> out(count);
+ for (uint8_t i = 0; i < count; i++) {
+ out[i] = build<T>();
+ }
+ 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<T>
+ template <typename T, typename Callback>
+ std::vector<T> vector(Callback generate) {
+ auto count = build<uint8_t>();
+ std::vector<T> 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 <typename T>
+ T enum_class(uint32_t count) {
+ return static_cast<T>(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<uint8_t*>(out), n);
+ }
+
+ /// Implementation of ::build<T>()
+ /// @tparam T - type of data to produce
+ template <typename T>
+ 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<std::string> {
+ /// 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<uint8_t>();
+ if (count == 0) {
+ return "";
+ }
+ std::vector<uint8_t> source(count);
+ b->build(source.data(), count);
+ return std::string(source.begin(), source.end());
+ }
+ };
+
+ /// Specialization for bool
+ template <>
+ struct BuildImpl<bool> {
+ /// 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 95%
rename from fuzzers/tint_init_fuzzer.cc
rename to fuzzers/fuzzer_init.cc
index b8e38cd..f651713 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 87%
rename from fuzzers/tint_init_fuzzer.h
rename to fuzzers/fuzzer_init.h
index 278ab5b..fa96ce5 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 @@
} // 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 20b04db..a485b0e 100644
--- a/fuzzers/random_generator.cc
+++ b/fuzzers/random_generator.cc
@@ -58,6 +58,9 @@
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 1879045..4fe6acc 100644
--- a/fuzzers/random_generator.h
+++ b/fuzzers/random_generator.h
@@ -27,6 +27,12 @@
/// @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 083ee28..88b6c82 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<transform::Robustness>();
- config->manager.Add<transform::FirstIndexOffset>();
- config->manager.Add<transform::BindingRemapper>();
- config->manager.Add<transform::Renamer>();
- config->manager.Add<tint::transform::SingleEntryPoint>();
- config->manager.Add<tint::transform::VertexPulling>();
-}
-
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 @@
#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 @@
#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 @@
#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 cdb1693..ca60cf8 100644
--- a/fuzzers/tint_ast_fuzzer/fuzzer.cc
+++ b/fuzzers/tint_ast_fuzzer/fuzzer.cc
@@ -115,7 +115,7 @@
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 c701078..4deb2d8 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<tint::transform::BindingRemapper>();
+ TransformBuilder tb(data, size);
+ tb.AddTransform<transform::BindingRemapper>();
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 f15c733..ac4de23 100644
--- a/fuzzers/tint_common_fuzzer.cc
+++ b/fuzzers/tint_common_fuzzer.cc
@@ -52,26 +52,6 @@
FatalError(diagnostics);
}
-transform::VertexAttributeDescriptor GenerateVertexAttributeDescriptor(
- DataBuilder* b) {
- transform::VertexAttributeDescriptor desc{};
- desc.format = b->enum_class<transform::VertexFormat>(
- static_cast<uint8_t>(transform::VertexFormat::kLastEntry) + 1);
- desc.offset = b->build<uint32_t>();
- desc.shader_location = b->build<uint32_t>();
- return desc;
-}
-
-transform::VertexBufferLayoutDescriptor GenerateVertexBufferLayoutDescriptor(
- DataBuilder* b) {
- transform::VertexBufferLayoutDescriptor desc;
- desc.array_stride = b->build<uint32_t>();
- desc.step_mode = b->enum_class<transform::VertexStepMode>(
- static_cast<uint8_t>(transform::VertexStepMode::kLastEntry) + 1);
- desc.attributes = b->vector(GenerateVertexAttributeDescriptor);
- return desc;
-}
-
bool SPIRVToolsValidationCheck(const tint::Program& program,
const std::vector<uint32_t>& spirv) {
spvtools::SpirvTools tools(SPV_ENV_VULKAN_1_1);
@@ -94,76 +74,6 @@
} // namespace
-DataBuilder::DataBuilder(const uint8_t* data, size_t size)
- : generator_(RandomGenerator::CalculateSeed(data, size)) {}
-
-std::string DataBuilder::string() {
- auto count = build<uint8_t>();
- if (count == 0) {
- return "";
- }
- std::vector<uint8_t> 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<uint8_t*>(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<Config> configs = b->vector<Config>();
- 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<transform::BindingRemapper::Remappings>(binding_points, accesses);
-}
-
-void GenerateFirstIndexOffsetInputs(DataBuilder* b,
- tint::transform::DataMap* inputs) {
- struct Config {
- uint32_t group;
- uint32_t binding;
- };
-
- Config config = b->build<Config>();
- inputs->Add<tint::transform::FirstIndexOffset::BindingPoint>(config.binding,
- config.group);
-}
-
-void GenerateSingleEntryPointInputs(DataBuilder* b,
- tint::transform::DataMap* inputs) {
- std::string input = b->string();
- transform::SingleEntryPoint::Config cfg(input);
- inputs->Add<transform::SingleEntryPoint::Config>(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<uint32_t>();
- inputs->Add<transform::VertexPulling::Config>(cfg);
-}
-
void GenerateSpirvOptions(DataBuilder* b, writer::spirv::Options* options) {
*options = b->build<writer::spirv::Options>();
}
@@ -181,10 +91,7 @@
}
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 @@
}
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 96aac01..975e563 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 <cassert>
#include <cstring>
#include <memory>
#include <string>
#include <utility>
#include <vector>
-#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 <typename T>
- T build() {
- T out{};
- build(&out, sizeof(T));
- return out;
- }
-
- std::string string();
-
- template <typename T>
- std::vector<T> vector() {
- auto count = build<uint8_t>();
- std::vector<T> out(count);
- for (uint8_t i = 0; i < count; i++) {
- out[i] = build<T>();
- }
- return out;
- }
-
- template <typename T>
- std::vector<T> vector(T (*generate)(DataBuilder*)) {
- auto count = build<uint8_t>();
- std::vector<T> out(count);
- for (uint8_t i = 0; i < count; i++) {
- out[i] = generate(this);
- }
- return out;
- }
-
- template <typename T>
- T enum_class(uint8_t count) {
- auto val = build<uint8_t>();
- return static_cast<T>(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 @@
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 @@
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 cf96e4a..f33529f 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<transform::FirstIndexOffset>();
- GenerateFirstIndexOffsetInputs(&b, &transform_inputs);
- transform_manager.Add<tint::transform::FirstIndexOffset>();
-
- 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 9175ea2..0fa7198 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<transform::Robustness>();
+ TransformBuilder tb(data, size);
+ tb.AddTransform<transform::Robustness>();
- 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 9eef8e3..1de67c7 100644
--- a/fuzzers/tint_regex_fuzzer/fuzzer.cc
+++ b/fuzzers/tint_regex_fuzzer/fuzzer.cc
@@ -143,7 +143,7 @@
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 7528915..db70352 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 3ae6121..e0296bb 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 988e4d2..a226b1f 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<transform::SingleEntryPoint>();
- GenerateSingleEntryPointInputs(&b, &transform_inputs);
- transform_manager.Add<tint::transform::SingleEntryPoint>();
-
- 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 1eb54ea..945b0f6 100644
--- a/fuzzers/tint_spv_reader_fuzzer.cc
+++ b/fuzzers/tint_spv_reader_fuzzer.cc
@@ -14,8 +14,8 @@
#include <vector>
+#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 505e8e1..5af7f9d 100644
--- a/fuzzers/tint_spv_reader_hlsl_writer_fuzzer.cc
+++ b/fuzzers/tint_spv_reader_hlsl_writer_fuzzer.cc
@@ -14,8 +14,8 @@
#include <vector>
+#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 6117d01..ed2ca58 100644
--- a/fuzzers/tint_spv_reader_msl_writer_fuzzer.cc
+++ b/fuzzers/tint_spv_reader_msl_writer_fuzzer.cc
@@ -14,8 +14,8 @@
#include <vector>
+#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 3d1a5c5..c3a03a4 100644
--- a/fuzzers/tint_spv_reader_spv_writer_fuzzer.cc
+++ b/fuzzers/tint_spv_reader_spv_writer_fuzzer.cc
@@ -14,8 +14,8 @@
#include <vector>
+#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 d3883f8..3de88f5 100644
--- a/fuzzers/tint_spv_reader_wgsl_writer_fuzzer.cc
+++ b/fuzzers/tint_spv_reader_wgsl_writer_fuzzer.cc
@@ -14,8 +14,8 @@
#include <vector>
+#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 a4f33a4..ff6182b 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<tint::transform::VertexPulling>();
+ TransformBuilder tb(data, size);
+ tb.AddTransform<transform::VertexPulling>();
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 f66e54b..71e9026 100644
--- a/fuzzers/tint_wgsl_reader_fuzzer.cc
+++ b/fuzzers/tint_wgsl_reader_fuzzer.cc
@@ -14,8 +14,8 @@
#include <string>
+#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 0465b7a..b9974c7 100644
--- a/fuzzers/tint_wgsl_reader_hlsl_writer_fuzzer.cc
+++ b/fuzzers/tint_wgsl_reader_hlsl_writer_fuzzer.cc
@@ -14,8 +14,8 @@
#include <string>
+#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 e075a30..dd75513 100644
--- a/fuzzers/tint_wgsl_reader_msl_writer_fuzzer.cc
+++ b/fuzzers/tint_wgsl_reader_msl_writer_fuzzer.cc
@@ -14,8 +14,8 @@
#include <string>
+#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 74985c6..14275ee 100644
--- a/fuzzers/tint_wgsl_reader_spv_writer_fuzzer.cc
+++ b/fuzzers/tint_wgsl_reader_spv_writer_fuzzer.cc
@@ -14,8 +14,8 @@
#include <string>
+#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 bbdb5ba..daf60e6 100644
--- a/fuzzers/tint_wgsl_reader_wgsl_writer_fuzzer.cc
+++ b/fuzzers/tint_wgsl_reader_wgsl_writer_fuzzer.cc
@@ -14,8 +14,8 @@
#include <string>
+#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 0000000..280c762
--- /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 <string>
+#include <vector>
+
+#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 <typename T>
+ void AddTransform() {
+ static_assert(std::is_base_of<transform::Transform, T>::value,
+ "T is not a transform::Transform");
+ AddTransformImpl<T>::impl(this);
+ }
+
+ /// Helper that invokes Add*Transform for all of the platform independent
+ /// passes.
+ void AddPlatformIndependentPasses() {
+ AddTransform<transform::Robustness>();
+ AddTransform<transform::FirstIndexOffset>();
+ AddTransform<transform::BindingRemapper>();
+ AddTransform<transform::Renamer>();
+ AddTransform<transform::SingleEntryPoint>();
+ AddTransform<transform::VertexPulling>();
+ }
+
+ 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 <typename T>
+ struct AddTransformImpl;
+
+ /// Implementation of AddTransform for transform::Robustness
+ template <>
+ struct AddTransformImpl<transform::Robustness> {
+ /// Add instance of transform::Robustness to TransformBuilder
+ /// @param tb - TransformBuilder to add transform to
+ static void impl(TransformBuilder* tb) {
+ tb->manager()->Add<transform::Robustness>();
+ }
+ };
+
+ /// Implementation of AddTransform for transform::FirstIndexOffset
+ template <>
+ struct AddTransformImpl<transform::FirstIndexOffset> {
+ /// 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<Config>();
+
+ tb->data_map()->Add<tint::transform::FirstIndexOffset::BindingPoint>(
+ config.binding, config.group);
+ tb->manager()->Add<transform::FirstIndexOffset>();
+ }
+ };
+
+ /// Implementation of AddTransform for transform::BindingRemapper
+ template <>
+ struct AddTransformImpl<transform::BindingRemapper> {
+ /// 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<Config> configs = tb->builder()->vector<Config>();
+ 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<transform::BindingRemapper::Remappings>(
+ binding_points, accesses, tb->builder()->build<bool>());
+ tb->manager()->Add<transform::BindingRemapper>();
+ }
+ };
+
+ /// Implementation of AddTransform for transform::Renamer
+ template <>
+ struct AddTransformImpl<transform::Renamer> {
+ /// Add instance of transform::Renamer to TransformBuilder
+ /// @param tb - TransformBuilder to add transform to
+ static void impl(TransformBuilder* tb) {
+ tb->manager()->Add<transform::Renamer>();
+ }
+ };
+
+ /// Implementation of AddTransform for transform::SingleEntryPoint
+ template <>
+ struct AddTransformImpl<transform::SingleEntryPoint> {
+ /// Add instance of transform::SingleEntryPoint to TransformBuilder
+ /// @param tb - TransformBuilder to add transform to
+ static void impl(TransformBuilder* tb) {
+ auto input = tb->builder()->build<std::string>();
+ transform::SingleEntryPoint::Config cfg(input);
+
+ tb->data_map()->Add<transform::SingleEntryPoint::Config>(cfg);
+ tb->manager()->Add<transform::SingleEntryPoint>();
+ }
+ }; // struct AddTransformImpl<transform::SingleEntryPoint>
+
+ /// Implementation of AddTransform for transform::VertexPulling
+ template <>
+ struct AddTransformImpl<transform::VertexPulling> {
+ /// 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<std::string>();
+ cfg.vertex_state =
+ tb->builder()->vector<transform::VertexBufferLayoutDescriptor>(
+ GenerateVertexBufferLayoutDescriptor);
+ cfg.pulling_group = tb->builder()->build<uint32_t>();
+
+ tb->data_map()->Add<transform::VertexPulling::Config>(cfg);
+ tb->manager()->Add<transform::VertexPulling>();
+ }
+
+ 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<transform::VertexFormat>(
+ static_cast<uint8_t>(transform::VertexFormat::kLastEntry) + 1);
+ desc.offset = b->build<uint32_t>();
+ desc.shader_location = b->build<uint32_t>();
+ 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<uint32_t>();
+ desc.step_mode = b->enum_class<transform::VertexStepMode>(
+ static_cast<uint8_t>(transform::VertexStepMode::kLastEntry) + 1);
+ desc.attributes = b->vector<transform::VertexAttributeDescriptor>(
+ GenerateVertexAttributeDescriptor);
+ return desc;
+ }
+ };
+}; // class TransformBuilder
+
+} // namespace fuzzers
+} // namespace tint
+
+#endif // FUZZERS_TRANSFORM_BUILDER_H_