Check OpSampledImage is only passed into valid instructions (#2467)

Fixes #1528
This commit is contained in:
Ryan Harrison 2019-03-25 15:44:57 -04:00 committed by GitHub
parent 2d52cbee49
commit ffbecae56a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 110 additions and 12 deletions

View File

@ -748,6 +748,33 @@ spv_result_t ValidateTypeSampledImage(ValidationState_t& _,
return SPV_SUCCESS;
}
bool IsAllowedSampledImageOperand(SpvOp opcode) {
switch (opcode) {
case SpvOpSampledImage:
case SpvOpImageSampleImplicitLod:
case SpvOpImageSampleExplicitLod:
case SpvOpImageSampleDrefImplicitLod:
case SpvOpImageSampleDrefExplicitLod:
case SpvOpImageSampleProjImplicitLod:
case SpvOpImageSampleProjExplicitLod:
case SpvOpImageSampleProjDrefImplicitLod:
case SpvOpImageSampleProjDrefExplicitLod:
case SpvOpImageGather:
case SpvOpImageDrefGather:
case SpvOpImage:
case SpvOpImageQueryLod:
case SpvOpImageSparseSampleImplicitLod:
case SpvOpImageSparseSampleExplicitLod:
case SpvOpImageSparseSampleDrefImplicitLod:
case SpvOpImageSparseSampleDrefExplicitLod:
case SpvOpImageSparseGather:
case SpvOpImageSparseDrefGather:
return true;
default:
return false;
}
}
spv_result_t ValidateSampledImage(ValidationState_t& _,
const Instruction* inst) {
if (_.GetIdOpcode(inst->type_id()) != SpvOpTypeSampledImage) {
@ -815,11 +842,7 @@ spv_result_t ValidateSampledImage(ValidationState_t& _,
"block. The consumer instruction <id> is '"
<< _.getIdName(consumer_instr->id()) << "'.";
}
// TODO: The following check is incomplete. We should also check that the
// Sampled Image is not used by instructions that should not take
// SampledImage as an argument. We could find the list of valid
// instructions by scanning for "Sampled Image" in the operand description
// field in the grammar file.
if (consumer_opcode == SpvOpPhi || consumer_opcode == SpvOpSelect) {
return _.diag(SPV_ERROR_INVALID_ID, inst)
<< "Result <id> from OpSampledImage instruction must not appear "
@ -830,6 +853,18 @@ spv_result_t ValidateSampledImage(ValidationState_t& _,
<< "' as an operand of <id> '"
<< _.getIdName(consumer_instr->id()) << "'.";
}
if (!IsAllowedSampledImageOperand(consumer_opcode)) {
return _.diag(SPV_ERROR_INVALID_ID, inst)
<< "Result <id> from OpSampledImage instruction must not appear "
"as operand for Op"
<< spvOpcodeString(static_cast<SpvOp>(consumer_opcode))
<< ", since it is not specificed as taking an "
<< "OpTypeSampledImage."
<< " Found result <id> '" << _.getIdName(inst->id())
<< "' as an operand of <id> '"
<< _.getIdName(consumer_instr->id()) << "'.";
}
}
}
return SPV_SUCCESS;

View File

@ -2283,7 +2283,7 @@ TEST_F(ValidateImage, FetchNotImage) {
%img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
%sampler = OpLoad %type_sampler %uniform_sampler
%simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
%res1 = OpImageFetch %f32vec4 %simg %u32vec2_01
%res1 = OpImageFetch %f32vec4 %sampler %u32vec2_01
)";
CompileSuccessfully(GenerateShaderCode(body).c_str());
@ -2292,6 +2292,21 @@ TEST_F(ValidateImage, FetchNotImage) {
HasSubstr("Expected Image to be of type OpTypeImage"));
}
TEST_F(ValidateImage, FetchSampledImageDirectly) {
const std::string body = R"(
%img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
%sampler = OpLoad %type_sampler %uniform_sampler
%simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
%res1 = OpImageFetch %f32vec4 %simg %u32vec2_01
)";
CompileSuccessfully(GenerateShaderCode(body).c_str());
ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
EXPECT_THAT(getDiagnosticString(),
HasSubstr("OpSampledImage instruction must not appear as operand "
"for OpImageFetch"));
}
TEST_F(ValidateImage, FetchNotSampled) {
const std::string body = R"(
%img = OpLoad %type_image_u32_2d_0000 %uniform_image_u32_2d_0000
@ -3191,7 +3206,7 @@ TEST_F(ValidateImage, QueryFormatNotImage) {
%img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
%sampler = OpLoad %type_sampler %uniform_sampler
%simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
%res1 = OpImageQueryFormat %u32 %simg
%res1 = OpImageQueryFormat %u32 %sampler
)";
CompileSuccessfully(GenerateKernelCode(body).c_str());
@ -3227,7 +3242,7 @@ TEST_F(ValidateImage, QueryOrderNotImage) {
%img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
%sampler = OpLoad %type_sampler %uniform_sampler
%simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
%res1 = OpImageQueryOrder %u32 %simg
%res1 = OpImageQueryOrder %u32 %sampler
)";
CompileSuccessfully(GenerateKernelCode(body).c_str());
@ -3276,7 +3291,7 @@ TEST_F(ValidateImage, QuerySizeLodNotImage) {
%img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
%sampler = OpLoad %type_sampler %uniform_sampler
%simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
%res1 = OpImageQuerySizeLod %u32vec2 %simg %u32_1
%res1 = OpImageQuerySizeLod %u32vec2 %sampler %u32_1
)";
CompileSuccessfully(GenerateKernelCode(body).c_str());
@ -3285,6 +3300,21 @@ TEST_F(ValidateImage, QuerySizeLodNotImage) {
HasSubstr("Expected Image to be of type OpTypeImage"));
}
TEST_F(ValidateImage, QuerySizeLodSampledImageDirectly) {
const std::string body = R"(
%img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
%sampler = OpLoad %type_sampler %uniform_sampler
%simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
%res1 = OpImageQuerySizeLod %u32vec2 %simg %u32_1
)";
CompileSuccessfully(GenerateShaderCode(body).c_str());
ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
EXPECT_THAT(getDiagnosticString(),
HasSubstr("OpSampledImage instruction must not appear as operand "
"for OpImageQuerySizeLod"));
}
TEST_F(ValidateImage, QuerySizeLodWrongImageDim) {
const std::string body = R"(
%img = OpLoad %type_image_f32_rect_0001 %uniform_image_f32_rect_0001
@ -3348,7 +3378,7 @@ TEST_F(ValidateImage, QuerySizeNotImage) {
%img = OpLoad %type_image_f32_2d_0010 %uniform_image_f32_2d_0010
%sampler = OpLoad %type_sampler %uniform_sampler
%simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
%res1 = OpImageQuerySize %u32vec2 %simg
%res1 = OpImageQuerySize %u32vec2 %sampler
)";
CompileSuccessfully(GenerateKernelCode(body).c_str());
@ -3357,6 +3387,21 @@ TEST_F(ValidateImage, QuerySizeNotImage) {
HasSubstr("Expected Image to be of type OpTypeImage"));
}
TEST_F(ValidateImage, QuerySizeSampledImageDirectly) {
const std::string body = R"(
%img = OpLoad %type_image_f32_2d_0010 %uniform_image_f32_2d_0010
%sampler = OpLoad %type_sampler %uniform_sampler
%simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
%res1 = OpImageQuerySize %u32vec2 %simg
)";
CompileSuccessfully(GenerateShaderCode(body).c_str());
ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
EXPECT_THAT(getDiagnosticString(),
HasSubstr("OpSampledImage instruction must not appear as operand "
"for OpImageQuerySize"));
}
TEST_F(ValidateImage, QuerySizeDimSubpassDataBad) {
const std::string body = R"(
%img = OpLoad %type_image_f32_spd_0002 %uniform_image_f32_spd_0002
@ -3531,7 +3576,7 @@ TEST_F(ValidateImage, QueryLevelsNotImage) {
%img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
%sampler = OpLoad %type_sampler %uniform_sampler
%simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
%res1 = OpImageQueryLevels %u32 %simg
%res1 = OpImageQueryLevels %u32 %sampler
)";
CompileSuccessfully(GenerateKernelCode(body).c_str());
@ -3540,6 +3585,21 @@ TEST_F(ValidateImage, QueryLevelsNotImage) {
HasSubstr("Expected Image to be of type OpTypeImage"));
}
TEST_F(ValidateImage, QueryLevelsSampledImageDirectly) {
const std::string body = R"(
%img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
%sampler = OpLoad %type_sampler %uniform_sampler
%simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
%res1 = OpImageQueryLevels %u32 %simg
)";
CompileSuccessfully(GenerateShaderCode(body).c_str());
ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
EXPECT_THAT(getDiagnosticString(),
HasSubstr("OpSampledImage instruction must not appear as operand "
"for OpImageQueryLevels"));
}
TEST_F(ValidateImage, QueryLevelsWrongDim) {
const std::string body = R"(
%img = OpLoad %type_image_f32_rect_0001 %uniform_image_f32_rect_0001
@ -4481,7 +4541,10 @@ TEST_F(ValidateImage, Issue2463NoSegFault) {
)";
CompileSuccessfully(spirv);
ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
EXPECT_THAT(getDiagnosticString(),
HasSubstr("OpSampledImage instruction must not appear as operand "
"for OpReturnValue"));
}
} // namespace