Convert fuzzer to generating configuration data
This is instead of consuming a portion of the input, so that the seed corpus of valid shaders can be more effective. BUG=tint:1098 Change-Id: If3696527c82c23b09edeea6ddd2a0f935e5e1ac7 Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/63301 Auto-Submit: Ryan Harrison <rharrison@chromium.org> Commit-Queue: Ben Clayton <bclayton@google.com> Kokoro: Kokoro <noreply+kokoro@google.com> Reviewed-by: Ben Clayton <bclayton@google.com>
This commit is contained in:
parent
28d6763ef8
commit
a617d0f0fc
|
@ -99,6 +99,8 @@ if (${TINT_BUILD_WGSL_READER}
|
||||||
AND ${TINT_BUILD_SPV_WRITER}
|
AND ${TINT_BUILD_SPV_WRITER}
|
||||||
AND ${TINT_BUILD_WGSL_WRITER})
|
AND ${TINT_BUILD_WGSL_WRITER})
|
||||||
add_executable(tint_black_box_fuzz_target
|
add_executable(tint_black_box_fuzz_target
|
||||||
|
random_generator.cc
|
||||||
|
random_generator.h
|
||||||
tint_black_box_fuzz_target
|
tint_black_box_fuzz_target
|
||||||
tint_common_fuzzer.cc
|
tint_common_fuzzer.cc
|
||||||
tint_common_fuzzer.h
|
tint_common_fuzzer.h
|
||||||
|
|
|
@ -18,6 +18,8 @@
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
#include "src/utils/hash.h"
|
||||||
|
|
||||||
namespace tint {
|
namespace tint {
|
||||||
namespace fuzzers {
|
namespace fuzzers {
|
||||||
|
|
||||||
|
@ -38,7 +40,7 @@ I RandomUInt(std::mt19937* engine, I lower, I upper) {
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
RandomGenerator::RandomGenerator(uint32_t seed) : engine_(seed) {}
|
RandomGenerator::RandomGenerator(uint64_t seed) : engine_(seed) {}
|
||||||
|
|
||||||
uint32_t RandomGenerator::GetUInt32(uint32_t lower, uint32_t upper) {
|
uint32_t RandomGenerator::GetUInt32(uint32_t lower, uint32_t upper) {
|
||||||
return RandomUInt(&engine_, lower, upper);
|
return RandomUInt(&engine_, lower, upper);
|
||||||
|
@ -66,12 +68,11 @@ uint32_t RandomGenerator::Get4Bytes() {
|
||||||
return std::independent_bits_engine<std::mt19937, 32, uint32_t>(engine_)();
|
return std::independent_bits_engine<std::mt19937, 32, uint32_t>(engine_)();
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<uint8_t> RandomGenerator::GetNBytes(size_t n) {
|
void RandomGenerator::GetNBytes(uint8_t* dest, size_t n) {
|
||||||
std::vector<uint8_t> result(n);
|
assert(dest && "|dest| must not be nullptr");
|
||||||
std::generate(
|
std::generate(
|
||||||
std::begin(result), std::end(result),
|
dest, dest + n,
|
||||||
std::independent_bits_engine<std::mt19937, 8, uint8_t>(engine_));
|
std::independent_bits_engine<std::mt19937, 8, uint8_t>(engine_));
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool RandomGenerator::GetBool() {
|
bool RandomGenerator::GetBool() {
|
||||||
|
@ -85,5 +86,31 @@ bool RandomGenerator::GetWeightedBool(uint32_t percentage) {
|
||||||
return RandomUInt(&engine_, 0u, kMaxPercentage) < percentage;
|
return RandomUInt(&engine_, 0u, kMaxPercentage) < percentage;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint64_t RandomGenerator::CalculateSeed(const uint8_t* data, size_t size) {
|
||||||
|
assert(data != nullptr && "|data| must be !nullptr");
|
||||||
|
assert(size > 0 && "|size| must be > 0");
|
||||||
|
|
||||||
|
// Number of bytes we want to skip at the start of data for the hash.
|
||||||
|
// Fewer bytes may be skipped when `size` is small.
|
||||||
|
// Has lower precedence than kHashDesiredMinBytes.
|
||||||
|
static const int64_t kHashDesiredLeadingSkipBytes = 5;
|
||||||
|
// Minimum number of bytes we want to use in the hash.
|
||||||
|
// Used for short buffers.
|
||||||
|
static const int64_t kHashDesiredMinBytes = 4;
|
||||||
|
// Maximum number of bytes we want to use in the hash.
|
||||||
|
static const int64_t kHashDesiredMaxBytes = 32;
|
||||||
|
int64_t size_i64 = static_cast<int64_t>(size);
|
||||||
|
int64_t hash_begin_i64 =
|
||||||
|
std::min(kHashDesiredLeadingSkipBytes,
|
||||||
|
std::max<int64_t>(size_i64 - kHashDesiredMinBytes, 0));
|
||||||
|
int64_t hash_end_i64 =
|
||||||
|
std::max(hash_begin_i64 + kHashDesiredMaxBytes, size_i64);
|
||||||
|
size_t hash_begin = static_cast<size_t>(hash_begin_i64);
|
||||||
|
size_t hash_size = static_cast<size_t>(hash_end_i64) - hash_begin;
|
||||||
|
std::vector<uint8_t> hash_portion(data + hash_begin,
|
||||||
|
data + hash_begin + hash_size + 1);
|
||||||
|
return tint::utils::Hash(hash_portion);
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace fuzzers
|
} // namespace fuzzers
|
||||||
} // namespace tint
|
} // namespace tint
|
||||||
|
|
|
@ -26,7 +26,7 @@ class RandomGenerator {
|
||||||
public:
|
public:
|
||||||
/// @brief Initializes the internal engine
|
/// @brief Initializes the internal engine
|
||||||
/// @param seed - seed value passed to engine
|
/// @param seed - seed value passed to engine
|
||||||
explicit RandomGenerator(uint32_t seed);
|
explicit RandomGenerator(uint64_t seed);
|
||||||
~RandomGenerator() {}
|
~RandomGenerator() {}
|
||||||
|
|
||||||
/// Get uint32_t value from uniform distribution.
|
/// Get uint32_t value from uniform distribution.
|
||||||
|
@ -62,9 +62,9 @@ class RandomGenerator {
|
||||||
uint32_t Get4Bytes();
|
uint32_t Get4Bytes();
|
||||||
|
|
||||||
/// Get N bytes of pseudo-random data
|
/// Get N bytes of pseudo-random data
|
||||||
|
/// @param dest - memory location to store data
|
||||||
/// @param n - number of bytes of data to generate
|
/// @param n - number of bytes of data to generate
|
||||||
/// @returns |N|-bytes of random data as vector
|
void GetNBytes(uint8_t* dest, size_t n);
|
||||||
std::vector<uint8_t> GetNBytes(size_t n);
|
|
||||||
|
|
||||||
/// Get random bool with even odds
|
/// Get random bool with even odds
|
||||||
/// @returns true 50% of the time and false %50 of time.
|
/// @returns true 50% of the time and false %50 of time.
|
||||||
|
@ -76,6 +76,13 @@ class RandomGenerator {
|
||||||
/// of the time.
|
/// of the time.
|
||||||
bool GetWeightedBool(uint32_t percentage);
|
bool GetWeightedBool(uint32_t percentage);
|
||||||
|
|
||||||
|
/// Calculate a seed value based on a blob of data.
|
||||||
|
/// Currently hashes bytes near the front of the buffer, after skipping N
|
||||||
|
/// bytes.
|
||||||
|
/// @param data - pointer to data to base calculation off of, must be !nullptr
|
||||||
|
/// @param size - number of elements in |data|, must be > 0
|
||||||
|
static uint64_t CalculateSeed(const uint8_t* data, size_t size);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::mt19937 engine_;
|
std::mt19937 engine_;
|
||||||
|
|
||||||
|
|
|
@ -12,6 +12,7 @@
|
||||||
// See the License for the specific language governing permissions and
|
// See the License for the specific language governing permissions and
|
||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
|
|
||||||
|
#include "fuzzers/random_generator.h"
|
||||||
#include "fuzzers/tint_common_fuzzer.h"
|
#include "fuzzers/tint_common_fuzzer.h"
|
||||||
#include "fuzzers/tint_init_fuzzer.h"
|
#include "fuzzers/tint_init_fuzzer.h"
|
||||||
|
|
||||||
|
@ -19,17 +20,17 @@ namespace tint {
|
||||||
namespace fuzzers {
|
namespace fuzzers {
|
||||||
|
|
||||||
struct Config {
|
struct Config {
|
||||||
Config(const uint8_t* data, size_t size) : reader(data, size) {}
|
Config(const uint8_t* data, size_t size) : builder(data, size) {}
|
||||||
Reader reader;
|
DataBuilder builder;
|
||||||
transform::Manager manager;
|
transform::Manager manager;
|
||||||
transform::DataMap inputs;
|
transform::DataMap inputs;
|
||||||
};
|
};
|
||||||
|
|
||||||
bool AddPlatformIndependentPasses(Config* config) {
|
void AddPlatformIndependentPasses(Config* config) {
|
||||||
ExtractFirstIndexOffsetInputs(&config->reader, &config->inputs);
|
GenerateFirstIndexOffsetInputs(&config->builder, &config->inputs);
|
||||||
ExtractBindingRemapperInputs(&config->reader, &config->inputs);
|
GenerateBindingRemapperInputs(&config->builder, &config->inputs);
|
||||||
ExtractSingleEntryPointInputs(&config->reader, &config->inputs);
|
GenerateSingleEntryPointInputs(&config->builder, &config->inputs);
|
||||||
ExtractVertexPullingInputs(&config->reader, &config->inputs);
|
GenerateVertexPullingInputs(&config->builder, &config->inputs);
|
||||||
|
|
||||||
config->manager.Add<transform::Robustness>();
|
config->manager.Add<transform::Robustness>();
|
||||||
config->manager.Add<transform::FirstIndexOffset>();
|
config->manager.Add<transform::FirstIndexOffset>();
|
||||||
|
@ -37,69 +38,55 @@ bool AddPlatformIndependentPasses(Config* config) {
|
||||||
config->manager.Add<transform::Renamer>();
|
config->manager.Add<transform::Renamer>();
|
||||||
config->manager.Add<tint::transform::SingleEntryPoint>();
|
config->manager.Add<tint::transform::SingleEntryPoint>();
|
||||||
config->manager.Add<tint::transform::VertexPulling>();
|
config->manager.Add<tint::transform::VertexPulling>();
|
||||||
|
|
||||||
return !config->reader.failed();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
|
extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
|
||||||
{
|
{
|
||||||
Config config(data, size);
|
Config config(data, size);
|
||||||
|
AddPlatformIndependentPasses(&config);
|
||||||
if (!AddPlatformIndependentPasses(&config)) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
fuzzers::CommonFuzzer fuzzer(InputFormat::kWGSL, OutputFormat::kSpv);
|
fuzzers::CommonFuzzer fuzzer(InputFormat::kWGSL, OutputFormat::kSpv);
|
||||||
fuzzer.SetTransformManager(&(config.manager), std::move(config.inputs));
|
fuzzer.SetTransformManager(&(config.manager), std::move(config.inputs));
|
||||||
fuzzer.SetDumpInput(GetCliParams().dump_input);
|
fuzzer.SetDumpInput(GetCliParams().dump_input);
|
||||||
|
|
||||||
fuzzer.Run(config.reader.data(), config.reader.size());
|
fuzzer.Run(data, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if TINT_BUILD_HLSL_WRITER
|
#if TINT_BUILD_HLSL_WRITER
|
||||||
{
|
{
|
||||||
Config config(data, size);
|
Config config(data, size);
|
||||||
|
AddPlatformIndependentPasses(&config);
|
||||||
if (!AddPlatformIndependentPasses(&config)) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
fuzzers::CommonFuzzer fuzzer(InputFormat::kWGSL, OutputFormat::kHLSL);
|
fuzzers::CommonFuzzer fuzzer(InputFormat::kWGSL, OutputFormat::kHLSL);
|
||||||
fuzzer.SetTransformManager(&config.manager, std::move(config.inputs));
|
fuzzer.SetTransformManager(&config.manager, std::move(config.inputs));
|
||||||
fuzzer.SetDumpInput(GetCliParams().dump_input);
|
fuzzer.SetDumpInput(GetCliParams().dump_input);
|
||||||
|
|
||||||
fuzzer.Run(config.reader.data(), config.reader.size());
|
fuzzer.Run(data, size);
|
||||||
}
|
}
|
||||||
#endif // TINT_BUILD_HLSL_WRITER
|
#endif // TINT_BUILD_HLSL_WRITER
|
||||||
|
|
||||||
#if TINT_BUILD_MSL_WRITER
|
#if TINT_BUILD_MSL_WRITER
|
||||||
{
|
{
|
||||||
Config config(data, size);
|
Config config(data, size);
|
||||||
|
AddPlatformIndependentPasses(&config);
|
||||||
if (!AddPlatformIndependentPasses(&config)) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
fuzzers::CommonFuzzer fuzzer(InputFormat::kWGSL, OutputFormat::kMSL);
|
fuzzers::CommonFuzzer fuzzer(InputFormat::kWGSL, OutputFormat::kMSL);
|
||||||
fuzzer.SetTransformManager(&config.manager, std::move(config.inputs));
|
fuzzer.SetTransformManager(&config.manager, std::move(config.inputs));
|
||||||
fuzzer.SetDumpInput(GetCliParams().dump_input);
|
fuzzer.SetDumpInput(GetCliParams().dump_input);
|
||||||
|
|
||||||
fuzzer.Run(config.reader.data(), config.reader.size());
|
fuzzer.Run(data, size);
|
||||||
}
|
}
|
||||||
#endif // TINT_BUILD_MSL_WRITER
|
#endif // TINT_BUILD_MSL_WRITER
|
||||||
#if TINT_BUILD_SPV_WRITER
|
#if TINT_BUILD_SPV_WRITER
|
||||||
{
|
{
|
||||||
Config config(data, size);
|
Config config(data, size);
|
||||||
|
AddPlatformIndependentPasses(&config);
|
||||||
if (!AddPlatformIndependentPasses(&config)) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
fuzzers::CommonFuzzer fuzzer(InputFormat::kWGSL, OutputFormat::kSpv);
|
fuzzers::CommonFuzzer fuzzer(InputFormat::kWGSL, OutputFormat::kSpv);
|
||||||
fuzzer.SetTransformManager(&config.manager, std::move(config.inputs));
|
fuzzer.SetTransformManager(&config.manager, std::move(config.inputs));
|
||||||
fuzzer.SetDumpInput(GetCliParams().dump_input);
|
fuzzer.SetDumpInput(GetCliParams().dump_input);
|
||||||
|
|
||||||
fuzzer.Run(config.reader.data(), config.reader.size());
|
fuzzer.Run(data, size);
|
||||||
}
|
}
|
||||||
#endif // TINT_BUILD_SPV_WRITER
|
#endif // TINT_BUILD_SPV_WRITER
|
||||||
|
|
||||||
|
|
|
@ -21,12 +21,9 @@ namespace fuzzers {
|
||||||
extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
|
extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
|
||||||
transform::Manager transform_manager;
|
transform::Manager transform_manager;
|
||||||
transform::DataMap transform_inputs;
|
transform::DataMap transform_inputs;
|
||||||
Reader r(data, size);
|
DataBuilder b(data, size);
|
||||||
|
|
||||||
ExtractBindingRemapperInputs(&r, &transform_inputs);
|
GenerateBindingRemapperInputs(&b, &transform_inputs);
|
||||||
if (r.failed()) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
transform_manager.Add<tint::transform::BindingRemapper>();
|
transform_manager.Add<tint::transform::BindingRemapper>();
|
||||||
|
|
||||||
|
@ -34,7 +31,7 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
|
||||||
fuzzer.SetTransformManager(&transform_manager, std::move(transform_inputs));
|
fuzzer.SetTransformManager(&transform_manager, std::move(transform_inputs));
|
||||||
fuzzer.SetDumpInput(GetCliParams().dump_input);
|
fuzzer.SetDumpInput(GetCliParams().dump_input);
|
||||||
|
|
||||||
return fuzzer.Run(r.data(), r.size());
|
return fuzzer.Run(data, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace fuzzers
|
} // namespace fuzzers
|
||||||
|
|
|
@ -47,7 +47,7 @@ bool ReadFile(const std::string& input_file, std::vector<T>* buffer) {
|
||||||
}
|
}
|
||||||
|
|
||||||
fseek(file, 0, SEEK_END);
|
fseek(file, 0, SEEK_END);
|
||||||
uint64_t tell_file_size = static_cast<uint64_t>(ftell(file));
|
auto tell_file_size = ftell(file);
|
||||||
if (tell_file_size <= 0) {
|
if (tell_file_size <= 0) {
|
||||||
std::cerr << "Input file of incorrect size: " << input_file << std::endl;
|
std::cerr << "Input file of incorrect size: " << input_file << std::endl;
|
||||||
fclose(file);
|
fclose(file);
|
||||||
|
@ -99,21 +99,21 @@ int main(int argc, const char** argv) {
|
||||||
tint::fuzzers::OutputFormat::kHLSL);
|
tint::fuzzers::OutputFormat::kHLSL);
|
||||||
return fuzzer.Run(data.data(), data.size());
|
return fuzzer.Run(data.data(), data.size());
|
||||||
} else if (target_format == "msl") {
|
} else if (target_format == "msl") {
|
||||||
tint::fuzzers::Reader reader(data.data(), data.size());
|
tint::fuzzers::DataBuilder builder(data.data(), data.size());
|
||||||
tint::writer::msl::Options options;
|
tint::writer::msl::Options options;
|
||||||
ExtractMslOptions(&reader, &options);
|
GenerateMslOptions(&builder, &options);
|
||||||
tint::fuzzers::CommonFuzzer fuzzer(tint::fuzzers::InputFormat::kWGSL,
|
tint::fuzzers::CommonFuzzer fuzzer(tint::fuzzers::InputFormat::kWGSL,
|
||||||
tint::fuzzers::OutputFormat::kMSL);
|
tint::fuzzers::OutputFormat::kMSL);
|
||||||
fuzzer.SetOptionsMsl(options);
|
fuzzer.SetOptionsMsl(options);
|
||||||
return fuzzer.Run(reader.data(), reader.size());
|
return fuzzer.Run(data.data(), data.size());
|
||||||
} else if (target_format == "spv") {
|
} else if (target_format == "spv") {
|
||||||
tint::fuzzers::Reader reader(data.data(), data.size());
|
tint::fuzzers::DataBuilder builder(data.data(), data.size());
|
||||||
tint::writer::spirv::Options options;
|
tint::writer::spirv::Options options;
|
||||||
ExtractSpirvOptions(&reader, &options);
|
GenerateSpirvOptions(&builder, &options);
|
||||||
tint::fuzzers::CommonFuzzer fuzzer(tint::fuzzers::InputFormat::kWGSL,
|
tint::fuzzers::CommonFuzzer fuzzer(tint::fuzzers::InputFormat::kWGSL,
|
||||||
tint::fuzzers::OutputFormat::kSpv);
|
tint::fuzzers::OutputFormat::kSpv);
|
||||||
fuzzer.SetOptionsSpirv(options);
|
fuzzer.SetOptionsSpirv(options);
|
||||||
return fuzzer.Run(reader.data(), reader.size());
|
return fuzzer.Run(data.data(), data.size());
|
||||||
} else if (target_format == "wgsl") {
|
} else if (target_format == "wgsl") {
|
||||||
tint::fuzzers::CommonFuzzer fuzzer(tint::fuzzers::InputFormat::kWGSL,
|
tint::fuzzers::CommonFuzzer fuzzer(tint::fuzzers::InputFormat::kWGSL,
|
||||||
tint::fuzzers::OutputFormat::kWGSL);
|
tint::fuzzers::OutputFormat::kWGSL);
|
||||||
|
|
|
@ -14,6 +14,7 @@
|
||||||
|
|
||||||
#include "fuzzers/tint_common_fuzzer.h"
|
#include "fuzzers/tint_common_fuzzer.h"
|
||||||
|
|
||||||
|
#include <cassert>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
@ -51,23 +52,23 @@ namespace {
|
||||||
FatalError(diagnostics);
|
FatalError(diagnostics);
|
||||||
}
|
}
|
||||||
|
|
||||||
transform::VertexAttributeDescriptor ExtractVertexAttributeDescriptor(
|
transform::VertexAttributeDescriptor GenerateVertexAttributeDescriptor(
|
||||||
Reader* r) {
|
DataBuilder* b) {
|
||||||
transform::VertexAttributeDescriptor desc{};
|
transform::VertexAttributeDescriptor desc{};
|
||||||
desc.format = r->enum_class<transform::VertexFormat>(
|
desc.format = b->enum_class<transform::VertexFormat>(
|
||||||
static_cast<uint8_t>(transform::VertexFormat::kLastEntry) + 1);
|
static_cast<uint8_t>(transform::VertexFormat::kLastEntry) + 1);
|
||||||
desc.offset = r->read<uint32_t>();
|
desc.offset = b->build<uint32_t>();
|
||||||
desc.shader_location = r->read<uint32_t>();
|
desc.shader_location = b->build<uint32_t>();
|
||||||
return desc;
|
return desc;
|
||||||
}
|
}
|
||||||
|
|
||||||
transform::VertexBufferLayoutDescriptor ExtractVertexBufferLayoutDescriptor(
|
transform::VertexBufferLayoutDescriptor GenerateVertexBufferLayoutDescriptor(
|
||||||
Reader* r) {
|
DataBuilder* b) {
|
||||||
transform::VertexBufferLayoutDescriptor desc;
|
transform::VertexBufferLayoutDescriptor desc;
|
||||||
desc.array_stride = r->read<uint32_t>();
|
desc.array_stride = b->build<uint32_t>();
|
||||||
desc.step_mode = r->enum_class<transform::VertexStepMode>(
|
desc.step_mode = b->enum_class<transform::VertexStepMode>(
|
||||||
static_cast<uint8_t>(transform::VertexStepMode::kLastEntry) + 1);
|
static_cast<uint8_t>(transform::VertexStepMode::kLastEntry) + 1);
|
||||||
desc.attributes = r->vector(ExtractVertexAttributeDescriptor);
|
desc.attributes = b->vector(GenerateVertexAttributeDescriptor);
|
||||||
return desc;
|
return desc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -93,36 +94,28 @@ bool SPIRVToolsValidationCheck(const tint::Program& program,
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
Reader::Reader(const uint8_t* data, size_t size) : data_(data), size_(size) {}
|
DataBuilder::DataBuilder(const uint8_t* data, size_t size)
|
||||||
|
: generator_(RandomGenerator::CalculateSeed(data, size)) {}
|
||||||
|
|
||||||
std::string Reader::string() {
|
std::string DataBuilder::string() {
|
||||||
auto count = read<uint8_t>();
|
auto count = build<uint8_t>();
|
||||||
if (failed_ || size_ < count) {
|
if (count == 0) {
|
||||||
mark_failed();
|
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
std::string out(data_, data_ + count);
|
std::vector<uint8_t> source(count);
|
||||||
data_ += count;
|
build(source.data(), count);
|
||||||
size_ -= count;
|
return std::string(source.begin(), source.end());
|
||||||
return out;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Reader::mark_failed() {
|
void DataBuilder::build(void* out, size_t n) {
|
||||||
size_ = 0;
|
assert(out != nullptr && "|out| cannot be nullptr");
|
||||||
failed_ = true;
|
assert(n > 0 && "|n| must be > 0");
|
||||||
|
|
||||||
|
generator_.GetNBytes(reinterpret_cast<uint8_t*>(out), n);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Reader::read(void* out, size_t n) {
|
void GenerateBindingRemapperInputs(DataBuilder* b,
|
||||||
if (n > size_) {
|
tint::transform::DataMap* inputs) {
|
||||||
mark_failed();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
memcpy(out, data_, n);
|
|
||||||
data_ += n;
|
|
||||||
size_ -= n;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ExtractBindingRemapperInputs(Reader* r, tint::transform::DataMap* inputs) {
|
|
||||||
struct Config {
|
struct Config {
|
||||||
uint8_t old_group;
|
uint8_t old_group;
|
||||||
uint8_t old_binding;
|
uint8_t old_binding;
|
||||||
|
@ -131,7 +124,7 @@ void ExtractBindingRemapperInputs(Reader* r, tint::transform::DataMap* inputs) {
|
||||||
ast::Access new_access;
|
ast::Access new_access;
|
||||||
};
|
};
|
||||||
|
|
||||||
std::vector<Config> configs = r->vector<Config>();
|
std::vector<Config> configs = b->vector<Config>();
|
||||||
transform::BindingRemapper::BindingPoints binding_points;
|
transform::BindingRemapper::BindingPoints binding_points;
|
||||||
transform::BindingRemapper::AccessControls accesses;
|
transform::BindingRemapper::AccessControls accesses;
|
||||||
for (const auto& config : configs) {
|
for (const auto& config : configs) {
|
||||||
|
@ -143,47 +136,48 @@ void ExtractBindingRemapperInputs(Reader* r, tint::transform::DataMap* inputs) {
|
||||||
inputs->Add<transform::BindingRemapper::Remappings>(binding_points, accesses);
|
inputs->Add<transform::BindingRemapper::Remappings>(binding_points, accesses);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ExtractFirstIndexOffsetInputs(Reader* r,
|
void GenerateFirstIndexOffsetInputs(DataBuilder* b,
|
||||||
tint::transform::DataMap* inputs) {
|
tint::transform::DataMap* inputs) {
|
||||||
struct Config {
|
struct Config {
|
||||||
uint32_t group;
|
uint32_t group;
|
||||||
uint32_t binding;
|
uint32_t binding;
|
||||||
};
|
};
|
||||||
|
|
||||||
Config config = r->read<Config>();
|
Config config = b->build<Config>();
|
||||||
inputs->Add<tint::transform::FirstIndexOffset::BindingPoint>(config.binding,
|
inputs->Add<tint::transform::FirstIndexOffset::BindingPoint>(config.binding,
|
||||||
config.group);
|
config.group);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ExtractSingleEntryPointInputs(Reader* r,
|
void GenerateSingleEntryPointInputs(DataBuilder* b,
|
||||||
tint::transform::DataMap* inputs) {
|
tint::transform::DataMap* inputs) {
|
||||||
std::string input = r->string();
|
std::string input = b->string();
|
||||||
transform::SingleEntryPoint::Config cfg(input);
|
transform::SingleEntryPoint::Config cfg(input);
|
||||||
inputs->Add<transform::SingleEntryPoint::Config>(cfg);
|
inputs->Add<transform::SingleEntryPoint::Config>(cfg);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ExtractVertexPullingInputs(Reader* r, tint::transform::DataMap* inputs) {
|
void GenerateVertexPullingInputs(DataBuilder* b,
|
||||||
|
tint::transform::DataMap* inputs) {
|
||||||
transform::VertexPulling::Config cfg;
|
transform::VertexPulling::Config cfg;
|
||||||
cfg.entry_point_name = r->string();
|
cfg.entry_point_name = b->string();
|
||||||
cfg.vertex_state = r->vector(ExtractVertexBufferLayoutDescriptor);
|
cfg.vertex_state = b->vector(GenerateVertexBufferLayoutDescriptor);
|
||||||
cfg.pulling_group = r->read<uint32_t>();
|
cfg.pulling_group = b->build<uint32_t>();
|
||||||
inputs->Add<transform::VertexPulling::Config>(cfg);
|
inputs->Add<transform::VertexPulling::Config>(cfg);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ExtractSpirvOptions(Reader* r, writer::spirv::Options* options) {
|
void GenerateSpirvOptions(DataBuilder* b, writer::spirv::Options* options) {
|
||||||
*options = r->read<writer::spirv::Options>();
|
*options = b->build<writer::spirv::Options>();
|
||||||
}
|
}
|
||||||
|
|
||||||
void ExtractWgslOptions(Reader* r, writer::wgsl::Options* options) {
|
void GenerateWgslOptions(DataBuilder* b, writer::wgsl::Options* options) {
|
||||||
*options = r->read<writer::wgsl::Options>();
|
*options = b->build<writer::wgsl::Options>();
|
||||||
}
|
}
|
||||||
|
|
||||||
void ExtractHlslOptions(Reader* r, writer::hlsl::Options* options) {
|
void GenerateHlslOptions(DataBuilder* b, writer::hlsl::Options* options) {
|
||||||
*options = r->read<writer::hlsl::Options>();
|
*options = b->build<writer::hlsl::Options>();
|
||||||
}
|
}
|
||||||
|
|
||||||
void ExtractMslOptions(Reader* r, writer::msl::Options* options) {
|
void GenerateMslOptions(DataBuilder* b, writer::msl::Options* options) {
|
||||||
*options = r->read<writer::msl::Options>();
|
*options = b->build<writer::msl::Options>();
|
||||||
}
|
}
|
||||||
|
|
||||||
CommonFuzzer::CommonFuzzer(InputFormat input, OutputFormat output)
|
CommonFuzzer::CommonFuzzer(InputFormat input, OutputFormat output)
|
||||||
|
|
|
@ -21,23 +21,20 @@
|
||||||
#include <utility>
|
#include <utility>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
#include "fuzzers/random_generator.h"
|
||||||
#include "include/tint/tint.h"
|
#include "include/tint/tint.h"
|
||||||
|
|
||||||
namespace tint {
|
namespace tint {
|
||||||
namespace fuzzers {
|
namespace fuzzers {
|
||||||
|
|
||||||
class Reader {
|
class DataBuilder {
|
||||||
public:
|
public:
|
||||||
Reader(const uint8_t* data, size_t size);
|
DataBuilder(const uint8_t* data, size_t size);
|
||||||
|
|
||||||
bool failed() const { return failed_; }
|
|
||||||
const uint8_t* data() { return data_; }
|
|
||||||
size_t size() const { return size_; }
|
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
T read() {
|
T build() {
|
||||||
T out{};
|
T out{};
|
||||||
read(&out, sizeof(T));
|
build(&out, sizeof(T));
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -45,66 +42,48 @@ class Reader {
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
std::vector<T> vector() {
|
std::vector<T> vector() {
|
||||||
auto count = read<uint8_t>();
|
auto count = build<uint8_t>();
|
||||||
auto size = static_cast<size_t>(count) * sizeof(T);
|
|
||||||
if (failed_ || size_ < size) {
|
|
||||||
mark_failed();
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
std::vector<T> out(count);
|
std::vector<T> out(count);
|
||||||
if (!out.empty()) {
|
for (uint8_t i = 0; i < count; i++) {
|
||||||
memcpy(out.data(), data_, size);
|
out[i] = build<T>();
|
||||||
data_ += size;
|
|
||||||
size_ -= size;
|
|
||||||
}
|
}
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
std::vector<T> vector(T (*extract)(Reader*)) {
|
std::vector<T> vector(T (*generate)(DataBuilder*)) {
|
||||||
auto count = read<uint8_t>();
|
auto count = build<uint8_t>();
|
||||||
if (failed_) {
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
std::vector<T> out(count);
|
std::vector<T> out(count);
|
||||||
for (uint8_t i = 0; i < count; i++) {
|
for (uint8_t i = 0; i < count; i++) {
|
||||||
out[i] = extract(this);
|
out[i] = generate(this);
|
||||||
if (failed_) {
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
T enum_class(uint8_t count) {
|
T enum_class(uint8_t count) {
|
||||||
auto val = read<uint8_t>();
|
auto val = build<uint8_t>();
|
||||||
return static_cast<T>(val % count);
|
return static_cast<T>(val % count);
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void mark_failed();
|
void build(void* out, size_t n);
|
||||||
void read(void* out, size_t n);
|
|
||||||
|
|
||||||
const uint8_t* data_;
|
RandomGenerator generator_;
|
||||||
size_t size_;
|
|
||||||
bool failed_ = false;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
void ExtractBindingRemapperInputs(Reader* r, tint::transform::DataMap* inputs);
|
void GenerateBindingRemapperInputs(DataBuilder* b,
|
||||||
|
tint::transform::DataMap* inputs);
|
||||||
void ExtractFirstIndexOffsetInputs(Reader* r, tint::transform::DataMap* inputs);
|
void GenerateFirstIndexOffsetInputs(DataBuilder* b,
|
||||||
|
tint::transform::DataMap* inputs);
|
||||||
void ExtractSingleEntryPointInputs(Reader* r, tint::transform::DataMap* inputs);
|
void GenerateSingleEntryPointInputs(DataBuilder* b,
|
||||||
|
tint::transform::DataMap* inputs);
|
||||||
void ExtractVertexPullingInputs(Reader* r, tint::transform::DataMap* inputs);
|
void GenerateVertexPullingInputs(DataBuilder* b,
|
||||||
|
tint::transform::DataMap* inputs);
|
||||||
void ExtractSpirvOptions(Reader* r, writer::spirv::Options* options);
|
void GenerateSpirvOptions(DataBuilder* b, writer::spirv::Options* options);
|
||||||
|
void GenerateWgslOptions(DataBuilder* b, writer::wgsl::Options* options);
|
||||||
void ExtractWgslOptions(Reader* r, writer::wgsl::Options* options);
|
void GenerateHlslOptions(DataBuilder* b, writer::hlsl::Options* options);
|
||||||
|
void GenerateMslOptions(DataBuilder* b, writer::msl::Options* options);
|
||||||
void ExtractHlslOptions(Reader* r, writer::hlsl::Options* options);
|
|
||||||
|
|
||||||
void ExtractMslOptions(Reader* r, writer::msl::Options* options);
|
|
||||||
|
|
||||||
enum class InputFormat { kWGSL, kSpv, kNone };
|
enum class InputFormat { kWGSL, kSpv, kNone };
|
||||||
|
|
||||||
|
|
|
@ -21,20 +21,16 @@ namespace fuzzers {
|
||||||
extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
|
extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
|
||||||
tint::transform::Manager transform_manager;
|
tint::transform::Manager transform_manager;
|
||||||
tint::transform::DataMap transform_inputs;
|
tint::transform::DataMap transform_inputs;
|
||||||
Reader r(data, size);
|
DataBuilder b(data, size);
|
||||||
|
|
||||||
ExtractFirstIndexOffsetInputs(&r, &transform_inputs);
|
|
||||||
if (r.failed()) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
GenerateFirstIndexOffsetInputs(&b, &transform_inputs);
|
||||||
transform_manager.Add<tint::transform::FirstIndexOffset>();
|
transform_manager.Add<tint::transform::FirstIndexOffset>();
|
||||||
|
|
||||||
tint::fuzzers::CommonFuzzer fuzzer(InputFormat::kWGSL, OutputFormat::kWGSL);
|
tint::fuzzers::CommonFuzzer fuzzer(InputFormat::kWGSL, OutputFormat::kWGSL);
|
||||||
fuzzer.SetTransformManager(&transform_manager, std::move(transform_inputs));
|
fuzzer.SetTransformManager(&transform_manager, std::move(transform_inputs));
|
||||||
fuzzer.SetDumpInput(GetCliParams().dump_input);
|
fuzzer.SetDumpInput(GetCliParams().dump_input);
|
||||||
|
|
||||||
return fuzzer.Run(r.data(), r.size());
|
return fuzzer.Run(data, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace fuzzers
|
} // namespace fuzzers
|
||||||
|
|
|
@ -21,20 +21,16 @@ namespace fuzzers {
|
||||||
extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
|
extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
|
||||||
tint::transform::Manager transform_manager;
|
tint::transform::Manager transform_manager;
|
||||||
tint::transform::DataMap transform_inputs;
|
tint::transform::DataMap transform_inputs;
|
||||||
Reader r(data, size);
|
DataBuilder b(data, size);
|
||||||
|
|
||||||
ExtractSingleEntryPointInputs(&r, &transform_inputs);
|
|
||||||
if (r.failed()) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
GenerateSingleEntryPointInputs(&b, &transform_inputs);
|
||||||
transform_manager.Add<tint::transform::SingleEntryPoint>();
|
transform_manager.Add<tint::transform::SingleEntryPoint>();
|
||||||
|
|
||||||
tint::fuzzers::CommonFuzzer fuzzer(InputFormat::kWGSL, OutputFormat::kWGSL);
|
tint::fuzzers::CommonFuzzer fuzzer(InputFormat::kWGSL, OutputFormat::kWGSL);
|
||||||
fuzzer.SetTransformManager(&transform_manager, std::move(transform_inputs));
|
fuzzer.SetTransformManager(&transform_manager, std::move(transform_inputs));
|
||||||
fuzzer.SetDumpInput(GetCliParams().dump_input);
|
fuzzer.SetDumpInput(GetCliParams().dump_input);
|
||||||
|
|
||||||
return fuzzer.Run(r.data(), r.size());
|
return fuzzer.Run(data, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace fuzzers
|
} // namespace fuzzers
|
||||||
|
|
|
@ -21,13 +21,13 @@ namespace tint {
|
||||||
namespace fuzzers {
|
namespace fuzzers {
|
||||||
|
|
||||||
extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
|
extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
|
||||||
Reader reader(data, size);
|
DataBuilder b(data, size);
|
||||||
writer::msl::Options options;
|
writer::msl::Options options;
|
||||||
ExtractMslOptions(&reader, &options);
|
GenerateMslOptions(&b, &options);
|
||||||
tint::fuzzers::CommonFuzzer fuzzer(InputFormat::kSpv, OutputFormat::kMSL);
|
tint::fuzzers::CommonFuzzer fuzzer(InputFormat::kSpv, OutputFormat::kMSL);
|
||||||
fuzzer.SetOptionsMsl(options);
|
fuzzer.SetOptionsMsl(options);
|
||||||
fuzzer.SetDumpInput(GetCliParams().dump_input);
|
fuzzer.SetDumpInput(GetCliParams().dump_input);
|
||||||
return fuzzer.Run(reader.data(), reader.size());
|
return fuzzer.Run(data, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace fuzzers
|
} // namespace fuzzers
|
||||||
|
|
|
@ -21,13 +21,13 @@ namespace tint {
|
||||||
namespace fuzzers {
|
namespace fuzzers {
|
||||||
|
|
||||||
extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
|
extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
|
||||||
Reader reader(data, size);
|
DataBuilder b(data, size);
|
||||||
writer::spirv::Options options;
|
writer::spirv::Options options;
|
||||||
ExtractSpirvOptions(&reader, &options);
|
GenerateSpirvOptions(&b, &options);
|
||||||
tint::fuzzers::CommonFuzzer fuzzer(InputFormat::kSpv, OutputFormat::kSpv);
|
tint::fuzzers::CommonFuzzer fuzzer(InputFormat::kSpv, OutputFormat::kSpv);
|
||||||
fuzzer.SetOptionsSpirv(options);
|
fuzzer.SetOptionsSpirv(options);
|
||||||
fuzzer.SetDumpInput(GetCliParams().dump_input);
|
fuzzer.SetDumpInput(GetCliParams().dump_input);
|
||||||
return fuzzer.Run(reader.data(), reader.size());
|
return fuzzer.Run(data, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace fuzzers
|
} // namespace fuzzers
|
||||||
|
|
|
@ -21,20 +21,16 @@ namespace fuzzers {
|
||||||
extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
|
extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
|
||||||
tint::transform::Manager transform_manager;
|
tint::transform::Manager transform_manager;
|
||||||
tint::transform::DataMap transform_inputs;
|
tint::transform::DataMap transform_inputs;
|
||||||
Reader r(data, size);
|
DataBuilder b(data, size);
|
||||||
|
|
||||||
ExtractVertexPullingInputs(&r, &transform_inputs);
|
|
||||||
if (r.failed()) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
GenerateVertexPullingInputs(&b, &transform_inputs);
|
||||||
transform_manager.Add<tint::transform::VertexPulling>();
|
transform_manager.Add<tint::transform::VertexPulling>();
|
||||||
|
|
||||||
tint::fuzzers::CommonFuzzer fuzzer(InputFormat::kWGSL, OutputFormat::kWGSL);
|
tint::fuzzers::CommonFuzzer fuzzer(InputFormat::kWGSL, OutputFormat::kWGSL);
|
||||||
fuzzer.SetTransformManager(&transform_manager, std::move(transform_inputs));
|
fuzzer.SetTransformManager(&transform_manager, std::move(transform_inputs));
|
||||||
fuzzer.SetDumpInput(GetCliParams().dump_input);
|
fuzzer.SetDumpInput(GetCliParams().dump_input);
|
||||||
|
|
||||||
return fuzzer.Run(r.data(), r.size());
|
return fuzzer.Run(data, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace fuzzers
|
} // namespace fuzzers
|
||||||
|
|
|
@ -21,13 +21,13 @@ namespace tint {
|
||||||
namespace fuzzers {
|
namespace fuzzers {
|
||||||
|
|
||||||
extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
|
extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
|
||||||
Reader reader(data, size);
|
DataBuilder b(data, size);
|
||||||
writer::msl::Options options;
|
writer::msl::Options options;
|
||||||
ExtractMslOptions(&reader, &options);
|
GenerateMslOptions(&b, &options);
|
||||||
tint::fuzzers::CommonFuzzer fuzzer(InputFormat::kWGSL, OutputFormat::kMSL);
|
tint::fuzzers::CommonFuzzer fuzzer(InputFormat::kWGSL, OutputFormat::kMSL);
|
||||||
fuzzer.SetOptionsMsl(options);
|
fuzzer.SetOptionsMsl(options);
|
||||||
fuzzer.SetDumpInput(GetCliParams().dump_input);
|
fuzzer.SetDumpInput(GetCliParams().dump_input);
|
||||||
return fuzzer.Run(reader.data(), reader.size());
|
return fuzzer.Run(data, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace fuzzers
|
} // namespace fuzzers
|
||||||
|
|
|
@ -21,13 +21,13 @@ namespace tint {
|
||||||
namespace fuzzers {
|
namespace fuzzers {
|
||||||
|
|
||||||
extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
|
extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
|
||||||
Reader reader(data, size);
|
DataBuilder b(data, size);
|
||||||
writer::spirv::Options options;
|
writer::spirv::Options options;
|
||||||
ExtractSpirvOptions(&reader, &options);
|
GenerateSpirvOptions(&b, &options);
|
||||||
tint::fuzzers::CommonFuzzer fuzzer(InputFormat::kWGSL, OutputFormat::kSpv);
|
tint::fuzzers::CommonFuzzer fuzzer(InputFormat::kWGSL, OutputFormat::kSpv);
|
||||||
fuzzer.SetOptionsSpirv(options);
|
fuzzer.SetOptionsSpirv(options);
|
||||||
fuzzer.SetDumpInput(GetCliParams().dump_input);
|
fuzzer.SetDumpInput(GetCliParams().dump_input);
|
||||||
return fuzzer.Run(reader.data(), reader.size());
|
return fuzzer.Run(data, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace fuzzers
|
} // namespace fuzzers
|
||||||
|
|
Loading…
Reference in New Issue