Validation for number of Struct members.
authorEhsan Nasiri <ehsann@google.com>
Thu, 24 Nov 2016 20:37:22 +0000 (15:37 -0500)
committerDavid Neto <dneto@google.com>
Wed, 30 Nov 2016 20:29:37 +0000 (15:29 -0500)
The number of members in a struct may not exceed 16,383.
Also Adding unit tests for Struct size limit check.

source/validate_instruction.cpp
test/val/val_limits_test.cpp

index 976980e..b9f3f2e 100644 (file)
@@ -142,6 +142,20 @@ spv_result_t LimitCheckIdBound(ValidationState_t& _,
   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);
@@ -183,6 +197,7 @@ spv_result_t InstructionPass(ValidationState_t& _,
 
   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;
index 97bca1d..4ebb9f5 100644 (file)
@@ -76,3 +76,30 @@ TEST_F(ValidateLimits, idEqualToBoundBad) {
       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)."));
+}
+