Restrict the size of shader arrays.

This prevents overflow issues in the HLSL translator and some drivers. The
limit it hard-coded to 65536 to be larger than the Shader Model 5 register
limit (4096) to account for register allocation optimizations and future
hardware.

BUG=379799

Change-Id: I20f05c9dd230fbfc1c92af52533cd2b50f2ff994
Reviewed-on: https://chromium-review.googlesource.com/202939
Reviewed-by: Jamie Madill <jmadill@chromium.org>
Reviewed-by: Shannon Woods <shannonwoods@chromium.org>
Tested-by: Nicolas Capens <nicolascapens@chromium.org>
diff --git a/src/compiler/translator/ParseContext.cpp b/src/compiler/translator/ParseContext.cpp
index eac8f2c..f900966 100644
--- a/src/compiler/translator/ParseContext.cpp
+++ b/src/compiler/translator/ParseContext.cpp
@@ -701,28 +701,44 @@
         return true;
     }
 
+    unsigned int unsignedSize = 0;
+
     if (constant->getBasicType() == EbtUInt)
     {
-        unsigned int uintSize = constant->getUConst(0);
-        if (uintSize > static_cast<unsigned int>(std::numeric_limits<int>::max()))
-        {
-            error(line, "array size too large", "");
-            size = 1;
-            return true;
-        }
-
-        size = static_cast<int>(uintSize);
+        unsignedSize = constant->getUConst(0);
+        size = static_cast<int>(unsignedSize);
     }
     else
     {
         size = constant->getIConst(0);
 
-        if (size <= 0)
+        if (size < 0)
         {
-            error(line, "array size must be a positive integer", "");
+            error(line, "array size must be non-negative", "");
             size = 1;
             return true;
         }
+
+        unsignedSize = static_cast<unsigned int>(size);
+    }
+
+    if (size == 0)
+    {
+        error(line, "array size must be greater than zero", "");
+        size = 1;
+        return true;
+    }
+
+    // The size of arrays is restricted here to prevent issues further down the
+    // compiler/translator/driver stack. Shader Model 5 generation hardware is limited to
+    // 4096 registers so this should be reasonable even for aggressively optimizable code.
+    const unsigned int sizeLimit = 65536;
+
+    if (unsignedSize > sizeLimit)
+    {
+        error(line, "array size too large", "");
+        size = 1;
+        return true;
     }
 
     return false;