translator: Fix validation sometimes modifying builtins.

When validating some shaders with out-of-bounds array indexes,
we would write the sanitized index into the global symbol table.
We would then overwrite a wrong value for the builtin. This
fixes the WebGL test extensions/webgl-draw-buffers-max-draw-buffers.

Also mark const on as many uses ConstantUnion as we can.

BUG=angleproject:993

Change-Id: I110efaf1b7b0158b08b704277e3bc2472437902c
Reviewed-on: https://chromium-review.googlesource.com/268962
Tested-by: Jamie Madill <jmadill@chromium.org>
Reviewed-by: Kenneth Russell <kbr@chromium.org>
Reviewed-by: Zhenyao Mo <zmo@chromium.org>
diff --git a/src/compiler/translator/ParseContext.cpp b/src/compiler/translator/ParseContext.cpp
index eb9328c..cd7ffc4 100644
--- a/src/compiler/translator/ParseContext.cpp
+++ b/src/compiler/translator/ParseContext.cpp
@@ -1814,7 +1814,7 @@
     TIntermTyped* typedNode;
     TIntermConstantUnion* tempConstantNode = node->getAsConstantUnion();
 
-    TConstantUnion *unionArray;
+    const TConstantUnion *unionArray;
     if (tempConstantNode) {
         unionArray = tempConstantNode->getUnionArrayPointer();
 
@@ -1868,7 +1868,7 @@
     }
 
     if (tempConstantNode) {
-         TConstantUnion* unionArray = tempConstantNode->getUnionArrayPointer();
+         TConstantUnion *unionArray = tempConstantNode->getUnionArrayPointer();
          int size = tempConstantNode->getType().getCols();
          typedNode = intermediate.addConstantUnion(&unionArray[size*index], tempConstantNode->getType(), line);
     } else {
@@ -2202,6 +2202,8 @@
         }
         else
         {
+            int safeIndex = -1;
+
             if (baseExpression->isArray())
             {
                 if (index >= baseExpression->getType().getArraySize())
@@ -2211,13 +2213,13 @@
                     std::string extraInfo = extraInfoStream.str();
                     error(location, "", "[", extraInfo.c_str());
                     recover();
-                    index = baseExpression->getType().getArraySize() - 1;
+                    safeIndex = baseExpression->getType().getArraySize() - 1;
                 }
                 else if (baseExpression->getQualifier() == EvqFragData && index > 0 && !isExtensionEnabled("GL_EXT_draw_buffers"))
                 {
                     error(location, "", "[", "array indexes for gl_FragData must be zero when GL_EXT_draw_buffers is disabled");
                     recover();
-                    index = 0;
+                    safeIndex = 0;
                 }
             }
             else if ((baseExpression->isVector() || baseExpression->isMatrix()) && baseExpression->getType().getNominalSize() <= index)
@@ -2227,10 +2229,18 @@
                 std::string extraInfo = extraInfoStream.str();
                 error(location, "", "[", extraInfo.c_str());
                 recover();
-                index = baseExpression->getType().getNominalSize() - 1;
+                safeIndex = baseExpression->getType().getNominalSize() - 1;
             }
 
-            indexConstantUnion->getUnionArrayPointer()->setIConst(index);
+            // Don't modify the data of the previous constant union, because it can point
+            // to builtins, like gl_MaxDrawBuffers. Instead use a new sanitized object.
+            if (safeIndex != -1)
+            {
+                TConstantUnion *safeConstantUnion = new TConstantUnion();
+                safeConstantUnion->setIConst(safeIndex);
+                indexConstantUnion->replaceConstantUnion(safeConstantUnion);
+            }
+
             indexedExpression = intermediate.addIndex(EOpIndexDirect, baseExpression, indexExpression, location);
         }
     }