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:
Alan Baker 2018-03-23 14:18:54 -04:00
parent 97c8fdccd2
commit 0a2ee65f57
4 changed files with 108 additions and 1 deletions

View File

@ -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:

View File

@ -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);

View File

@ -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");

View File

@ -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