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/intermediate.h b/src/compiler/translator/intermediate.h
index b09fc9e..7c72099 100644
--- a/src/compiler/translator/intermediate.h
+++ b/src/compiler/translator/intermediate.h
@@ -664,4 +664,30 @@
     TVector<TIntermNode *> path;
 };
 
+//
+// For traversing the tree, and computing max depth.
+// Takes a maximum depth limit to prevent stack overflow.
+//
+class TMaxDepthTraverser : public TIntermTraverser
+{
+public:
+    POOL_ALLOCATOR_NEW_DELETE();
+    TMaxDepthTraverser(int depthLimit)
+      : TIntermTraverser(true, true, false, false),
+        depthLimit(depthLimit)
+    {}
+
+    virtual bool visitBinary(Visit visit, TIntermBinary*) { return depthCheck(); }
+    virtual bool visitUnary(Visit visit, TIntermUnary*) { return depthCheck(); }
+    virtual bool visitSelection(Visit visit, TIntermSelection*) { return depthCheck(); }
+    virtual bool visitAggregate(Visit visit, TIntermAggregate*) { return depthCheck(); }
+    virtual bool visitLoop(Visit visit, TIntermLoop*) { return depthCheck(); }
+    virtual bool visitBranch(Visit visit, TIntermBranch*) { return depthCheck(); }
+
+protected:
+    int depthLimit;
+
+    bool depthCheck() const { return maxDepth < depthLimit; }
+};
+
 #endif // __INTERMEDIATE_H