void RegisterSampledImageConsumer(uint32_t sampled_image_id,
uint32_t cons_id);
+ /// Returns the number of Global Variables
+ uint32_t num_global_vars() { return num_global_vars_; }
+
+ /// Returns the number of Local Variables
+ uint32_t num_local_vars() { return num_local_vars_; }
+
+ /// Increments the number of Global Variables
+ void incrementNumGlobalVars() { ++num_global_vars_; }
+
+ /// Increments the number of Local Variables
+ void incrementNumLocalVars() { ++num_local_vars_; }
+
private:
ValidationState_t(const ValidationState_t&);
/// ID Bound from the Header
uint32_t id_bound_;
+ /// Number of Global Variables (Storage Class other than 'Function')
+ uint32_t num_global_vars_;
+
+ /// Number of Local Variables ('Function' Storage Class)
+ uint32_t num_local_vars_;
+
AssemblyGrammar grammar_;
SpvAddressingModel addressing_model_;
return SPV_SUCCESS;
}
+// Ensure the number of variables of the given class does not exceed the limit.
+spv_result_t LimitCheckNumVars(ValidationState_t& _,
+ const SpvStorageClass storage_class) {
+ if (SpvStorageClassFunction == storage_class) {
+ _.incrementNumLocalVars();
+ const uint32_t num_local_vars_limit = 0x7FFFF;
+ if (_.num_local_vars() > num_local_vars_limit) {
+ return _.diag(SPV_ERROR_INVALID_BINARY)
+ << "Number of local variables ('Function' Storage Class) "
+ "exceeded the valid limit ("
+ << num_local_vars_limit << ").";
+ }
+ } else {
+ _.incrementNumGlobalVars();
+ const uint32_t num_global_vars_limit = 0xFFFF;
+ if (_.num_global_vars() > num_global_vars_limit) {
+ return _.diag(SPV_ERROR_INVALID_BINARY)
+ << "Number of Global Variables (Storage Class other than "
+ "'Function') exceeded the valid limit ("
+ << num_global_vars_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 (opcode == SpvOpVariable) {
const auto storage_class =
static_cast<SpvStorageClass>(inst->words[inst->operands[2].offset]);
+ if (auto error = LimitCheckNumVars(_, storage_class)) {
+ return error;
+ }
if (storage_class == SpvStorageClassGeneric)
return _.diag(SPV_ERROR_INVALID_BINARY)
<< "OpVariable storage class cannot be Generic";
HasSubstr("OpTypeFunction may not take more than 255 arguments. "
"OpTypeFunction <id> '2' has 256 arguments."));
}
+
+// Valid: module has 65,535 global variables.
+TEST_F(ValidateLimits, NumGlobalVarsGood) {
+ int num_globals = 65535;
+ std::ostringstream spirv;
+ spirv << header << R"(
+ %int = OpTypeInt 32 0
+%_ptr_int = OpTypePointer Input %int
+ )";
+
+ for (int i = 0; i < num_globals; ++i) {
+ spirv << "%var_" << i << " = OpVariable %_ptr_int Input\n";
+ }
+
+ CompileSuccessfully(spirv.str());
+ EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
+}
+
+// Invalid: module has 65,536 global variables (limit is 65,535).
+TEST_F(ValidateLimits, NumGlobalVarsBad) {
+ int num_globals = 65536;
+ std::ostringstream spirv;
+ spirv << header << R"(
+ %int = OpTypeInt 32 0
+%_ptr_int = OpTypePointer Input %int
+ )";
+
+ for (int i = 0; i < num_globals; ++i) {
+ spirv << "%var_" << i << " = OpVariable %_ptr_int Input\n";
+ }
+
+ CompileSuccessfully(spirv.str());
+ EXPECT_EQ(SPV_ERROR_INVALID_BINARY, ValidateInstructions());
+ EXPECT_THAT(getDiagnosticString(),
+ HasSubstr("Number of Global Variables (Storage Class other than "
+ "'Function') exceeded the valid limit (65535)."));
+}
+
+// Valid: module has 524,287 local variables.
+TEST_F(ValidateLimits, NumLocalVarsGood) {
+ int num_locals = 524287;
+ std::ostringstream spirv;
+ spirv << header << R"(
+ %int = OpTypeInt 32 0
+ %_ptr_int = OpTypePointer Function %int
+ %voidt = OpTypeVoid
+ %funct = OpTypeFunction %voidt
+ %main = OpFunction %voidt None %funct
+ %entry = OpLabel
+ )";
+
+ for (int i = 0; i < num_locals; ++i) {
+ spirv << "%var_" << i << " = OpVariable %_ptr_int Function\n";
+ }
+
+ spirv << R"(
+ OpReturn
+ OpFunctionEnd
+ )";
+
+ CompileSuccessfully(spirv.str());
+ EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
+}
+
+// Invalid: module has 524,288 local variables (limit is 524,287).
+TEST_F(ValidateLimits, NumLocalVarsBad) {
+ int num_locals = 524288;
+ std::ostringstream spirv;
+ spirv << header << R"(
+ %int = OpTypeInt 32 0
+ %_ptr_int = OpTypePointer Function %int
+ %voidt = OpTypeVoid
+ %funct = OpTypeFunction %voidt
+ %main = OpFunction %voidt None %funct
+ %entry = OpLabel
+ )";
+
+ for (int i = 0; i < num_locals; ++i) {
+ spirv << "%var_" << i << " = OpVariable %_ptr_int Function\n";
+ }
+
+ spirv << R"(
+ OpReturn
+ OpFunctionEnd
+ )";
+
+ CompileSuccessfully(spirv.str());
+ EXPECT_EQ(SPV_ERROR_INVALID_BINARY, ValidateInstructions());
+ EXPECT_THAT(getDiagnosticString(),
+ HasSubstr("Number of local variables ('Function' Storage Class) "
+ "exceeded the valid limit (524287)."));
+}
+