return SPV_SUCCESS;
}
+// Checks that the number of OpTypeStruct members is within the limit.
+spv_result_t LimitCheckStruct(ValidationState_t& _,
+ const spv_parsed_instruction_t* inst) {
+ // Number of members is the number of operands of the instruction minus 1.
+ // One operand is the result ID.
+ const uint16_t limit = 0x3fff;
+ if (SpvOpTypeStruct == inst->opcode && inst->num_operands - 1 > limit) {
+ return _.diag(SPV_ERROR_INVALID_BINARY)
+ << "Number of OpTypeStruct members (" << inst->num_operands - 1
+ << ") has exceeded the limit (" << limit << ").";
+ }
+ return SPV_SUCCESS;
+}
+
spv_result_t InstructionPass(ValidationState_t& _,
const spv_parsed_instruction_t* inst) {
const SpvOp opcode = static_cast<SpvOp>(inst->opcode);
if (auto error = CapCheck(_, inst)) return error;
if (auto error = LimitCheckIdBound(_, inst)) return error;
+ if (auto error = LimitCheckStruct(_, inst)) return error;
// All instruction checks have passed.
return SPV_SUCCESS;
HasSubstr("Result <id> '64' must be less than the ID bound '64'."));
}
+TEST_F(ValidateLimits, structNumMembersGood) {
+ std::ostringstream spirv;
+ spirv << header << R"(
+%1 = OpTypeInt 32 0
+%2 = OpTypeStruct)";
+ for (int i = 0; i < 16383; ++i) {
+ spirv << " %1";
+ }
+ CompileSuccessfully(spirv.str());
+ ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
+}
+
+TEST_F(ValidateLimits, structNumMembersExceededBad) {
+ std::ostringstream spirv;
+ spirv << header << R"(
+%1 = OpTypeInt 32 0
+%2 = OpTypeStruct)";
+ for (int i = 0; i < 16384; ++i) {
+ spirv << " %1";
+ }
+ CompileSuccessfully(spirv.str());
+ ASSERT_EQ(SPV_ERROR_INVALID_BINARY, ValidateInstructions());
+ EXPECT_THAT(getDiagnosticString(),
+ HasSubstr("Number of OpTypeStruct members (16384) has exceeded "
+ "the limit (16383)."));
+}
+