mirror of
https://github.com/KhronosGroup/SPIRV-Tools
synced 2024-10-18 11:10:05 +00:00
spirv-fuzz: Handle capabilities during module donation (#3651)
Fixes #3648.
This commit is contained in:
parent
9f22236024
commit
d9c73ebd9e
@ -84,6 +84,16 @@ void FuzzerPassDonateModules::Apply() {
|
||||
|
||||
void FuzzerPassDonateModules::DonateSingleModule(
|
||||
opt::IRContext* donor_ir_context, bool make_livesafe) {
|
||||
// Check that the donated module has capabilities, supported by the recipient
|
||||
// module.
|
||||
for (const auto& capability_inst : donor_ir_context->capabilities()) {
|
||||
auto capability =
|
||||
static_cast<SpvCapability>(capability_inst.GetSingleWordInOperand(0));
|
||||
if (!GetIRContext()->get_feature_mgr()->HasCapability(capability)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// The ids used by the donor module may very well clash with ids defined in
|
||||
// the recipient module. Furthermore, some instructions defined in the donor
|
||||
// module will be equivalent to instructions defined in the recipient module,
|
||||
|
@ -12,9 +12,10 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include "source/fuzz/fuzzer_pass_donate_modules.h"
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
#include "source/fuzz/fuzzer_pass_donate_modules.h"
|
||||
#include "source/fuzz/pseudo_random_generator.h"
|
||||
#include "test/fuzz/fuzz_test_util.h"
|
||||
|
||||
@ -1902,6 +1903,131 @@ TEST(FuzzerPassDonateModulesTest, DonationSupportsOpTypeRuntimeArray) {
|
||||
ASSERT_TRUE(IsValid(env, recipient_context.get()));
|
||||
}
|
||||
|
||||
TEST(FuzzerPassDonateModulesTest, HandlesCapabilities) {
|
||||
std::string donor_shader = R"(
|
||||
OpCapability VariablePointersStorageBuffer
|
||||
%1 = OpExtInstImport "GLSL.std.450"
|
||||
OpMemoryModel Logical GLSL450
|
||||
OpEntryPoint Fragment %4 "main"
|
||||
OpExecutionMode %4 OriginUpperLeft
|
||||
OpSource ESSL 310
|
||||
%2 = OpTypeVoid
|
||||
%3 = OpTypeFunction %2
|
||||
%6 = OpTypeFloat 32
|
||||
%11 = OpConstant %6 23
|
||||
%7 = OpTypePointer Function %6
|
||||
%4 = OpFunction %2 None %3
|
||||
|
||||
%5 = OpLabel
|
||||
%8 = OpVariable %7 Function
|
||||
OpBranch %9
|
||||
|
||||
%9 = OpLabel
|
||||
%10 = OpPhi %7 %8 %5
|
||||
OpStore %10 %11
|
||||
OpReturn
|
||||
|
||||
OpFunctionEnd
|
||||
)";
|
||||
|
||||
std::string recipient_shader = R"(
|
||||
OpCapability Shader
|
||||
%1 = OpExtInstImport "GLSL.std.450"
|
||||
OpMemoryModel Logical GLSL450
|
||||
OpEntryPoint Fragment %4 "main"
|
||||
OpExecutionMode %4 OriginUpperLeft
|
||||
OpSource ESSL 310
|
||||
%2 = OpTypeVoid
|
||||
%3 = OpTypeFunction %2
|
||||
%4 = OpFunction %2 None %3
|
||||
%5 = OpLabel
|
||||
OpReturn
|
||||
OpFunctionEnd
|
||||
)";
|
||||
|
||||
const auto env = SPV_ENV_UNIVERSAL_1_3;
|
||||
const auto consumer = nullptr;
|
||||
const auto recipient_context =
|
||||
BuildModule(env, consumer, recipient_shader, kFuzzAssembleOption);
|
||||
ASSERT_TRUE(IsValid(env, recipient_context.get()));
|
||||
|
||||
const auto donor_context =
|
||||
BuildModule(env, consumer, donor_shader, kFuzzAssembleOption);
|
||||
ASSERT_TRUE(IsValid(env, donor_context.get()));
|
||||
|
||||
FactManager fact_manager;
|
||||
spvtools::ValidatorOptions validator_options;
|
||||
TransformationContext transformation_context(&fact_manager,
|
||||
validator_options);
|
||||
|
||||
PseudoRandomGenerator rng(0);
|
||||
FuzzerContext fuzzer_context(&rng, 100);
|
||||
protobufs::TransformationSequence transformation_sequence;
|
||||
|
||||
FuzzerPassDonateModules fuzzer_pass(recipient_context.get(),
|
||||
&transformation_context, &fuzzer_context,
|
||||
&transformation_sequence, {});
|
||||
|
||||
ASSERT_TRUE(donor_context->get_feature_mgr()->HasCapability(
|
||||
SpvCapabilityVariablePointersStorageBuffer));
|
||||
ASSERT_FALSE(recipient_context->get_feature_mgr()->HasCapability(
|
||||
SpvCapabilityVariablePointersStorageBuffer));
|
||||
|
||||
fuzzer_pass.DonateSingleModule(donor_context.get(), false);
|
||||
|
||||
// Check that recipient module hasn't changed.
|
||||
ASSERT_TRUE(IsEqual(env, recipient_shader, recipient_context.get()));
|
||||
|
||||
// Add the missing capability.
|
||||
//
|
||||
// We are adding VariablePointers to test the case when donor and recipient
|
||||
// have different OpCapability instructions but the same capabilities. In our
|
||||
// example, VariablePointers implicitly declares
|
||||
// VariablePointersStorageBuffer. Thus, two modules must be compatible.
|
||||
recipient_context->AddCapability(SpvCapabilityVariablePointers);
|
||||
|
||||
ASSERT_TRUE(donor_context->get_feature_mgr()->HasCapability(
|
||||
SpvCapabilityVariablePointersStorageBuffer));
|
||||
ASSERT_TRUE(recipient_context->get_feature_mgr()->HasCapability(
|
||||
SpvCapabilityVariablePointersStorageBuffer));
|
||||
|
||||
fuzzer_pass.DonateSingleModule(donor_context.get(), false);
|
||||
|
||||
// Check that donation was successful.
|
||||
ASSERT_TRUE(IsValid(env, recipient_context.get()));
|
||||
|
||||
std::string after_transformation = R"(
|
||||
OpCapability Shader
|
||||
OpCapability VariablePointers
|
||||
%1 = OpExtInstImport "GLSL.std.450"
|
||||
OpMemoryModel Logical GLSL450
|
||||
OpEntryPoint Fragment %4 "main"
|
||||
OpExecutionMode %4 OriginUpperLeft
|
||||
OpSource ESSL 310
|
||||
%2 = OpTypeVoid
|
||||
%3 = OpTypeFunction %2
|
||||
%100 = OpTypeFloat 32
|
||||
%101 = OpConstant %100 23
|
||||
%102 = OpTypePointer Function %100
|
||||
%105 = OpConstant %100 0
|
||||
%4 = OpFunction %2 None %3
|
||||
%5 = OpLabel
|
||||
OpReturn
|
||||
OpFunctionEnd
|
||||
%103 = OpFunction %2 None %3
|
||||
%104 = OpLabel
|
||||
%106 = OpVariable %102 Function %105
|
||||
OpBranch %107
|
||||
%107 = OpLabel
|
||||
%108 = OpPhi %102 %106 %104
|
||||
OpStore %108 %101
|
||||
OpReturn
|
||||
OpFunctionEnd
|
||||
)";
|
||||
|
||||
ASSERT_TRUE(IsEqual(env, after_transformation, recipient_context.get()));
|
||||
}
|
||||
|
||||
} // namespace
|
||||
} // namespace fuzz
|
||||
} // namespace spvtools
|
||||
|
Loading…
Reference in New Issue
Block a user