Validate the number of arguments in OpTypeFunction
authorEhsan Nasiri <ehsann@google.com>
Mon, 28 Nov 2016 18:04:32 +0000 (13:04 -0500)
committerDavid Neto <dneto@google.com>
Thu, 1 Dec 2016 20:49:31 +0000 (15:49 -0500)
According to the SPIR-V spec (section 2.17: Universal Limits), the
OpTypeFunction instruction may not take more than 255 arguments for the
function. Also added unit tests for it.

source/validate_id.cpp
test/val/val_limits_test.cpp

index a486362..9e4d942 100644 (file)
@@ -411,8 +411,9 @@ bool idUsage::isValid<SpvOpTypeFunction>(const spv_instruction_t* inst,
                           << inst->words[returnTypeIndex] << "' is not a type.";
     return false;
   }
+  size_t num_args = 0;
   for (size_t paramTypeIndex = 3; paramTypeIndex < inst->words.size();
-       ++paramTypeIndex) {
+       ++paramTypeIndex, ++num_args) {
     auto paramType = module_.FindDef(inst->words[paramTypeIndex]);
     if (!paramType || !spvOpcodeGeneratesType(paramType->opcode())) {
       DIAG(paramTypeIndex) << "OpTypeFunction Parameter Type <id> '"
@@ -420,6 +421,13 @@ bool idUsage::isValid<SpvOpTypeFunction>(const spv_instruction_t* inst,
       return false;
     }
   }
+  if (num_args > 255) {
+    DIAG(returnTypeIndex) << "OpTypeFunction may not take more than 255 "
+                             "arguments. OpTypeFunction <id> '"
+                          << inst->words[1] << "' has " << num_args
+                          << " arguments.";
+    return false;
+  }
   return true;
 }
 
@@ -746,8 +754,7 @@ bool idUsage::isValid<SpvOpSampledImage>(const spv_instruction_t* inst,
   // to OpPhi instructions or OpSelect instructions, or any instructions other
   // than the image lookup and query instructions specified to take an operand
   // whose type is OpTypeSampledImage.
-  std::vector<uint32_t> consumers =
-      module_.getSampledImageConsumers(resultID);
+  std::vector<uint32_t> consumers = module_.getSampledImageConsumers(resultID);
   if (!consumers.empty()) {
     for (auto consumer_id : consumers) {
       auto consumer_instr = module_.FindDef(consumer_id);
index 5188ca3..0d34259 100644 (file)
@@ -162,3 +162,35 @@ OpFunctionEnd
                         "exceeds the limit (16383)."));
 }
 
+// Valid: OpTypeFunction with 255 arguments.
+TEST_F(ValidateLimits, OpTypeFunctionGood) {
+  int num_args = 255;
+  std::ostringstream spirv;
+  spirv << header << R"(
+%1 = OpTypeInt 32 0
+%2 = OpTypeFunction %1)";
+  // add parameters
+  for (int i = 0; i < num_args; ++i) {
+    spirv << " %1";
+  }
+  CompileSuccessfully(spirv.str());
+  EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
+}
+
+// Invalid: OpTypeFunction with 256 arguments. (limit is 255 according to the
+// spec Universal Limits (2.17).
+TEST_F(ValidateLimits, OpTypeFunctionBad) {
+  int num_args = 256;
+  std::ostringstream spirv;
+  spirv << header << R"(
+%1 = OpTypeInt 32 0
+%2 = OpTypeFunction %1)";
+  for (int i = 0; i < num_args; ++i) {
+    spirv << " %1";
+  }
+  CompileSuccessfully(spirv.str());
+  EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
+  EXPECT_THAT(getDiagnosticString(),
+              HasSubstr("OpTypeFunction may not take more than 255 arguments. "
+                        "OpTypeFunction <id> '2' has 256 arguments."));
+}