mirror of
https://github.com/KhronosGroup/SPIRV-Tools
synced 2024-12-24 00:40:14 +00:00
Fixes #1403.
Don't validate composite insert, extract and construct instructions against spec constant sized arrays. * Added predicate for spec constant opcodes * Added tests
This commit is contained in:
parent
97c8fdccd2
commit
0a2ee65f57
@ -206,6 +206,19 @@ int32_t spvOpcodeIsScalarType(const SpvOp opcode) {
|
||||
}
|
||||
}
|
||||
|
||||
int32_t spvOpcodeIsSpecConstant(const SpvOp opcode) {
|
||||
switch (opcode) {
|
||||
case SpvOpSpecConstantTrue:
|
||||
case SpvOpSpecConstantFalse:
|
||||
case SpvOpSpecConstant:
|
||||
case SpvOpSpecConstantComposite:
|
||||
case SpvOpSpecConstantOp:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
int32_t spvOpcodeIsConstant(const SpvOp opcode) {
|
||||
switch (opcode) {
|
||||
case SpvOpConstantTrue:
|
||||
|
@ -63,6 +63,10 @@ const char* spvOpcodeString(const SpvOp opcode);
|
||||
// non-zero otherwise.
|
||||
int32_t spvOpcodeIsScalarType(const SpvOp opcode);
|
||||
|
||||
// Determines if the given opcode is a specialization constant. Returns zero if
|
||||
// false, non-zero otherwise.
|
||||
int32_t spvOpcodeIsSpecConstant(const SpvOp opcode);
|
||||
|
||||
// Determines if the given opcode is a constant. Returns zero if false, non-zero
|
||||
// otherwise.
|
||||
int32_t spvOpcodeIsConstant(const SpvOp opcode);
|
||||
|
@ -85,10 +85,16 @@ spv_result_t GetExtractInsertValueType(ValidationState_t& _,
|
||||
}
|
||||
case SpvOpTypeArray: {
|
||||
uint64_t array_size = 0;
|
||||
auto size = _.FindDef(type_inst->word(3));
|
||||
*member_type = type_inst->word(2);
|
||||
if (spvOpcodeIsSpecConstant(size->opcode())) {
|
||||
// Cannot verify against the size of this array.
|
||||
break;
|
||||
}
|
||||
|
||||
if (!_.GetConstantValUint64(type_inst->word(3), &array_size)) {
|
||||
assert(0 && "Array type definition is corrupt");
|
||||
}
|
||||
*member_type = type_inst->word(2);
|
||||
if (component_index >= array_size) {
|
||||
return _.diag(SPV_ERROR_INVALID_DATA)
|
||||
<< spvOpcodeString(opcode)
|
||||
@ -288,6 +294,12 @@ spv_result_t CompositesPass(ValidationState_t& _,
|
||||
assert(array_inst);
|
||||
assert(array_inst->opcode() == SpvOpTypeArray);
|
||||
|
||||
auto size = _.FindDef(array_inst->word(3));
|
||||
if (spvOpcodeIsSpecConstant(size->opcode())) {
|
||||
// Cannot verify against the size of this array.
|
||||
break;
|
||||
}
|
||||
|
||||
uint64_t array_size = 0;
|
||||
if (!_.GetConstantValUint64(array_inst->word(3), &array_size)) {
|
||||
assert(0 && "Array type definition is corrupt");
|
||||
|
@ -1416,4 +1416,82 @@ TEST_F(ValidateComposites, CompositeInsertStructIndexOutOfBoundBad) {
|
||||
"index 3 into the structure <id> '26'. This structure "
|
||||
"has 3 members. Largest valid index is 2."));
|
||||
}
|
||||
|
||||
// #1403: Ensure that the default spec constant value is not used to check the
|
||||
// extract index.
|
||||
TEST_F(ValidateComposites, ExtractFromSpecConstantSizedArray) {
|
||||
std::string spirv = R"(
|
||||
OpCapability Kernel
|
||||
OpCapability Linkage
|
||||
OpMemoryModel Logical OpenCL
|
||||
OpDecorate %spec_const SpecId 1
|
||||
%void = OpTypeVoid
|
||||
%uint = OpTypeInt 32 0
|
||||
%spec_const = OpSpecConstant %uint 3
|
||||
%uint_array = OpTypeArray %uint %spec_const
|
||||
%undef = OpUndef %uint_array
|
||||
%voidf = OpTypeFunction %void
|
||||
%func = OpFunction %void None %voidf
|
||||
%1 = OpLabel
|
||||
%2 = OpCompositeExtract %uint %undef 4
|
||||
OpReturn
|
||||
OpFunctionEnd
|
||||
)";
|
||||
|
||||
CompileSuccessfully(spirv);
|
||||
EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
|
||||
}
|
||||
|
||||
// #1403: Ensure that spec constant ops do not produce false positives.
|
||||
TEST_F(ValidateComposites, ExtractFromSpecConstantOpSizedArray) {
|
||||
std::string spirv = R"(
|
||||
OpCapability Kernel
|
||||
OpCapability Linkage
|
||||
OpMemoryModel Logical OpenCL
|
||||
OpDecorate %spec_const SpecId 1
|
||||
%void = OpTypeVoid
|
||||
%uint = OpTypeInt 32 0
|
||||
%const = OpConstant %uint 1
|
||||
%spec_const = OpSpecConstant %uint 3
|
||||
%spec_const_op = OpSpecConstantOp %uint IAdd %spec_const %const
|
||||
%uint_array = OpTypeArray %uint %spec_const_op
|
||||
%undef = OpUndef %uint_array
|
||||
%voidf = OpTypeFunction %void
|
||||
%func = OpFunction %void None %voidf
|
||||
%1 = OpLabel
|
||||
%2 = OpCompositeExtract %uint %undef 4
|
||||
OpReturn
|
||||
OpFunctionEnd
|
||||
)";
|
||||
|
||||
CompileSuccessfully(spirv);
|
||||
EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
|
||||
}
|
||||
|
||||
// #1403: Ensure that the default spec constant value is not used to check the
|
||||
// size of the array for a composite construct. This code has limited actual
|
||||
// value as it is incorrect unless the specialization constant is assigned the
|
||||
// value of 2, but it is still a valid module.
|
||||
TEST_F(ValidateComposites, CompositeConstructSpecConstantSizedArray) {
|
||||
std::string spirv = R"(
|
||||
OpCapability Kernel
|
||||
OpCapability Linkage
|
||||
OpMemoryModel Logical OpenCL
|
||||
OpDecorate %spec_const SpecId 1
|
||||
%void = OpTypeVoid
|
||||
%uint = OpTypeInt 32 0
|
||||
%uint_0 = OpConstant %uint 0
|
||||
%spec_const = OpSpecConstant %uint 3
|
||||
%uint_array = OpTypeArray %uint %spec_const
|
||||
%voidf = OpTypeFunction %void
|
||||
%func = OpFunction %void None %voidf
|
||||
%1 = OpLabel
|
||||
%2 = OpCompositeConstruct %uint_array %uint_0 %uint_0
|
||||
OpReturn
|
||||
OpFunctionEnd
|
||||
)";
|
||||
|
||||
CompileSuccessfully(spirv);
|
||||
EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
|
||||
}
|
||||
} // anonymous namespace
|
||||
|
Loading…
Reference in New Issue
Block a user