Add some missing switch validation (#4507)

Fixes #4506

* Add validation of selector and default operands
This commit is contained in:
alan-baker 2021-09-08 05:09:01 -04:00 committed by GitHub
parent 92868b8f3f
commit c16224c684
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 62 additions and 0 deletions

View File

@ -199,6 +199,18 @@ spv_result_t ValidateSwitch(ValidationState_t& _, const Instruction* inst) {
// At least two operands (selector, default), any more than that are
// literal/target.
const auto sel_type_id = _.GetOperandTypeId(inst, 0);
if (!_.IsIntScalarType(sel_type_id)) {
return _.diag(SPV_ERROR_INVALID_ID, inst)
<< "Selector type must be OpTypeInt";
}
const auto default_label = _.FindDef(inst->GetOperandAs<uint32_t>(1));
if (default_label->opcode() != SpvOpLabel) {
return _.diag(SPV_ERROR_INVALID_ID, inst)
<< "Default must be an OpLabel instruction";
}
// target operands must be OpLabel
for (size_t i = 2; i < num_operands; i += 2) {
// literal, id

View File

@ -4399,6 +4399,56 @@ OpFunctionEnd
"1[%BAD], but not via a structured exit"));
}
TEST_F(ValidateCFG, SwitchSelectorNotAnInt) {
const std::string spirv = R"(
OpCapability Shader
OpMemoryModel Logical GLSL450
OpEntryPoint GLCompute %main "main"
OpExecutionMode %main LocalSize 1 1 1
%void = OpTypeVoid
%float = OpTypeFloat 32
%float_1 = OpConstant %float 1
%void_fn = OpTypeFunction %void
%main = OpFunction %void None %void_fn
%entry = OpLabel
OpSelectionMerge %default None
OpSwitch %float_1 %default
%default = OpLabel
OpReturn
OpFunctionEnd
)";
CompileSuccessfully(spirv);
EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
EXPECT_THAT(getDiagnosticString(),
HasSubstr("Selector type must be OpTypeInt"));
}
TEST_F(ValidateCFG, SwitchDefaultNotALabel) {
const std::string spirv = R"(
OpCapability Shader
OpMemoryModel Logical GLSL450
OpEntryPoint GLCompute %main "main"
OpExecutionMode %main LocalSize 1 1 1
%void = OpTypeVoid
%int = OpTypeInt 32 0
%int_1 = OpConstant %int 1
%void_fn = OpTypeFunction %void
%main = OpFunction %void None %void_fn
%entry = OpLabel
OpSelectionMerge %default None
OpSwitch %int_1 %int_1
%default = OpLabel
OpReturn
OpFunctionEnd
)";
CompileSuccessfully(spirv);
EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
EXPECT_THAT(getDiagnosticString(),
HasSubstr("Default must be an OpLabel instruction"));
}
} // namespace
} // namespace val
} // namespace spvtools