[tint] Add limit for array constructors

Set a hard limit of 32767, which is the largest (2^n - 1) that doesn't
cause operand count overflow in SPIR-V.

Bug: 366067963
Change-Id: I54e8f61d3c4111cb02082d5cb663b3c4e8d19690
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/206914
Commit-Queue: James Price <jrprice@google.com>
Commit-Queue: dan sinclair <dsinclair@chromium.org>
Auto-Submit: James Price <jrprice@google.com>
Reviewed-by: dan sinclair <dsinclair@chromium.org>
diff --git a/src/tint/lang/wgsl/resolver/validator.cc b/src/tint/lang/wgsl/resolver/validator.cc
index dda482a..e5bb5bb 100644
--- a/src/tint/lang/wgsl/resolver/validator.cc
+++ b/src/tint/lang/wgsl/resolver/validator.cc
@@ -99,6 +99,7 @@
 namespace tint::resolver {
 namespace {
 
+constexpr size_t kMaxArrayConstructorElements = 32767;
 constexpr size_t kMaxFunctionParameters = 255;
 constexpr size_t kMaxSwitchCaseSelectors = 16383;
 constexpr size_t kMaxClipDistancesSize = 8;
@@ -2205,6 +2206,11 @@
                                << count << ", found " << values.Length();
         return false;
     }
+    if (values.Length() > kMaxArrayConstructorElements) {
+        AddError(ctor->target->source) << "array constructor has excessive number of elements (>"
+                                       << kMaxArrayConstructorElements << ")";
+        return false;
+    }
     return true;
 }
 
diff --git a/src/tint/lang/wgsl/resolver/value_constructor_validation_test.cc b/src/tint/lang/wgsl/resolver/value_constructor_validation_test.cc
index 36fb57e..d6c0c5b 100644
--- a/src/tint/lang/wgsl/resolver/value_constructor_validation_test.cc
+++ b/src/tint/lang/wgsl/resolver/value_constructor_validation_test.cc
@@ -882,6 +882,21 @@
               "found 5");
 }
 
+TEST_F(ResolverValueConstructorValidationTest, Array_ExcessiveNumberOfElements) {
+    // array<i32, 40000u>(0i, 2i, 3i, ..., 39999i);
+    SetSource(Source::Location({12, 34}));
+    Vector<const ast::IntLiteralExpression*, 40000> elements;
+    for (uint32_t i = 0; i < 40000; i++) {
+        elements.Push(Expr(i32(i)));
+    }
+    auto* tc = Call<array<i32, 40000>>(std::move(elements));
+    WrapInFunction(tc);
+
+    EXPECT_FALSE(r()->Resolve());
+    EXPECT_EQ(r()->error(),
+              "12:34 error: array constructor has excessive number of elements (>32767)");
+}
+
 TEST_F(ResolverValueConstructorValidationTest, Array_Runtime) {
     // array<i32>(1i);
     auto* tc = Call<array<i32>>(Source{{12, 34}}, Expr(1_i));