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>
This commit is contained in:
parent
0e193ac03e
commit
c57642cbd5
|
@ -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) {
|
||||
|
|
|
@ -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})
|
||||
|
|
|
@ -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_
|
|
@ -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 {
|
|
@ -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_
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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 @@ 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);
|
||||
|
|
|
@ -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()) {
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -52,26 +52,6 @@ namespace {
|
|||
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 @@ 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<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 @@ 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.
|
||||
|
|
|
@ -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 @@ 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_;
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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_
|
Loading…
Reference in New Issue