Add fuzzing for transform::VertexPulling
Includes a significant refactoring of helper functions in tint_common_fuzzer.cc/.h BUG=tint:722 Change-Id: I1fdab0113bae02c4a0bf8da0d1b7729f05a2fc5b Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/49902 Commit-Queue: Ryan Harrison <rharrison@chromium.org> Auto-Submit: Ryan Harrison <rharrison@chromium.org> Reviewed-by: Ben Clayton <bclayton@google.com>
This commit is contained in:
parent
4f34e7897b
commit
a0174e613f
|
@ -102,6 +102,11 @@ if (build_with_chromium) {
|
||||||
deps = [ ":tint_fuzzer_common" ]
|
deps = [ ":tint_fuzzer_common" ]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fuzzer_test("tint_vertex_pulling_fuzzer") {
|
||||||
|
sources = [ "tint_vertex_pulling_fuzzer.cc" ]
|
||||||
|
deps = [ ":tint_fuzzer_common" ]
|
||||||
|
}
|
||||||
|
|
||||||
fuzzer_test("tint_wgsl_reader_spv_writer_fuzzer") {
|
fuzzer_test("tint_wgsl_reader_spv_writer_fuzzer") {
|
||||||
sources = [ "tint_wgsl_reader_spv_writer_fuzzer.cc" ]
|
sources = [ "tint_wgsl_reader_spv_writer_fuzzer.cc" ]
|
||||||
deps = [ ":tint_fuzzer_common" ]
|
deps = [ ":tint_fuzzer_common" ]
|
||||||
|
@ -196,6 +201,7 @@ if (build_with_chromium) {
|
||||||
":tint_renamer_fuzzer",
|
":tint_renamer_fuzzer",
|
||||||
":tint_single_entry_point_fuzzer",
|
":tint_single_entry_point_fuzzer",
|
||||||
":tint_spirv_transform_fuzzer",
|
":tint_spirv_transform_fuzzer",
|
||||||
|
":tint_vertex_pulling_fuzzer",
|
||||||
":tint_wgsl_reader_spv_writer_fuzzer",
|
":tint_wgsl_reader_spv_writer_fuzzer",
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
|
@ -39,6 +39,7 @@ if (${TINT_BUILD_WGSL_READER} AND ${TINT_BUILD_SPV_WRITER})
|
||||||
add_tint_fuzzer(tint_renamer_fuzzer)
|
add_tint_fuzzer(tint_renamer_fuzzer)
|
||||||
add_tint_fuzzer(tint_single_entry_point_fuzzer)
|
add_tint_fuzzer(tint_single_entry_point_fuzzer)
|
||||||
add_tint_fuzzer(tint_spirv_transform_fuzzer)
|
add_tint_fuzzer(tint_spirv_transform_fuzzer)
|
||||||
|
add_tint_fuzzer(tint_vertex_pulling_fuzzer)
|
||||||
add_tint_fuzzer(tint_wgsl_reader_spv_writer_fuzzer)
|
add_tint_fuzzer(tint_wgsl_reader_spv_writer_fuzzer)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
|
|
@ -18,27 +18,17 @@ namespace tint {
|
||||||
namespace fuzzers {
|
namespace fuzzers {
|
||||||
|
|
||||||
struct Config {
|
struct Config {
|
||||||
const uint8_t* data;
|
Config(const uint8_t* data, size_t size) : reader(data, size) {}
|
||||||
size_t size;
|
Reader reader;
|
||||||
transform::Manager manager;
|
transform::Manager manager;
|
||||||
transform::DataMap inputs;
|
transform::DataMap inputs;
|
||||||
};
|
};
|
||||||
|
|
||||||
bool AddPlatformIndependentPasses(Config* config) {
|
bool AddPlatformIndependentPasses(Config* config) {
|
||||||
if (!ExtractFirstIndexOffsetInputs(&config->data, &config->size,
|
ExtractFirstIndexOffsetInputs(&config->reader, &config->inputs);
|
||||||
&config->inputs)) {
|
ExtractBindingRemapperInputs(&config->reader, &config->inputs);
|
||||||
return false;
|
ExtractSingleEntryPointInputs(&config->reader, &config->inputs);
|
||||||
}
|
ExtractVertexPullingInputs(&config->reader, &config->inputs);
|
||||||
|
|
||||||
if (!ExtractBindingRemapperInputs(&config->data, &config->size,
|
|
||||||
&config->inputs)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!ExtractSingleEntryPointInputs(&config->data, &config->size,
|
|
||||||
&config->inputs)) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
config->manager.Add<transform::BoundArrayAccessors>();
|
config->manager.Add<transform::BoundArrayAccessors>();
|
||||||
config->manager
|
config->manager
|
||||||
|
@ -48,15 +38,14 @@ bool AddPlatformIndependentPasses(Config* config) {
|
||||||
config->manager.Add<transform::BindingRemapper>();
|
config->manager.Add<transform::BindingRemapper>();
|
||||||
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>();
|
||||||
|
|
||||||
return true;
|
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;
|
Config config(data, size);
|
||||||
config.data = data;
|
|
||||||
config.size = size;
|
|
||||||
|
|
||||||
if (!AddPlatformIndependentPasses(&config)) {
|
if (!AddPlatformIndependentPasses(&config)) {
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -65,14 +54,12 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
|
||||||
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.Run(config.data, config.size);
|
fuzzer.Run(config.reader.data(), config.reader.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
#if TINT_BUILD_HLSL_WRITER
|
#if TINT_BUILD_HLSL_WRITER
|
||||||
{
|
{
|
||||||
Config config;
|
Config config(data, size);
|
||||||
config.data = data;
|
|
||||||
config.size = size;
|
|
||||||
|
|
||||||
if (!AddPlatformIndependentPasses(&config)) {
|
if (!AddPlatformIndependentPasses(&config)) {
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -83,15 +70,13 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
|
||||||
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.Run(config.data, config.size);
|
fuzzer.Run(config.reader.data(), config.reader.size());
|
||||||
}
|
}
|
||||||
#endif // TINT_BUILD_HLSL_WRITER
|
#endif // TINT_BUILD_HLSL_WRITER
|
||||||
|
|
||||||
#if TINT_BUILD_MSL_WRITER
|
#if TINT_BUILD_MSL_WRITER
|
||||||
{
|
{
|
||||||
Config config;
|
Config config(data, size);
|
||||||
config.data = data;
|
|
||||||
config.size = size;
|
|
||||||
|
|
||||||
if (!AddPlatformIndependentPasses(&config)) {
|
if (!AddPlatformIndependentPasses(&config)) {
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -102,14 +87,12 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
|
||||||
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.Run(config.data, config.size);
|
fuzzer.Run(config.reader.data(), config.reader.size());
|
||||||
}
|
}
|
||||||
#endif // TINT_BUILD_MSL_WRITER
|
#endif // TINT_BUILD_MSL_WRITER
|
||||||
#if TINT_BUILD_SPV_WRITER
|
#if TINT_BUILD_SPV_WRITER
|
||||||
{
|
{
|
||||||
Config config;
|
Config config(data, size);
|
||||||
config.data = data;
|
|
||||||
config.size = size;
|
|
||||||
|
|
||||||
if (!AddPlatformIndependentPasses(&config)) {
|
if (!AddPlatformIndependentPasses(&config)) {
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -120,7 +103,7 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
|
||||||
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.Run(config.data, config.size);
|
fuzzer.Run(config.reader.data(), config.reader.size());
|
||||||
}
|
}
|
||||||
#endif // TINT_BUILD_SPV_WRITER
|
#endif // TINT_BUILD_SPV_WRITER
|
||||||
|
|
||||||
|
|
|
@ -20,8 +20,10 @@ 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);
|
||||||
|
|
||||||
if (!ExtractBindingRemapperInputs(&data, &size, &transform_inputs)) {
|
ExtractBindingRemapperInputs(&r, &transform_inputs);
|
||||||
|
if (r.failed()) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -30,7 +32,7 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
|
||||||
fuzzers::CommonFuzzer fuzzer(InputFormat::kWGSL, OutputFormat::kSpv);
|
fuzzers::CommonFuzzer fuzzer(InputFormat::kWGSL, OutputFormat::kSpv);
|
||||||
fuzzer.SetTransformManager(&transform_manager, std::move(transform_inputs));
|
fuzzer.SetTransformManager(&transform_manager, std::move(transform_inputs));
|
||||||
|
|
||||||
return fuzzer.Run(data, size);
|
return fuzzer.Run(r.data(), r.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace fuzzers
|
} // namespace fuzzers
|
||||||
|
|
|
@ -26,6 +26,8 @@
|
||||||
namespace tint {
|
namespace tint {
|
||||||
namespace fuzzers {
|
namespace fuzzers {
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
[[noreturn]] void TintInternalCompilerErrorReporter(
|
[[noreturn]] void TintInternalCompilerErrorReporter(
|
||||||
const tint::diag::List& diagnostics) {
|
const tint::diag::List& diagnostics) {
|
||||||
auto printer = tint::diag::Printer::create(stderr, true);
|
auto printer = tint::diag::Printer::create(stderr, true);
|
||||||
|
@ -37,41 +39,72 @@ namespace fuzzers {
|
||||||
auto printer = tint::diag::Printer::create(stderr, true);
|
auto printer = tint::diag::Printer::create(stderr, true);
|
||||||
printer->write(
|
printer->write(
|
||||||
"Fuzzing detected valid input program being transformed into an invalid "
|
"Fuzzing detected valid input program being transformed into an invalid "
|
||||||
"output progam",
|
"output progam\n",
|
||||||
{diag::Color::kRed, true});
|
{diag::Color::kRed, true});
|
||||||
__builtin_trap();
|
__builtin_trap();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ExtractBindingRemapperInputs(const uint8_t** data,
|
transform::VertexAttributeDescriptor ExtractVertexAttributeDescriptor(
|
||||||
size_t* size,
|
Reader* r) {
|
||||||
tint::transform::DataMap* inputs) {
|
transform::VertexAttributeDescriptor desc;
|
||||||
if ((*size) < sizeof(uint8_t)) {
|
desc.format = r->enum_class<transform::VertexFormat>(
|
||||||
return false;
|
static_cast<uint8_t>(transform::VertexFormat::kLastEntry) + 1);
|
||||||
|
desc.offset = r->read<uint64_t>();
|
||||||
|
desc.shader_location = r->read<uint32_t>();
|
||||||
|
return desc;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto count = *reinterpret_cast<const uint8_t*>(*data);
|
transform::VertexBufferLayoutDescriptor ExtractVertexBufferLayoutDescriptor(
|
||||||
(*data) += sizeof(uint8_t);
|
Reader* r) {
|
||||||
(*size) -= sizeof(uint8_t);
|
transform::VertexBufferLayoutDescriptor desc;
|
||||||
|
desc.array_stride = r->read<uint64_t>();
|
||||||
|
desc.step_mode = r->enum_class<transform::InputStepMode>(
|
||||||
|
static_cast<uint8_t>(transform::InputStepMode::kLastEntry) + 1);
|
||||||
|
desc.attributes = r->vector(ExtractVertexAttributeDescriptor);
|
||||||
|
return desc;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
Reader::Reader(const uint8_t* data, size_t size) : data_(data), size_(size) {}
|
||||||
|
|
||||||
|
std::string Reader::string() {
|
||||||
|
auto count = read<uint8_t>();
|
||||||
|
if (failed_ || size_ < count) {
|
||||||
|
mark_failed();
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
std::string out(data_, data_ + count);
|
||||||
|
data_ += count;
|
||||||
|
size_ -= count;
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Reader::mark_failed() {
|
||||||
|
size_ = 0;
|
||||||
|
failed_ = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Reader::read(void* out, size_t n) {
|
||||||
|
if (n > size_) {
|
||||||
|
mark_failed();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
memcpy(&out, data_, n);
|
||||||
|
data_ += n;
|
||||||
|
size_ -= n;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ExtractBindingRemapperInputs(Reader* r, tint::transform::DataMap* inputs) {
|
||||||
struct Config {
|
struct Config {
|
||||||
uint32_t old_group;
|
uint8_t old_group;
|
||||||
uint32_t old_binding;
|
uint8_t old_binding;
|
||||||
uint32_t new_group;
|
uint8_t new_group;
|
||||||
uint32_t new_binding;
|
uint8_t new_binding;
|
||||||
ast::AccessControl::Access new_ac;
|
ast::AccessControl::Access new_ac;
|
||||||
};
|
};
|
||||||
|
|
||||||
if ((*size) < count * sizeof(Config)) {
|
std::vector<Config> configs = r->vector<Config>();
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::vector<Config> configs(count);
|
|
||||||
|
|
||||||
memcpy(configs.data(), *data, count * sizeof(Config));
|
|
||||||
|
|
||||||
(*data) += count * sizeof(Config);
|
|
||||||
(*size) -= count * sizeof(Config);
|
|
||||||
|
|
||||||
transform::BindingRemapper::BindingPoints binding_points;
|
transform::BindingRemapper::BindingPoints binding_points;
|
||||||
transform::BindingRemapper::AccessControls access_controls;
|
transform::BindingRemapper::AccessControls access_controls;
|
||||||
for (const auto& config : configs) {
|
for (const auto& config : configs) {
|
||||||
|
@ -82,59 +115,33 @@ bool ExtractBindingRemapperInputs(const uint8_t** data,
|
||||||
|
|
||||||
inputs->Add<transform::BindingRemapper::Remappings>(binding_points,
|
inputs->Add<transform::BindingRemapper::Remappings>(binding_points,
|
||||||
access_controls);
|
access_controls);
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ExtractFirstIndexOffsetInputs(const uint8_t** data,
|
void ExtractFirstIndexOffsetInputs(Reader* r,
|
||||||
size_t* size,
|
|
||||||
tint::transform::DataMap* inputs) {
|
tint::transform::DataMap* inputs) {
|
||||||
struct Config {
|
struct Config {
|
||||||
uint32_t group;
|
uint32_t group;
|
||||||
uint32_t binding;
|
uint32_t binding;
|
||||||
};
|
};
|
||||||
|
|
||||||
if ((*size) < sizeof(Config)) {
|
Config config = r->read<Config>();
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
Config config;
|
|
||||||
memcpy(&config, data, sizeof(config));
|
|
||||||
|
|
||||||
(*data) += sizeof(Config);
|
|
||||||
(*size) -= sizeof(Config);
|
|
||||||
|
|
||||||
inputs->Add<tint::transform::FirstIndexOffset::BindingPoint>(config.binding,
|
inputs->Add<tint::transform::FirstIndexOffset::BindingPoint>(config.binding,
|
||||||
config.group);
|
config.group);
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ExtractSingleEntryPointInputs(const uint8_t** data,
|
void ExtractSingleEntryPointInputs(Reader* r,
|
||||||
size_t* size,
|
|
||||||
tint::transform::DataMap* inputs) {
|
tint::transform::DataMap* inputs) {
|
||||||
if ((*size) < sizeof(uint8_t)) {
|
std::string input = r->string();
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto count = *reinterpret_cast<const uint8_t*>(*data);
|
|
||||||
(*data) += sizeof(uint8_t);
|
|
||||||
(*size) -= sizeof(uint8_t);
|
|
||||||
|
|
||||||
if ((*size) < count) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto* c = reinterpret_cast<const char*>(*data);
|
|
||||||
std::string input(c, c + count);
|
|
||||||
|
|
||||||
(*data) += count * sizeof(char);
|
|
||||||
(*size) -= count * sizeof(char);
|
|
||||||
|
|
||||||
transform::SingleEntryPoint::Config cfg(input);
|
transform::SingleEntryPoint::Config cfg(input);
|
||||||
inputs->Add<transform::SingleEntryPoint::Config>(cfg);
|
inputs->Add<transform::SingleEntryPoint::Config>(cfg);
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
void ExtractVertexPullingInputs(Reader* r, tint::transform::DataMap* inputs) {
|
||||||
|
transform::VertexPulling::Config cfg;
|
||||||
|
cfg.entry_point_name = r->string();
|
||||||
|
cfg.vertex_state = r->vector(ExtractVertexBufferLayoutDescriptor);
|
||||||
|
cfg.pulling_group = r->read<uint32_t>();
|
||||||
|
inputs->Add<transform::VertexPulling::Config>(cfg);
|
||||||
}
|
}
|
||||||
|
|
||||||
CommonFuzzer::CommonFuzzer(InputFormat input, OutputFormat output)
|
CommonFuzzer::CommonFuzzer(InputFormat input, OutputFormat output)
|
||||||
|
@ -158,7 +165,6 @@ int CommonFuzzer::Run(const uint8_t* data, size_t size) {
|
||||||
#if TINT_BUILD_WGSL_READER
|
#if TINT_BUILD_WGSL_READER
|
||||||
case InputFormat::kWGSL: {
|
case InputFormat::kWGSL: {
|
||||||
std::string str(reinterpret_cast<const char*>(data), size);
|
std::string str(reinterpret_cast<const char*>(data), size);
|
||||||
|
|
||||||
file = std::make_unique<Source::File>("test.wgsl", str);
|
file = std::make_unique<Source::File>("test.wgsl", str);
|
||||||
program = reader::wgsl::Parse(file.get());
|
program = reader::wgsl::Parse(file.get());
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -15,23 +15,80 @@
|
||||||
#ifndef FUZZERS_TINT_COMMON_FUZZER_H_
|
#ifndef FUZZERS_TINT_COMMON_FUZZER_H_
|
||||||
#define FUZZERS_TINT_COMMON_FUZZER_H_
|
#define FUZZERS_TINT_COMMON_FUZZER_H_
|
||||||
|
|
||||||
|
#include <string>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
#include "include/tint/tint.h"
|
#include "include/tint/tint.h"
|
||||||
|
|
||||||
namespace tint {
|
namespace tint {
|
||||||
namespace fuzzers {
|
namespace fuzzers {
|
||||||
|
|
||||||
bool ExtractBindingRemapperInputs(const uint8_t** data,
|
class Reader {
|
||||||
size_t* size,
|
public:
|
||||||
tint::transform::DataMap* inputs);
|
Reader(const uint8_t* data, size_t size);
|
||||||
bool ExtractFirstIndexOffsetInputs(const uint8_t** data,
|
|
||||||
size_t* size,
|
|
||||||
tint::transform::DataMap* inputs);
|
|
||||||
|
|
||||||
bool ExtractSingleEntryPointInputs(const uint8_t** data,
|
bool failed() { return failed_; }
|
||||||
size_t* size,
|
const uint8_t* data() { return data_; }
|
||||||
tint::transform::DataMap* inputs);
|
size_t size() { return size_; }
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
T read() {
|
||||||
|
T out{};
|
||||||
|
read(&out, sizeof(T));
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string string();
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
std::vector<T> vector() {
|
||||||
|
auto count = read<uint8_t>();
|
||||||
|
if (failed_ || size_ < count) {
|
||||||
|
mark_failed();
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
std::vector<T> out(count);
|
||||||
|
memcpy(out.data(), data_, count * sizeof(T));
|
||||||
|
data_ += count * sizeof(T);
|
||||||
|
size_ -= count * sizeof(T);
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
std::vector<T> vector(T (*extract)(Reader*)) {
|
||||||
|
auto count = read<uint8_t>();
|
||||||
|
if (size_ < count) {
|
||||||
|
mark_failed();
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
std::vector<T> out(count);
|
||||||
|
for (uint8_t i = 0; i < count; i++) {
|
||||||
|
out[i] = extract(this);
|
||||||
|
}
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
template <typename T>
|
||||||
|
T enum_class(uint8_t count) {
|
||||||
|
auto val = read<uint8_t>();
|
||||||
|
return static_cast<T>(val % count);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
void mark_failed();
|
||||||
|
void read(void* out, size_t n);
|
||||||
|
|
||||||
|
const uint8_t* data_;
|
||||||
|
size_t size_;
|
||||||
|
bool failed_ = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
void ExtractBindingRemapperInputs(Reader* r, tint::transform::DataMap* inputs);
|
||||||
|
void ExtractFirstIndexOffsetInputs(Reader* r, tint::transform::DataMap* inputs);
|
||||||
|
|
||||||
|
void ExtractSingleEntryPointInputs(Reader* r, tint::transform::DataMap* inputs);
|
||||||
|
|
||||||
|
void ExtractVertexPullingInputs(Reader* r, tint::transform::DataMap* inputs);
|
||||||
|
|
||||||
enum class InputFormat { kWGSL, kSpv, kNone };
|
enum class InputFormat { kWGSL, kSpv, kNone };
|
||||||
|
|
||||||
|
|
|
@ -20,8 +20,10 @@ 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);
|
||||||
|
|
||||||
if (!ExtractFirstIndexOffsetInputs(&data, &size, &transform_inputs)) {
|
ExtractFirstIndexOffsetInputs(&r, &transform_inputs);
|
||||||
|
if (r.failed()) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -30,7 +32,7 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
|
||||||
tint::fuzzers::CommonFuzzer fuzzer(InputFormat::kWGSL, OutputFormat::kSpv);
|
tint::fuzzers::CommonFuzzer fuzzer(InputFormat::kWGSL, OutputFormat::kSpv);
|
||||||
fuzzer.SetTransformManager(&transform_manager, std::move(transform_inputs));
|
fuzzer.SetTransformManager(&transform_manager, std::move(transform_inputs));
|
||||||
|
|
||||||
return fuzzer.Run(data, size);
|
return fuzzer.Run(r.data(), r.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace fuzzers
|
} // namespace fuzzers
|
||||||
|
|
|
@ -20,8 +20,10 @@ 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);
|
||||||
|
|
||||||
if (!ExtractSingleEntryPointInputs(&data, &size, &transform_inputs)) {
|
ExtractSingleEntryPointInputs(&r, &transform_inputs);
|
||||||
|
if (r.failed()) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -30,7 +32,7 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
|
||||||
tint::fuzzers::CommonFuzzer fuzzer(InputFormat::kWGSL, OutputFormat::kSpv);
|
tint::fuzzers::CommonFuzzer fuzzer(InputFormat::kWGSL, OutputFormat::kSpv);
|
||||||
fuzzer.SetTransformManager(&transform_manager, std::move(transform_inputs));
|
fuzzer.SetTransformManager(&transform_manager, std::move(transform_inputs));
|
||||||
|
|
||||||
return fuzzer.Run(data, size);
|
return fuzzer.Run(r.data(), r.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace fuzzers
|
} // namespace fuzzers
|
||||||
|
|
|
@ -0,0 +1,42 @@
|
||||||
|
// 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.
|
||||||
|
|
||||||
|
// TODO(tint:753): Remove this fuzzer once that transform is only
|
||||||
|
// being used from sanitizers.
|
||||||
|
|
||||||
|
#include "fuzzers/tint_common_fuzzer.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;
|
||||||
|
Reader r(data, size);
|
||||||
|
|
||||||
|
ExtractVertexPullingInputs(&r, &transform_inputs);
|
||||||
|
if (r.failed()) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
transform_manager.Add<tint::transform::VertexPulling>();
|
||||||
|
|
||||||
|
tint::fuzzers::CommonFuzzer fuzzer(InputFormat::kWGSL, OutputFormat::kSpv);
|
||||||
|
fuzzer.SetTransformManager(&transform_manager, {});
|
||||||
|
|
||||||
|
return fuzzer.Run(r.data(), r.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace fuzzers
|
||||||
|
} // namespace tint
|
|
@ -28,6 +28,7 @@ TINT_INSTANTIATE_TYPEINFO(tint::transform::VertexPulling::Config);
|
||||||
|
|
||||||
namespace tint {
|
namespace tint {
|
||||||
namespace transform {
|
namespace transform {
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
struct State {
|
struct State {
|
||||||
|
|
|
@ -56,12 +56,13 @@ enum class VertexFormat {
|
||||||
kI32,
|
kI32,
|
||||||
kVec2I32,
|
kVec2I32,
|
||||||
kVec3I32,
|
kVec3I32,
|
||||||
kVec4I32
|
kVec4I32,
|
||||||
|
kLastEntry = kVec4I32
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Describes if a vertex attributes increments with vertex index or instance
|
/// Describes if a vertex attributes increments with vertex index or instance
|
||||||
/// index
|
/// index
|
||||||
enum class InputStepMode { kVertex, kInstance };
|
enum class InputStepMode { kVertex, kInstance, kLastEntry = kInstance };
|
||||||
|
|
||||||
/// Describes a vertex attribute within a buffer
|
/// Describes a vertex attribute within a buffer
|
||||||
struct VertexAttributeDescriptor {
|
struct VertexAttributeDescriptor {
|
||||||
|
|
Loading…
Reference in New Issue