Skip to content

Commit

Permalink
spirv-fuzz: Do not outline regions that produce pointer outputs (Khro…
Browse files Browse the repository at this point in the history
…nosGroup#3291)

The function outliner uses a struct to return ids that a region
generates and that are used outside that region.  If these ids have
pointer type this would result in a struct with pointer members, which
leads to illegal loading from non-logical pointers if logical
addressing is used.  This change bans that outlining possibility.
  • Loading branch information
afd authored Apr 14, 2020
1 parent f460cca commit c018fc6
Show file tree
Hide file tree
Showing 2 changed files with 71 additions and 3 deletions.
14 changes: 11 additions & 3 deletions source/fuzz/transformation_outline_function.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -274,12 +274,20 @@ bool TransformationOutlineFunction::IsApplicable(
}

// For each region output id -- i.e. every id defined inside the region but
// used outside the region -- there needs to be a corresponding fresh id that
// can hold the value for this id computed in the outlined function.
// used outside the region, ...
std::map<uint32_t, uint32_t> output_id_to_fresh_id_map =
PairSequenceToMap(message_.output_id_to_fresh_id());
for (auto id : GetRegionOutputIds(ir_context, region_set, exit_block)) {
if (output_id_to_fresh_id_map.count(id) == 0) {
if (
// ... there needs to be a corresponding fresh id that can hold the
// value for this id computed in the outlined function, and ...
output_id_to_fresh_id_map.count(id) == 0
// ... the output id must not have pointer type (to avoid creating a
// struct with pointer members to pass data out of the outlined
// function)
|| ir_context->get_def_use_mgr()
->GetDef(fuzzerutil::GetTypeId(ir_context, id))
->opcode() == SpvOpTypePointer) {
return false;
}
}
Expand Down
60 changes: 60 additions & 0 deletions test/fuzz/transformation_outline_function_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2460,6 +2460,66 @@ TEST(TransformationOutlineFunctionTest,
}
}

TEST(TransformationOutlineFunctionTest,
DoNotOutlineCodeThatProducesUsedPointer) {
// This checks that we cannot outline a region of code if it produces a
// pointer result id that gets used outside the region. This avoids creating
// a struct with a pointer member.

std::string shader = R"(
OpCapability Shader
%1 = OpExtInstImport "GLSL.std.450"
OpMemoryModel Logical GLSL450
OpEntryPoint Fragment %6 "main"
OpExecutionMode %6 OriginUpperLeft
OpSource ESSL 310
%2 = OpTypeVoid
%3 = OpTypeFunction %2
%21 = OpTypeBool
%100 = OpTypeInt 32 0
%99 = OpConstant %100 0
%101 = OpTypeVector %100 2
%102 = OpTypePointer Function %100
%103 = OpTypePointer Function %101
%6 = OpFunction %2 None %3
%7 = OpLabel
%104 = OpVariable %103 Function
OpBranch %80
%80 = OpLabel
%105 = OpAccessChain %102 %104 %99
OpBranch %106
%106 = OpLabel
OpStore %105 %99
OpReturn
OpFunctionEnd
)";

const auto env = SPV_ENV_UNIVERSAL_1_5;
const auto consumer = nullptr;
const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
ASSERT_TRUE(IsValid(env, context.get()));

FactManager fact_manager;
spvtools::ValidatorOptions validator_options;
TransformationContext transformation_context(&fact_manager,
validator_options);

TransformationOutlineFunction transformation(
/*entry_block*/ 80,
/*exit_block*/ 80,
/*new_function_struct_return_type_id*/ 300,
/*new_function_type_id*/ 301,
/*new_function_id*/ 302,
/*new_function_region_entry_block*/ 304,
/*new_caller_result_id*/ 305,
/*new_callee_result_id*/ 306,
/*input_id_to_fresh_id*/ {{104, 307}},
/*output_id_to_fresh_id*/ {{105, 308}});

ASSERT_FALSE(
transformation.IsApplicable(context.get(), transformation_context));
}

TEST(TransformationOutlineFunctionTest, Miscellaneous1) {
// This tests outlining of some non-trivial code.

Expand Down

0 comments on commit c018fc6

Please sign in to comment.