Warn when input facts are invalid. (#2699)
Fixes #2621. Instead of aborting when an invalid input fact is provided, the tool now warns about the invalid fact and then ignores it. This is convenient for example if facts are specified about uniforms with descriptor sets and bindings that happen to not be present in the input binary.
This commit is contained in:
Родитель
88183041d5
Коммит
6ccb52b864
|
@ -14,12 +14,60 @@
|
|||
|
||||
#include "source/fuzz/fact_manager.h"
|
||||
|
||||
#include <sstream>
|
||||
|
||||
#include "source/fuzz/uniform_buffer_element_descriptor.h"
|
||||
#include "source/opt/ir_context.h"
|
||||
|
||||
namespace spvtools {
|
||||
namespace fuzz {
|
||||
|
||||
namespace {
|
||||
|
||||
std::string ToString(const protobufs::Fact& fact) {
|
||||
assert(fact.fact_case() == protobufs::Fact::kConstantUniformFact &&
|
||||
"Right now this is the only fact.");
|
||||
std::stringstream stream;
|
||||
stream << "("
|
||||
<< fact.constant_uniform_fact()
|
||||
.uniform_buffer_element_descriptor()
|
||||
.descriptor_set()
|
||||
<< ", "
|
||||
<< fact.constant_uniform_fact()
|
||||
.uniform_buffer_element_descriptor()
|
||||
.binding()
|
||||
<< ")[";
|
||||
|
||||
bool first = true;
|
||||
for (auto index : fact.constant_uniform_fact()
|
||||
.uniform_buffer_element_descriptor()
|
||||
.index()) {
|
||||
if (first) {
|
||||
first = false;
|
||||
} else {
|
||||
stream << ", ";
|
||||
}
|
||||
stream << index;
|
||||
}
|
||||
|
||||
stream << "] == [";
|
||||
|
||||
first = true;
|
||||
for (auto constant_word : fact.constant_uniform_fact().constant_word()) {
|
||||
if (first) {
|
||||
first = false;
|
||||
} else {
|
||||
stream << ", ";
|
||||
}
|
||||
stream << constant_word;
|
||||
}
|
||||
|
||||
stream << "]";
|
||||
return stream.str();
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
// The purpose of this struct is to group the fields and data used to represent
|
||||
// facts about uniform constants.
|
||||
struct FactManager::ConstantUniformFacts {
|
||||
|
@ -288,16 +336,16 @@ FactManager::FactManager() {
|
|||
|
||||
FactManager::~FactManager() = default;
|
||||
|
||||
bool FactManager::AddFacts(const protobufs::FactSequence& initial_facts,
|
||||
void FactManager::AddFacts(const MessageConsumer& message_consumer,
|
||||
const protobufs::FactSequence& initial_facts,
|
||||
opt::IRContext* context) {
|
||||
for (auto& fact : initial_facts.fact()) {
|
||||
if (!AddFact(fact, context)) {
|
||||
// TODO(https://github.com/KhronosGroup/SPIRV-Tools/issues/2621) Provide
|
||||
// information about the fact that could not be added.
|
||||
return false;
|
||||
message_consumer(
|
||||
SPV_MSG_WARNING, nullptr, {},
|
||||
("Invalid fact " + ToString(fact) + " ignored.").c_str());
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool FactManager::AddFact(const spvtools::fuzz::protobufs::Fact& fact,
|
||||
|
|
|
@ -41,11 +41,14 @@ class FactManager {
|
|||
~FactManager();
|
||||
|
||||
// Adds all the facts from |facts|, checking them for validity with respect to
|
||||
// |context|. Returns true if and only if all facts are valid.
|
||||
bool AddFacts(const protobufs::FactSequence& facts, opt::IRContext* context);
|
||||
// |context|. Warnings about invalid facts are communicated via
|
||||
// |message_consumer|; such facts are otherwise ignored.
|
||||
void AddFacts(const MessageConsumer& message_consumer,
|
||||
const protobufs::FactSequence& facts, opt::IRContext* context);
|
||||
|
||||
// Adds |fact| to the fact manager, checking it for validity with respect to
|
||||
// |context|. Returns true if and only if the fact is valid.
|
||||
// Checks the fact for validity with respect to |context|. Returns false,
|
||||
// with no side effects, if the fact is invalid. Otherwise adds |fact| to the
|
||||
// fact manager.
|
||||
bool AddFact(const protobufs::Fact& fact, opt::IRContext* context);
|
||||
|
||||
// The fact manager will ultimately be responsible for managing a few distinct
|
||||
|
|
|
@ -97,9 +97,7 @@ Fuzzer::FuzzerResultStatus Fuzzer::Run(
|
|||
FuzzerContext fuzzer_context(&random_generator, minimum_fresh_id);
|
||||
|
||||
FactManager fact_manager;
|
||||
if (!fact_manager.AddFacts(initial_facts, ir_context.get())) {
|
||||
return Fuzzer::FuzzerResultStatus::kInitialFactsInvalid;
|
||||
}
|
||||
fact_manager.AddFacts(impl_->consumer, initial_facts, ir_context.get());
|
||||
|
||||
// Add some essential ingredients to the module if they are not already
|
||||
// present, such as boolean constants.
|
||||
|
|
|
@ -33,7 +33,6 @@ class Fuzzer {
|
|||
kComplete,
|
||||
kFailedToCreateSpirvToolsInterface,
|
||||
kInitialBinaryInvalid,
|
||||
kInitialFactsInvalid,
|
||||
};
|
||||
|
||||
// Constructs a fuzzer from the given target environment.
|
||||
|
|
|
@ -81,9 +81,7 @@ Replayer::ReplayerResultStatus Replayer::Run(
|
|||
assert(ir_context);
|
||||
|
||||
FactManager fact_manager;
|
||||
if (!fact_manager.AddFacts(initial_facts, ir_context.get())) {
|
||||
return Replayer::ReplayerResultStatus::kInitialFactsInvalid;
|
||||
}
|
||||
fact_manager.AddFacts(impl_->consumer, initial_facts, ir_context.get());
|
||||
|
||||
// Consider the transformation proto messages in turn.
|
||||
for (auto& message : transformation_sequence_in.transformation()) {
|
||||
|
|
|
@ -33,7 +33,6 @@ class Replayer {
|
|||
kComplete,
|
||||
kFailedToCreateSpirvToolsInterface,
|
||||
kInitialBinaryInvalid,
|
||||
kInitialFactsInvalid,
|
||||
};
|
||||
|
||||
// Constructs a replayer from the given target environment.
|
||||
|
|
|
@ -257,7 +257,7 @@ int main(int argc, const char** argv) {
|
|||
const std::string dot_spv(".spv");
|
||||
std::string in_facts_file =
|
||||
in_binary_file.substr(0, in_binary_file.length() - dot_spv.length()) +
|
||||
".json";
|
||||
".facts";
|
||||
std::ifstream facts_input(in_facts_file);
|
||||
if (facts_input) {
|
||||
std::string facts_json_string((std::istreambuf_iterator<char>(facts_input)),
|
||||
|
|
Загрузка…
Ссылка в новой задаче