Fix stack overflow when parsing huge expressions.

The expression limit validation check needs to be in front
of other tree traversal to prevent stack overflows. Also,
call depths of sufficient size (80k+) could overflow the
depth check itself, necessitating an upper bound on initial
tree traversal.

This fixes crashes in the WebGL long-expressions bug test.

BUG=angle:584

Change-Id: Ib48294bf77a5923d230f237fbd63a36a5662e317
Reviewed-on: https://chromium-review.googlesource.com/191931
Reviewed-by: Zhenyao Mo <zmo@chromium.org>
Reviewed-by: Nicolas Capens <nicolascapens@chromium.org>
Tested-by: Jamie Madill <jmadill@chromium.org>
diff --git a/src/compiler/translator/Compiler.cpp b/src/compiler/translator/Compiler.cpp
index a42ef62..36b313e 100644
--- a/src/compiler/translator/Compiler.cpp
+++ b/src/compiler/translator/Compiler.cpp
@@ -180,6 +180,10 @@
         TIntermNode* root = parseContext.treeRoot;
         success = intermediate.postProcess(root);
 
+        // Disallow expressions deemed too complex.
+        if (success && (compileOptions & SH_LIMIT_EXPRESSION_COMPLEXITY))
+            success = limitExpressionComplexity(root);
+
         if (success)
             success = detectCallDepth(root, infoSink, (compileOptions & SH_LIMIT_CALL_STACK_DEPTH) != 0);
 
@@ -221,10 +225,6 @@
         if (success && (compileOptions & SH_CLAMP_INDIRECT_ARRAY_BOUNDS))
             arrayBoundsClamper.MarkIndirectArrayBoundsForClamping(root);
 
-        // Disallow expressions deemed too complex.
-        if (success && (compileOptions & SH_LIMIT_EXPRESSION_COMPLEXITY))
-            success = limitExpressionComplexity(root);
-
         if (success && shaderType == SH_VERTEX_SHADER && (compileOptions & SH_INIT_GL_POSITION))
             initializeGLPosition(root);
 
@@ -413,8 +413,15 @@
 
 bool TCompiler::limitExpressionComplexity(TIntermNode* root)
 {
-    TIntermTraverser traverser;
+    TMaxDepthTraverser traverser(maxExpressionComplexity+1);
     root->traverse(&traverser);
+
+    if (traverser.getMaxDepth() > maxExpressionComplexity)
+    {
+        infoSink.info << "Expression too complex.";
+        return false;
+    }
+
     TDependencyGraph graph(root);
 
     for (TFunctionCallVector::const_iterator iter = graph.beginUserDefinedFunctionCalls();
@@ -426,11 +433,6 @@
         samplerSymbol->traverse(&graphTraverser);
     }
 
-    if (traverser.getMaxDepth() > maxExpressionComplexity)
-    {
-        infoSink.info << "Expression too complex.";
-        return false;
-    }
     return true;
 }