Move validation from IndexDataManager to the API.

This validates all necessary buffer sizes for element array
buffers in the validation layer, before we start the draw.

BUG=angle:571

Change-Id: I602744ca1ea493e9f0f7e1ccbeb85fc4ae5c9f5a
Reviewed-on: https://chromium-review.googlesource.com/210648
Tested-by: Jamie Madill <jmadill@chromium.org>
Reviewed-by: Geoff Lang <geofflang@chromium.org>
diff --git a/src/libGLESv2/Buffer.h b/src/libGLESv2/Buffer.h
index b363c11..c39d7d7 100644
--- a/src/libGLESv2/Buffer.h
+++ b/src/libGLESv2/Buffer.h
@@ -58,7 +58,7 @@
     rx::BufferImpl *mBuffer;
 
     GLenum mUsage;
-    GLsizeiptr mSize;
+    GLint64 mSize;
     GLint mAccessFlags;
     GLboolean mMapped;
     GLvoid *mMapPointer;
diff --git a/src/libGLESv2/renderer/d3d/IndexDataManager.cpp b/src/libGLESv2/renderer/d3d/IndexDataManager.cpp
index ce46b3d..868ce8a 100644
--- a/src/libGLESv2/renderer/d3d/IndexDataManager.cpp
+++ b/src/libGLESv2/renderer/d3d/IndexDataManager.cpp
@@ -125,17 +125,7 @@
           default: UNREACHABLE(); alignedOffset = false;
         }
 
-        // check for integer overflows
-        if (static_cast<unsigned int>(count) > (std::numeric_limits<unsigned int>::max() / typeInfo.bytes) ||
-            typeInfo.bytes * static_cast<unsigned int>(count) + offset < offset)
-        {
-            return GL_OUT_OF_MEMORY;
-        }
-
-        if (typeInfo.bytes * static_cast<unsigned int>(count) + offset > storage->getSize())
-        {
-            return GL_INVALID_OPERATION;
-        }
+        ASSERT(typeInfo.bytes * static_cast<unsigned int>(count) + offset <= storage->getSize());
 
         indices = static_cast<const GLubyte*>(storage->getData()) + offset;
     }
@@ -197,11 +187,7 @@
             }
         }
 
-        if (!indexBuffer)
-        {
-            ERR("No valid index buffer.");
-            return GL_INVALID_OPERATION;
-        }
+        ASSERT(indexBuffer);
 
         if (convertCount > std::numeric_limits<unsigned int>::max() / destTypeInfo.bytes)
         {
diff --git a/src/libGLESv2/validationES.cpp b/src/libGLESv2/validationES.cpp
index 4b9ff1c..8225df9 100644
--- a/src/libGLESv2/validationES.cpp
+++ b/src/libGLESv2/validationES.cpp
@@ -1489,6 +1489,32 @@
         return gl::error(GL_INVALID_OPERATION, false);
     }
 
+    if (elementArrayBuffer)
+    {
+        const gl::Type &typeInfo = gl::GetTypeInfo(type);
+
+        GLint64 offset = reinterpret_cast<GLint64>(indices);
+        GLint64 byteCount = static_cast<GLint64>(typeInfo.bytes) * static_cast<GLint64>(count)+offset;
+
+        // check for integer overflows
+        if (static_cast<GLuint>(count) > (std::numeric_limits<GLuint>::max() / typeInfo.bytes) ||
+            byteCount > static_cast<GLint64>(std::numeric_limits<GLuint>::max()))
+        {
+            return gl::error(GL_OUT_OF_MEMORY, false);
+        }
+
+        // Check for reading past the end of the bound buffer object
+        if (byteCount > elementArrayBuffer->getSize())
+        {
+            return gl::error(GL_INVALID_OPERATION, false);
+        }
+    }
+    else if (!indices)
+    {
+        // Catch this programming error here
+        return gl::error(GL_INVALID_OPERATION, false);
+    }
+
     // Use max index to validate if our vertex buffers are large enough for the pull.
     // TODO: offer fast path, with disabled index validation.
     // TODO: also disable index checking on back-ends that are robust to out-of-range accesses.