spirv-fuzz: Disallow copying of null and undefined pointers (#3172)

If the fuzzer object-copies a pointer we would like to be able to
perform loads from the copy (and stores to it, if its value is known
not to matter).  Undefined and null pointers present a problem here,
so this change disallows copying them.
This commit is contained in:
Alastair Donaldson 2020-02-04 11:15:07 +00:00 committed by GitHub
parent a9624b4d5d
commit b7e0998e3d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 54 additions and 0 deletions

View File

@ -226,6 +226,20 @@ bool CanMakeSynonymOf(opt::IRContext* ir_context, opt::Instruction* inst) {
// We can only make a synonym of an instruction that has a type.
return false;
}
auto type_inst = ir_context->get_def_use_mgr()->GetDef(inst->type_id());
if (type_inst->opcode() == SpvOpTypePointer) {
switch (inst->opcode()) {
case SpvOpConstantNull:
case SpvOpUndef:
// We disallow making synonyms of null or undefined pointers. This is
// to provide the property that if the original shader exhibited no bad
// pointer accesses, the transformed shader will not either.
return false;
default:
break;
}
}
// We do not make synonyms of objects that have decorations: if the synonym is
// not decorated analogously, using the original object vs. its synonymous
// form may not be equivalent.

View File

@ -47,6 +47,8 @@ class TransformationCopyObject : public Transformation {
// - It must be legal to insert an OpCopyObject instruction directly
// before 'inst'.
// - |message_.object| must be available directly before 'inst'.
// - |message_.object| must not be a null pointer or undefined pointer (so as
// to make it legal to load from copied pointers).
bool IsApplicable(opt::IRContext* context,
const FactManager& fact_manager) const override;

View File

@ -588,6 +588,44 @@ TEST(TransformationCopyObjectTest, MiscellaneousCopies) {
ASSERT_TRUE(IsEqual(env, after_transformation, context.get()));
}
TEST(TransformationCopyObjectTest, DoNotCopyNullOrUndefPointers) {
std::string 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
%6 = OpTypeInt 32 1
%7 = OpTypePointer Function %6
%8 = OpConstantNull %7
%9 = OpUndef %7
%4 = OpFunction %2 None %3
%5 = OpLabel
OpReturn
OpFunctionEnd
)";
const auto env = SPV_ENV_UNIVERSAL_1_3;
const auto consumer = nullptr;
const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
ASSERT_TRUE(IsValid(env, context.get()));
FactManager fact_manager;
// Illegal to copy null.
ASSERT_FALSE(TransformationCopyObject(
8, MakeInstructionDescriptor(5, SpvOpReturn, 0), 100)
.IsApplicable(context.get(), fact_manager));
// Illegal to copy an OpUndef of pointer type.
ASSERT_FALSE(TransformationCopyObject(
9, MakeInstructionDescriptor(5, SpvOpReturn, 0), 100)
.IsApplicable(context.get(), fact_manager));
}
} // namespace
} // namespace fuzz
} // namespace spvtools