dawn-cmake/fuzzers/tint_spirv_tools_fuzzer/spirv_fuzz_mutator.cc

128 lines
4.7 KiB
C++
Raw Normal View History

// 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.
#include "fuzzers/tint_spirv_tools_fuzzer/spirv_fuzz_mutator.h"
#include <fstream>
#include <utility>
#include "fuzzers/tint_spirv_tools_fuzzer/util.h"
#include "source/opt/build_module.h"
namespace tint {
namespace fuzzers {
namespace spvtools_fuzzer {
SpirvFuzzMutator::SpirvFuzzMutator(
spv_target_env target_env,
std::vector<uint32_t> binary,
unsigned seed,
const std::vector<spvtools::fuzz::fuzzerutil::ModuleSupplier>& donors,
bool enable_all_passes,
spvtools::fuzz::RepeatedPassStrategy repeated_pass_strategy,
bool validate_after_each_pass,
uint32_t transformation_batch_size)
: transformation_batch_size_(transformation_batch_size),
errors_(std::make_unique<std::stringstream>()),
fuzzer_(nullptr),
validator_options_(),
original_binary_(std::move(binary)),
seed_(seed) {
auto ir_context = spvtools::BuildModule(
target_env, spvtools::fuzz::fuzzerutil::kSilentMessageConsumer,
original_binary_.data(), original_binary_.size());
assert(ir_context && "|binary| is invalid");
auto transformation_context =
std::make_unique<spvtools::fuzz::TransformationContext>(
std::make_unique<spvtools::fuzz::FactManager>(ir_context.get()),
validator_options_);
auto fuzzer_context = std::make_unique<spvtools::fuzz::FuzzerContext>(
std::make_unique<spvtools::fuzz::PseudoRandomGenerator>(seed),
spvtools::fuzz::FuzzerContext::GetMinFreshId(ir_context.get()), false);
fuzzer_ = std::make_unique<spvtools::fuzz::Fuzzer>(
std::move(ir_context), std::move(transformation_context),
std::move(fuzzer_context), util::GetBufferMessageConsumer(errors_.get()),
donors, enable_all_passes, repeated_pass_strategy,
Revert "Update SPIR-V Tools fuzzer" This reverts commit 5a536347649b3b76a4ddb41ae08967a30118d10a. Reason for revert: This is making the Dawn -> Chromium roller fail. https://github.com/KhronosGroup/SPIRV-Tools/pull/4407 introduces a new mandatory parameter to the spvtools::fuzz::Fuzzer constructor, which does not exist in Chromium's version of SPIRV-Tools (d9f89257855a2784323512cd9568b6610bcae581). The roll of SPIRV-Tools into Chromium is currently blocked by another issue, and is a couple of weeks behind ToT. See https://autoroll.skia.org/r/vulkan-deps-chromium-autoroll. Note, that https://github.com/KhronosGroup/SPIRV-Tools/pull/4407 is going to block the eventual roll of SPIRV-Tools in Chromium, as there's no way this code can compile for both pre and post roll. I'll try and fix this after unblocking this roll Original change's description: > Update SPIR-V Tools fuzzer > > Updates spirv-tools DEPS to pull in some recent spirv-fuzz changes, and > modifies the SPIR-V Tools fuzzer so that inapplicable transformations > are ignored. > > Change-Id: Ibdea6e9bc35224efe148133eced341168f7ce7b7 > Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/60209 > Auto-Submit: Alastair Donaldson <afdx@google.com> > Kokoro: Kokoro <noreply+kokoro@google.com> > Reviewed-by: Ryan Harrison <rharrison@chromium.org> > Commit-Queue: Ryan Harrison <rharrison@chromium.org> # Not skipping CQ checks because original CL landed > 1 day ago. Change-Id: I4ebcfcfab16e760f64cb8dc622dfb6ef4f1eccf0 Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/60560 Reviewed-by: Ben Clayton <bclayton@chromium.org> Kokoro: Ben Clayton <bclayton@chromium.org> Commit-Queue: Ben Clayton <bclayton@chromium.org>
2021-08-02 11:13:49 +00:00
validate_after_each_pass, validator_options_);
}
Mutator::Result SpirvFuzzMutator::Mutate() {
// The assertion will fail in |fuzzer_->Run| if the previous fuzzing led to
// invalid module.
auto result = fuzzer_->Run(transformation_batch_size_);
switch (result.status) {
case spvtools::fuzz::Fuzzer::Status::kComplete:
return {Mutator::Status::kComplete, result.is_changed};
case spvtools::fuzz::Fuzzer::Status::kModuleTooBig:
case spvtools::fuzz::Fuzzer::Status::kTransformationLimitReached:
return {Mutator::Status::kLimitReached, result.is_changed};
case spvtools::fuzz::Fuzzer::Status::kFuzzerStuck:
return {Mutator::Status::kStuck, result.is_changed};
case spvtools::fuzz::Fuzzer::Status::kFuzzerPassLedToInvalidModule:
return {Mutator::Status::kInvalid, result.is_changed};
}
}
std::vector<uint32_t> SpirvFuzzMutator::GetBinary() const {
std::vector<uint32_t> result;
fuzzer_->GetIRContext()->module()->ToBinary(&result, true);
return result;
}
std::string SpirvFuzzMutator::GetErrors() const {
return errors_->str();
}
void SpirvFuzzMutator::LogErrors(const std::string* path,
uint32_t count) const {
auto message = GetErrors();
std::cout << count << " | SpirvFuzzMutator (seed: " << seed_ << ")"
<< std::endl;
std::cout << message << std::endl;
if (path) {
auto prefix = *path + std::to_string(count);
// Write errors to file.
std::ofstream(prefix + ".fuzzer.log") << "seed: " << seed_ << std::endl
<< message << std::endl;
// Write the invalid SPIR-V binary.
util::WriteBinary(prefix + ".fuzzer.invalid.spv", GetBinary());
// Write the original SPIR-V binary.
util::WriteBinary(prefix + ".fuzzer.original.spv", original_binary_);
// Write transformations.
google::protobuf::util::JsonOptions options;
options.add_whitespace = true;
std::string json;
google::protobuf::util::MessageToJsonString(
fuzzer_->GetTransformationSequence(), &json, options);
std::ofstream(prefix + ".fuzzer.transformations.json") << json << std::endl;
std::ofstream binary_transformations(
prefix + ".fuzzer.transformations.binary",
std::ios::binary | std::ios::out);
fuzzer_->GetTransformationSequence().SerializeToOstream(
&binary_transformations);
}
}
} // namespace spvtools_fuzzer
} // namespace fuzzers
} // namespace tint